unitf-tag 0.1.25 → 0.2.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.
- checksums.yaml +4 -4
- data/.gitignore +0 -2
- data/.vscode/tasks.json +10 -2
- data/CHANGELOG.md +7 -0
- data/bin/test.rb +3 -19
- data/docs/taglib.md +47 -0
- data/exe/tag +13 -6
- data/lib/unitf/tag/auto_tags.rb +62 -0
- data/lib/unitf/tag/file.rb +57 -109
- data/lib/unitf/tag/mp3.rb +4 -0
- data/lib/unitf/tag/version.rb +1 -1
- data/lib/unitf/tag.rb +1 -1
- data/test-data/Foo/Bar/.autotag +2 -0
- data/test-data/Foo/Bar/2025/qq250916.mp3 +0 -0
- data/test-data/Test Artist/Test Album/04 - Test Song.mp3 +0 -0
- data/test-data/WFMU/BJ/2025/bj250915.mp3 +0 -0
- data/test-data/cover.jpg +0 -0
- data/test-data/song.mp3 +0 -0
- data/unitf-tag.gemspec +3 -2
- metadata +25 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0e8a3abd8e593009ee730ed4ee98c85f9f0b5665cdccf7ac1ea68b0f29e793a6
|
4
|
+
data.tar.gz: 2b62f8700524ba32f9961b14c129869a98b4e0fbf304c05173f9e059820d8bb3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d5a1dd21d9cddb72642a99e8d0f1274f6e95a3fc76e80d9bb71838c6addc201814ac3dd0ff1d38482af6464ab37eddd5cd643d70240bf7fdf5fba80866d9c156
|
7
|
+
data.tar.gz: 6e7d036234644964322c41dd0dcc4d8e9982c76c6abc4dd430c28a88431f635194da76826c153dcd249b6c0e4a0d26c2e2892b74f75f8063d7ece32fdb99cca7
|
data/.gitignore
CHANGED
data/.vscode/tasks.json
CHANGED
@@ -16,10 +16,18 @@
|
|
16
16
|
"presentation": {
|
17
17
|
"clear": true
|
18
18
|
},
|
19
|
-
"command": "bundle exec
|
19
|
+
"command": "bundle exec ruby bin/test.rb"
|
20
20
|
},
|
21
21
|
{
|
22
|
-
"label": "test
|
22
|
+
"label": "tag-test",
|
23
|
+
"type": "shell",
|
24
|
+
"options": {
|
25
|
+
"cwd": "${workspaceFolder}",
|
26
|
+
},
|
27
|
+
"command": "bundle exec ruby exe/tag --auto_tag '/Users/mbaron/music2/Dinosaur Jr/Little Fury Things'"
|
28
|
+
},
|
29
|
+
{
|
30
|
+
"label": "rspec",
|
23
31
|
"type": "shell",
|
24
32
|
"presentation": {
|
25
33
|
"clear": true
|
data/CHANGELOG.md
CHANGED
data/bin/test.rb
CHANGED
@@ -4,23 +4,7 @@ require 'unitf/tag'
|
|
4
4
|
|
5
5
|
UnitF::Log.to_console
|
6
6
|
|
7
|
-
UnitF::Tag.update('test-data/
|
8
|
-
|
9
|
-
file.tag.
|
10
|
-
file.tag.album = 'This is the album'
|
11
|
-
file.tag.title = 'This is the title'
|
12
|
-
file.tag.track = 99
|
13
|
-
file.auto_cover!
|
14
|
-
end
|
15
|
-
|
16
|
-
file = UnitF::Tag::File.new('test-data/bar.mp3')
|
17
|
-
# file.tag
|
18
|
-
|
19
|
-
file.update do |f|
|
20
|
-
f.tag.title = 'Hello world2!'
|
21
|
-
f.tag.track = 100
|
22
|
-
end
|
23
|
-
|
24
|
-
file.open do |f|
|
25
|
-
f.tag.title = 'Hello world9!'
|
7
|
+
UnitF::Tag.update('test-data/song.mp3') do |file|
|
8
|
+
puts "FILE: #{file}"
|
9
|
+
file.tag.artist = "Update #{Time.now.to_s}"
|
26
10
|
end
|
data/docs/taglib.md
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# taglib Notes
|
2
|
+
Notes on `taglib` and `taglib-ruby` issues
|
3
|
+
|
4
|
+
**GitHub**
|
5
|
+
- https://github.com/taglib/taglib
|
6
|
+
- https://github.com/robinst/taglib-ruby
|
7
|
+
|
8
|
+
## Custom TagLib 1.13.1 Build on MacOS
|
9
|
+
```
|
10
|
+
curl -O https://taglib.org/releases/taglib-1.13.1.tar.gz
|
11
|
+
tar xvf taglib-1.13.1.tar.gz
|
12
|
+
cd taglib-1.13.1
|
13
|
+
cmake -DCMAKE_INSTALL_PREFIX=/usr/local/taglib1 -DCMAKE_BUILD_TYPE=Release .
|
14
|
+
make
|
15
|
+
sudo make install
|
16
|
+
```
|
17
|
+
|
18
|
+
```
|
19
|
+
TAGLIB_DIR=/usr/local/taglib1 gem install taglib-ruby --version '< 2'
|
20
|
+
```
|
21
|
+
|
22
|
+
## Custom Build on Linux
|
23
|
+
```
|
24
|
+
git clone https://github.com/taglib/taglib.git
|
25
|
+
cd taglib/
|
26
|
+
git submodule update --init
|
27
|
+
cmake -DCMAKE_INSTALL_PREFIX=/usr/local/taglib -DCMAKE_BUILD_TYPE=Release .
|
28
|
+
make
|
29
|
+
make install
|
30
|
+
```
|
31
|
+
|
32
|
+
```
|
33
|
+
TAGLIB_DIR=/usr/local/taglib gem install taglib-ruby --version '>= 2'
|
34
|
+
```
|
35
|
+
|
36
|
+
### Taglib error w/ taglib 2.0.2
|
37
|
+
```
|
38
|
+
root@homer:/nas/music2/WFMU# gem install /tmp/unitf-tag-0.1.27.gem
|
39
|
+
Successfully installed unitf-tag-0.1.27
|
40
|
+
Parsing documentation for unitf-tag-0.1.27
|
41
|
+
Installing ri documentation for unitf-tag-0.1.27
|
42
|
+
Done installing documentation for unitf-tag after 0 seconds
|
43
|
+
1 gem installed
|
44
|
+
root@homer:/nas/music2/WFMU# tag
|
45
|
+
<internal:/usr/share/rubygems/rubygems/core_ext/kernel_require.rb>:136:in `require': /usr/local/lib64/gems/ruby/taglib-ruby-2.0.0/taglib_base.so: undefined symbol: _ZN6TagLib4File11removeBlockElm - /usr/local/lib64/gems/ruby/taglib-ruby-2.0.0/taglib_base.so (LoadError)
|
46
|
+
from <internal:/usr/share/rubygems/rubygems/core_ext/kernel_require.rb>:136:in `require'
|
47
|
+
```
|
data/exe/tag
CHANGED
@@ -54,6 +54,10 @@ targets = OptionParser.new do |opts|
|
|
54
54
|
actions << :auto_tag
|
55
55
|
end
|
56
56
|
|
57
|
+
opts.on('--auto_tags', 'Auto Tags') do
|
58
|
+
actions << :auto_tags
|
59
|
+
end
|
60
|
+
|
57
61
|
opts.on('-f', '--force', 'Force') do
|
58
62
|
opt[:force] = true
|
59
63
|
end
|
@@ -96,19 +100,22 @@ end
|
|
96
100
|
|
97
101
|
files.each do |file|
|
98
102
|
UnitF::Log.info("Processing file: #{file}")
|
99
|
-
|
100
|
-
|
103
|
+
|
104
|
+
file.update do |f|
|
105
|
+
f.properties!(properties) unless properties.empty?
|
101
106
|
|
102
107
|
actions.each do |action|
|
103
108
|
case action
|
104
109
|
when :cover
|
105
|
-
|
110
|
+
f.cover!(opt[:cover])
|
106
111
|
when :delete_cover
|
107
|
-
|
112
|
+
f.delete_cover!
|
108
113
|
when :auto_cover
|
109
|
-
|
114
|
+
f.auto_cover!
|
110
115
|
when :auto_tag
|
111
|
-
|
116
|
+
f.auto_tag!
|
117
|
+
when :auto_tags
|
118
|
+
puts "\tauto_tags: #{f.auto_tags}\n\n"
|
112
119
|
end
|
113
120
|
end
|
114
121
|
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module UnitF
|
2
|
+
module Tag
|
3
|
+
class AutoTags < Hash
|
4
|
+
def initialize(file_path)
|
5
|
+
super
|
6
|
+
|
7
|
+
@file_path = ::File.realpath(file_path.to_s)
|
8
|
+
@dirname = ::File.dirname(@file_path)
|
9
|
+
|
10
|
+
merge!(from_path)
|
11
|
+
merge!(from_file)
|
12
|
+
end
|
13
|
+
|
14
|
+
def auto_tag_path
|
15
|
+
return @auto_tag_path unless @auto_tag_path.nil?
|
16
|
+
|
17
|
+
["#{@dirname}/.autotag", "#{@dirname}/../.autotag"].each do |path|
|
18
|
+
return @auto_tag_path = path if ::File.exist?(path)
|
19
|
+
end
|
20
|
+
|
21
|
+
nil
|
22
|
+
end
|
23
|
+
|
24
|
+
def from_path
|
25
|
+
tags = {}
|
26
|
+
|
27
|
+
tags[:title] = ::File.basename(@file_path)
|
28
|
+
tags[:track] = tags[:title].match(/^\s*\d+/).to_s.to_i
|
29
|
+
|
30
|
+
# Specific formatting for dated radio
|
31
|
+
if tags[:title].scan(/(\.|_|-)((\d\d\d\d)(\.|-)\d\d(\.|-)\d\d(\w*))\./).any?
|
32
|
+
tags[:title] = ::Regexp.last_match[2]
|
33
|
+
tags[:year] = ::Regexp.last_match[3].to_i
|
34
|
+
else
|
35
|
+
tags[:title].gsub!(/\.\w+$/, '')
|
36
|
+
tags[:title].gsub!(/^\d*\s*(-|\.)*\s*/, '')
|
37
|
+
end
|
38
|
+
|
39
|
+
path_parts = @dirname.to_s.split('/')
|
40
|
+
tags[:artist] = path_parts[-2]
|
41
|
+
tags[:album] = path_parts[-1]
|
42
|
+
|
43
|
+
tags
|
44
|
+
end
|
45
|
+
|
46
|
+
def from_file
|
47
|
+
tags = {}
|
48
|
+
return tags unless ::File.exist?(auto_tag_path)
|
49
|
+
|
50
|
+
::File.read(auto_tag_path).each_line do |line|
|
51
|
+
line.chomp!
|
52
|
+
tag, value = line.split(/\s*=\s*/)
|
53
|
+
tags[tag.strip.to_sym] = value.strip
|
54
|
+
end
|
55
|
+
|
56
|
+
tags
|
57
|
+
rescue StandardError
|
58
|
+
{}
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
data/lib/unitf/tag/file.rb
CHANGED
@@ -6,24 +6,22 @@ require 'json'
|
|
6
6
|
|
7
7
|
module UnitF
|
8
8
|
module Tag
|
9
|
-
class File
|
9
|
+
class File
|
10
|
+
attr_accessor :path, :realpath, :dirname, :extname
|
11
|
+
|
10
12
|
def initialize(file_path)
|
11
|
-
|
12
|
-
end
|
13
|
+
raise Error, "Invalid file #{file_path}" unless ::File.exist?(file_path)
|
13
14
|
|
14
|
-
|
15
|
-
|
15
|
+
@path = ::File.path(file_path.to_s)
|
16
|
+
@realpath = ::File.realpath(path)
|
17
|
+
@dirname = ::File.dirname(path)
|
18
|
+
@extname = ::File.extname(path)
|
16
19
|
|
17
|
-
|
20
|
+
raise Error, "Unknown file type: #{file_path}" unless mp3? || flac?
|
18
21
|
end
|
19
22
|
|
20
|
-
def
|
21
|
-
@
|
22
|
-
end
|
23
|
-
|
24
|
-
def close
|
25
|
-
@file&.close
|
26
|
-
@file = nil
|
23
|
+
def to_s
|
24
|
+
@path
|
27
25
|
end
|
28
26
|
|
29
27
|
def format_json
|
@@ -40,7 +38,7 @@ module UnitF
|
|
40
38
|
|
41
39
|
def info
|
42
40
|
{
|
43
|
-
file: realpath
|
41
|
+
file: realpath,
|
44
42
|
artist: tag.artist,
|
45
43
|
album: tag.album,
|
46
44
|
title: tag.title,
|
@@ -68,12 +66,8 @@ module UnitF
|
|
68
66
|
["#{dirname}/cover.jpg", "#{dirname}/../cover.jpg"].each do |path|
|
69
67
|
return ::File.realpath(path) if ::File.exist?(path)
|
70
68
|
end
|
71
|
-
end
|
72
69
|
|
73
|
-
|
74
|
-
["#{dirname}/.autotag", "#{dirname}/../.autotag"].each do |path|
|
75
|
-
return ::File.realpath(path) if ::File.exist?(path)
|
76
|
-
end
|
70
|
+
nil
|
77
71
|
end
|
78
72
|
|
79
73
|
def mp3?
|
@@ -85,104 +79,34 @@ module UnitF
|
|
85
79
|
end
|
86
80
|
|
87
81
|
def cover_available?
|
88
|
-
cover_path
|
82
|
+
!cover_path.nil?
|
89
83
|
end
|
90
84
|
|
91
85
|
def auto_cover!
|
92
86
|
raise Error, "File is not open #{self.class.name}" if tag.nil?
|
93
87
|
|
94
|
-
cover!(cover_path)
|
88
|
+
cover!(cover_path) if cover_available?
|
95
89
|
true
|
96
90
|
rescue StandardError => e
|
97
91
|
UnitF::Log.error("Failed to auto-cover file #{e}")
|
92
|
+
puts e.backtrace
|
98
93
|
false
|
99
94
|
end
|
100
95
|
|
101
|
-
def
|
102
|
-
UnitF::
|
103
|
-
tags = {}
|
104
|
-
return {} unless ::File.exist?(auto_tag_path)
|
105
|
-
::File.read(auto_tag_path).each_line do |line|
|
106
|
-
line.chomp!
|
107
|
-
UnitF::Log.info(line)
|
108
|
-
tag, value = line.split(/\s*=\s*/)
|
109
|
-
tags[tag.to_sym] = value
|
110
|
-
end
|
111
|
-
tags
|
112
|
-
rescue StandardError
|
113
|
-
{}
|
114
|
-
end
|
115
|
-
|
116
|
-
# def auto_tags
|
117
|
-
# manual_tags = manual_auto_tags
|
118
|
-
# tags = {}
|
119
|
-
|
120
|
-
# tags[:title] = ::File.basename(realpath.to_path)
|
121
|
-
# track = tags[:title].match(/^\s*\d+/).to_s.to_i
|
122
|
-
|
123
|
-
# if tags[:title].scan(/(\.|_|-)(\d\d\d\d(\.|-)\d\d(\.|-)\d\d)/)
|
124
|
-
# tags[:title] = ::Regexp::last_match
|
125
|
-
# else
|
126
|
-
# tags[:title].gsub!(/\.\w+$/, '')
|
127
|
-
# tags[:title].gsub!(/^\d*\s*(-|\.)*\s*/, '')
|
128
|
-
# end
|
129
|
-
|
130
|
-
# path_parts = realpath.dirname.to_path.split('/')
|
131
|
-
# tags[:album] = path_parts[-1]
|
132
|
-
# tags[:artist] = path_parts[-2]
|
133
|
-
|
134
|
-
# tags.merge(manual_auto_tags)
|
135
|
-
# end
|
136
|
-
|
137
|
-
def path_tags
|
138
|
-
tags = {}
|
139
|
-
|
140
|
-
tags[:title] = ::File.basename(realpath.to_path)
|
141
|
-
tags[:track] = tags[:title].match(/^\s*\d+/).to_s.to_i
|
142
|
-
|
143
|
-
# Specific formatting for dated radio
|
144
|
-
if tags[:title].scan(/(\.|_|-)((\d\d\d\d)(\.|-)\d\d(\.|-)\d\d(\w*))\./).any?
|
145
|
-
tags[:title] = ::Regexp.last_match[2]
|
146
|
-
tags[:year] = ::Regexp.last_match[3].to_i
|
147
|
-
else
|
148
|
-
tags[:title].gsub!(/\.\w+$/, '')
|
149
|
-
tags[:title].gsub!(/^\d*\s*(-|\.)*\s*/, '')
|
150
|
-
end
|
151
|
-
|
152
|
-
tags[:artist] = path_parts[-2]
|
153
|
-
tags[:album] = tags[:album_artist] = path_parts[-1]
|
96
|
+
def auto_tags
|
97
|
+
@auto_tags ||= UnitF::Tag::AutoTags.new(path)
|
154
98
|
end
|
155
99
|
|
156
100
|
def auto_tag!
|
157
101
|
UnitF::Log.info("Auto tagging #{self}")
|
102
|
+
UnitF::Log.info(auto_tags)
|
158
103
|
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
track = title.match(/^\s*\d+/).to_s.to_i
|
166
|
-
|
167
|
-
# Specific formatting for dated radio
|
168
|
-
if title.scan(/(\.|_|-)((\d\d\d\d)(\.|-)\d\d(\.|-)\d\d(\w*))\./).any?
|
169
|
-
title = ::Regexp.last_match[2]
|
170
|
-
album = path_parts[-1]
|
171
|
-
year = ::Regexp.last_match[3].to_i
|
172
|
-
else
|
173
|
-
title.gsub!(/\.\w+$/, '')
|
174
|
-
title.gsub!(/^\d*\s*(-|\.)*\s*/, '')
|
175
|
-
album = path_parts[-1]
|
176
|
-
end
|
177
|
-
|
178
|
-
artist = path_parts[-2]
|
179
|
-
|
180
|
-
tag.year = year unless year.nil?
|
181
|
-
tag.album = album
|
182
|
-
tag.artist = artist
|
183
|
-
tag.title = title
|
184
|
-
tag.track = track if track.positive?
|
185
|
-
self.album_artist = artist
|
104
|
+
tag.album = auto_tags[:album]
|
105
|
+
tag.artist = auto_tags[:artist]
|
106
|
+
tag.title = auto_tags[:title]
|
107
|
+
tag.track = auto_tags[:track] if auto_tags.key?(:track)
|
108
|
+
tag.year = auto_tags[:year] if auto_tags.key?(:year)
|
109
|
+
self.album_artist = auto_tags[:artist]
|
186
110
|
end
|
187
111
|
|
188
112
|
def properties!(properties)
|
@@ -193,21 +117,45 @@ module UnitF
|
|
193
117
|
end
|
194
118
|
|
195
119
|
def update
|
196
|
-
open
|
197
|
-
|
120
|
+
open do |file|
|
121
|
+
if block_given?
|
122
|
+
yield(file)
|
123
|
+
file.save || (raise Error, "Failed to save file #{file}")
|
124
|
+
end
|
198
125
|
end
|
199
126
|
end
|
200
127
|
|
201
|
-
def open
|
128
|
+
def open
|
202
129
|
file = if flac?
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
130
|
+
UnitF::Tag::FLAC.new(path)
|
131
|
+
elsif mp3?
|
132
|
+
UnitF::Tag::MP3.new(path)
|
133
|
+
end
|
207
134
|
yield(file) if block_given?
|
208
|
-
file.save if auto_save
|
209
135
|
file.close
|
210
136
|
end
|
137
|
+
|
138
|
+
#
|
139
|
+
# Methods that use @file, which comes from child classes
|
140
|
+
#
|
141
|
+
def tag
|
142
|
+
raise Error, "File is not open #{self.class.name}" if @file&.tag.nil?
|
143
|
+
|
144
|
+
@file&.tag
|
145
|
+
end
|
146
|
+
|
147
|
+
def save
|
148
|
+
raise Error, "File is not open #{self.class.name}" if @file&.tag.nil?
|
149
|
+
|
150
|
+
@file&.save
|
151
|
+
end
|
152
|
+
|
153
|
+
def close
|
154
|
+
raise Error, "File is not open #{self.class.name}" if @file&.tag.nil?
|
155
|
+
|
156
|
+
@file&.close
|
157
|
+
@file = nil
|
158
|
+
end
|
211
159
|
end
|
212
160
|
end
|
213
161
|
end
|
data/lib/unitf/tag/mp3.rb
CHANGED
@@ -23,6 +23,10 @@ module UnitF
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def cover!(file_path)
|
26
|
+
return unless ::File.exist?(file_path.to_s)
|
27
|
+
|
28
|
+
delete_cover! if cover?
|
29
|
+
|
26
30
|
UnitF::Log.info("Setting cover #{file_path}")
|
27
31
|
apic = TagLib::ID3v2::AttachedPictureFrame.new
|
28
32
|
apic.mime_type = 'image/jpeg'
|
data/lib/unitf/tag/version.rb
CHANGED
data/lib/unitf/tag.rb
CHANGED
@@ -6,6 +6,7 @@ require_relative 'tag/file'
|
|
6
6
|
require_relative 'tag/fileset'
|
7
7
|
require_relative 'tag/flac'
|
8
8
|
require_relative 'tag/mp3'
|
9
|
+
require_relative 'tag/auto_tags'
|
9
10
|
|
10
11
|
require 'unitf/logging'
|
11
12
|
|
@@ -15,7 +16,6 @@ module UnitF
|
|
15
16
|
def update(file_path)
|
16
17
|
UnitF::Tag::File.new(file_path).update do |file|
|
17
18
|
yield file
|
18
|
-
file.save || (raise UnitF::Tag::Error, "Failed to save file #{file_path}")
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
Binary file
|
Binary file
|
Binary file
|
data/test-data/cover.jpg
ADDED
Binary file
|
data/test-data/song.mp3
ADDED
Binary file
|
data/unitf-tag.gemspec
CHANGED
@@ -27,7 +27,8 @@ Gem::Specification.new do |spec|
|
|
27
27
|
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
28
28
|
spec.require_paths = ['lib']
|
29
29
|
|
30
|
-
|
31
|
-
spec.add_dependency 'taglib-ruby'
|
30
|
+
spec.add_dependency 'logger'
|
31
|
+
spec.add_dependency 'taglib-ruby', '1.1.3'
|
32
|
+
# spec.add_dependency 'taglib-ruby', '>= 2.0.0'
|
32
33
|
spec.add_dependency 'unitf-logging'
|
33
34
|
end
|
metadata
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: unitf-tag
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Baron
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-
|
10
|
+
date: 2025-04-04 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
|
-
name:
|
13
|
+
name: logger
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
15
15
|
requirements:
|
16
16
|
- - ">="
|
@@ -23,6 +23,20 @@ dependencies:
|
|
23
23
|
- - ">="
|
24
24
|
- !ruby/object:Gem::Version
|
25
25
|
version: '0'
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: taglib-ruby
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - '='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 1.1.3
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - '='
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: 1.1.3
|
26
40
|
- !ruby/object:Gem::Dependency
|
27
41
|
name: unitf-logging
|
28
42
|
requirement: !ruby/object:Gem::Requirement
|
@@ -57,9 +71,11 @@ files:
|
|
57
71
|
- README.md
|
58
72
|
- Rakefile
|
59
73
|
- bin/test.rb
|
74
|
+
- docs/taglib.md
|
60
75
|
- exe/tag
|
61
76
|
- exe/unitf-autotags
|
62
77
|
- lib/unitf/tag.rb
|
78
|
+
- lib/unitf/tag/auto_tags.rb
|
63
79
|
- lib/unitf/tag/export/exporter.rb
|
64
80
|
- lib/unitf/tag/file.rb
|
65
81
|
- lib/unitf/tag/fileset.rb
|
@@ -67,6 +83,12 @@ files:
|
|
67
83
|
- lib/unitf/tag/helpers.rb
|
68
84
|
- lib/unitf/tag/mp3.rb
|
69
85
|
- lib/unitf/tag/version.rb
|
86
|
+
- test-data/Foo/Bar/.autotag
|
87
|
+
- test-data/Foo/Bar/2025/qq250916.mp3
|
88
|
+
- test-data/Test Artist/Test Album/04 - Test Song.mp3
|
89
|
+
- test-data/WFMU/BJ/2025/bj250915.mp3
|
90
|
+
- test-data/cover.jpg
|
91
|
+
- test-data/song.mp3
|
70
92
|
- unitf-tag.gemspec
|
71
93
|
homepage: https://github.com/mattbaron/unitf-tag
|
72
94
|
licenses:
|