unitf-tag 0.1.0 → 0.1.6
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/.vscode/tasks.json +1 -1
- data/bin/test.rb +6 -3
- data/exe/rtag +25 -24
- data/lib/unitf/tag/export/exporter.rb +18 -0
- data/lib/unitf/tag/file.rb +26 -0
- data/lib/unitf/tag/fileset.rb +28 -0
- data/lib/unitf/tag/flac.rb +8 -0
- data/lib/unitf/tag/mp3.rb +8 -0
- data/lib/unitf/tag/version.rb +1 -1
- data/lib/unitf/tag.rb +30 -2
- data/unitf-tag.gemspec +1 -0
- metadata +19 -4
- data/lib/unitf/version.rb +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3844f8f9883d9584a03a19be4ca9200c7b2203ec5b0f6d7615477d097d430628
|
4
|
+
data.tar.gz: 55e82e675756dbb52721575c888b0e3b7fb1bb2f0a59c9eb8b6557c657c54f2a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eb091d040bab764dda18aded5e23a7ed370f0b3b253a8b4b21b324b22a85b6ac079e6ce8fd530665f84fd9a0b30e454a846f7af64305b1bc601e988266bb4b31
|
7
|
+
data.tar.gz: 90448d8bf47f1973c1639c6fc81f18b258ed24e248f314f37a6d79a119e2e09420b14bede4c2276d6030bfeb7e7ec5f64929d9e51ee24c59ef662e9cccb315d2
|
data/.vscode/tasks.json
CHANGED
data/bin/test.rb
CHANGED
@@ -2,7 +2,10 @@ require 'optparse'
|
|
2
2
|
|
3
3
|
require 'unitf/tag'
|
4
4
|
|
5
|
-
file_str = '/Users/mbaron/tag/music/fIREHOSE3/Sometimes'
|
6
|
-
file = UnitF::Tag::File.new(file_str)
|
5
|
+
file_str = '/Users/mbaron/tag/music/fIREHOSE3/Sometimes/01 - Sometimes.flac'
|
7
6
|
|
8
|
-
|
7
|
+
file = UnitF::Tag::FLAC.new(file_str)
|
8
|
+
|
9
|
+
file.open do |o|
|
10
|
+
pp o.info
|
11
|
+
end
|
data/exe/rtag
CHANGED
@@ -11,32 +11,44 @@ logger = Logger.new($stdout)
|
|
11
11
|
actions = []
|
12
12
|
files = []
|
13
13
|
opt = {
|
14
|
-
:
|
15
|
-
:
|
14
|
+
recursive: false,
|
15
|
+
force: false
|
16
16
|
}
|
17
17
|
|
18
18
|
targets = OptionParser.new do |opts|
|
19
|
-
opts.on('-r', '--recursive', 'Auto Cover') do
|
19
|
+
opts.on('-r', '--recursive', 'Auto Cover') do
|
20
20
|
opt[:recursive] = true
|
21
21
|
end
|
22
22
|
|
23
|
-
opts.on('
|
23
|
+
opts.on('--dump', 'Dump Tags') do
|
24
24
|
opt[:dump] = true
|
25
25
|
end
|
26
26
|
|
27
|
-
opts.on('
|
27
|
+
opts.on('-d', '--debug', 'Debug') do
|
28
|
+
UnitF::Tag.logger.level = Logger::DEBUG
|
29
|
+
end
|
30
|
+
|
31
|
+
opts.on('-j', '--json', 'JSON Output') do
|
32
|
+
opt[:format] = :json
|
33
|
+
end
|
34
|
+
|
35
|
+
opts.on('-l', '--line', 'Single Line Output') do
|
36
|
+
opt[:format] = :line
|
37
|
+
end
|
38
|
+
|
39
|
+
opts.on('--auto_cover', 'Auto Cover') do
|
28
40
|
actions << :auto_cover
|
29
41
|
end
|
30
42
|
|
31
|
-
opts.on('--delete_cover', 'Delete Cover') do
|
43
|
+
opts.on('--delete_cover', 'Delete Cover') do
|
32
44
|
actions << :delete_cover
|
33
45
|
end
|
34
46
|
|
35
|
-
opts.on('--auto_tag', 'Auto Tag') do
|
47
|
+
opts.on('--auto_tag', 'Auto Tag') do
|
36
48
|
actions << :auto_tag
|
37
49
|
end
|
38
50
|
|
39
|
-
opts.on('-f', '--force', 'Force') do
|
51
|
+
opts.on('-f', '--force', 'Force') do
|
40
52
|
opt[:force] = true
|
41
53
|
end
|
42
54
|
|
@@ -61,25 +73,14 @@ targets = OptionParser.new do |opts|
|
|
61
73
|
end
|
62
74
|
end.parse!
|
63
75
|
|
64
|
-
|
65
|
-
files.concat(UnitF::Tag::process_target(target))
|
66
|
-
end
|
67
|
-
|
68
|
-
if files.size.zero? && actions.size.zero?
|
69
|
-
files = UnitF::Tag::find_files('.')
|
70
|
-
end
|
76
|
+
files = UnitF::Tag::FileSet.new(targets)
|
71
77
|
|
72
78
|
if files.size.zero?
|
73
79
|
logger.error('Cannot find any files to operate on')
|
74
80
|
end
|
75
81
|
|
76
82
|
if actions.size.zero?
|
77
|
-
files
|
78
|
-
file.open do |o|
|
79
|
-
o.print unless opt[:dump]
|
80
|
-
o.dump if opt[:dump]
|
81
|
-
end
|
82
|
-
end
|
83
|
+
UnitF::Tag.list(files, format: opt[:format])
|
83
84
|
exit 0
|
84
85
|
end
|
85
86
|
|
@@ -89,7 +90,7 @@ files.each do |file|
|
|
89
90
|
actions.each do |action|
|
90
91
|
case action
|
91
92
|
when :delete_cover
|
92
|
-
logger.info(
|
93
|
+
logger.info('Delete cover')
|
93
94
|
o.delete_cover!
|
94
95
|
when :auto_cover
|
95
96
|
unless o.cover?
|
@@ -101,7 +102,7 @@ files.each do |file|
|
|
101
102
|
end
|
102
103
|
end
|
103
104
|
when :auto_tag
|
104
|
-
logger.info(
|
105
|
+
logger.info('Auto Tag')
|
105
106
|
o.auto_tag!
|
106
107
|
when :artist
|
107
108
|
logger.info("Setting artist to #{opt[:artist]}")
|
@@ -120,6 +121,6 @@ files.each do |file|
|
|
120
121
|
o.tag.genre = opt[:track]
|
121
122
|
end
|
122
123
|
end
|
123
|
-
o.save
|
124
|
+
o.save || logger.error("Unable to save changes to #{file}")
|
124
125
|
end
|
125
126
|
end
|
data/lib/unitf/tag/file.rb
CHANGED
@@ -2,6 +2,7 @@ require 'find'
|
|
2
2
|
require 'taglib'
|
3
3
|
require 'pathname'
|
4
4
|
require 'logger'
|
5
|
+
require 'json'
|
5
6
|
|
6
7
|
module UnitF
|
7
8
|
module Tag
|
@@ -14,6 +15,31 @@ module UnitF
|
|
14
15
|
@file.tag
|
15
16
|
end
|
16
17
|
|
18
|
+
def format_json
|
19
|
+
JSON.pretty_generate(info)
|
20
|
+
end
|
21
|
+
|
22
|
+
def format_line
|
23
|
+
buff = []
|
24
|
+
info.each_key do |key|
|
25
|
+
buff << "#{key}=#{info[key]}"
|
26
|
+
end
|
27
|
+
buff.join(',')
|
28
|
+
end
|
29
|
+
|
30
|
+
def info
|
31
|
+
{
|
32
|
+
file: realpath.to_path,
|
33
|
+
artist: tag.artist,
|
34
|
+
album: tag.album,
|
35
|
+
title: tag.title,
|
36
|
+
track: tag.track,
|
37
|
+
genre: tag.genre,
|
38
|
+
year: tag.year,
|
39
|
+
cover: cover?
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
17
43
|
def print
|
18
44
|
puts "File : #{realpath}"
|
19
45
|
puts "Artist: #{tag.artist}"
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module UnitF
|
2
|
+
module Tag
|
3
|
+
class FileSet < Array
|
4
|
+
def initialize(targets)
|
5
|
+
targets.each do |target|
|
6
|
+
process_target(target)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def process_target(target)
|
11
|
+
if ::File.directory?(target)
|
12
|
+
find_files(target)
|
13
|
+
elsif UnitF::Tag.valid_file?(target)
|
14
|
+
append(UnitF::Tag::File.new(target))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def find_files(root_path)
|
19
|
+
Find.find(root_path) do |file_path|
|
20
|
+
UnitF::Log.debug("Considering #{file_path}")
|
21
|
+
next unless UnitF::Tag.valid_file?(file_path)
|
22
|
+
UnitF::Log.debug("Including #{file_path}")
|
23
|
+
append(UnitF::Tag::File.new(file_path))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/unitf/tag/flac.rb
CHANGED
@@ -6,6 +6,14 @@ module UnitF
|
|
6
6
|
@file = TagLib::FLAC::File.new(file_path)
|
7
7
|
end
|
8
8
|
|
9
|
+
def info
|
10
|
+
super.merge!({
|
11
|
+
stats: stats,
|
12
|
+
sample_rate: @file.audio_properties.sample_rate,
|
13
|
+
bits_per_sample: @file.audio_properties.bits_per_sample
|
14
|
+
})
|
15
|
+
end
|
16
|
+
|
9
17
|
def cover?
|
10
18
|
@file.picture_list.each do |pic|
|
11
19
|
return true if pic.type == TagLib::FLAC::Picture::FrontCover
|
data/lib/unitf/tag/mp3.rb
CHANGED
@@ -10,6 +10,14 @@ module UnitF
|
|
10
10
|
sprintf("%.1fkHz/%dkbps", @file.audio_properties.sample_rate / 1000.to_f, @file.audio_properties.bitrate)
|
11
11
|
end
|
12
12
|
|
13
|
+
def info
|
14
|
+
super.merge!({
|
15
|
+
stats: stats,
|
16
|
+
sample_rate: @file.audio_properties.sample_rate,
|
17
|
+
bitrate: @file.audio_properties.bitrate
|
18
|
+
})
|
19
|
+
end
|
20
|
+
|
13
21
|
def cover?
|
14
22
|
@file.id3v2_tag.frame_list('APIC').size > 0
|
15
23
|
end
|
data/lib/unitf/tag/version.rb
CHANGED
data/lib/unitf/tag.rb
CHANGED
@@ -2,20 +2,30 @@
|
|
2
2
|
|
3
3
|
require_relative 'tag/version'
|
4
4
|
require_relative 'tag/file'
|
5
|
+
require_relative 'tag/fileset'
|
5
6
|
require_relative 'tag/flac'
|
6
7
|
require_relative 'tag/mp3'
|
7
8
|
|
9
|
+
require 'unitf/logging'
|
10
|
+
|
8
11
|
module UnitF
|
9
12
|
module Tag
|
10
13
|
class Error < StandardError; end
|
11
14
|
class MissingCover < Error; end
|
12
15
|
|
13
16
|
def self.logger
|
14
|
-
@logger
|
17
|
+
unless @logger
|
18
|
+
@logger = UnitF::Logging::Logger.new
|
19
|
+
@logger.add_writer(UnitF::Logging::ConsoleWriter.new)
|
20
|
+
end
|
21
|
+
@logger
|
15
22
|
end
|
16
23
|
|
17
24
|
def self.valid_file?(file_path)
|
18
|
-
::File.file?(file_path) && file_path.match(/\.(flac|mp3)$/i)
|
25
|
+
::File.file?(file_path) && file_path.encode.match(/\.(flac|mp3)$/i)
|
26
|
+
rescue ArgumentError => e
|
27
|
+
logger.error("Error processing #{file_path} - #{e.message}")
|
28
|
+
false
|
19
29
|
end
|
20
30
|
|
21
31
|
def self.process_target(target)
|
@@ -31,10 +41,28 @@ module UnitF
|
|
31
41
|
def self.find_files(root_path)
|
32
42
|
files = []
|
33
43
|
Find.find(root_path) do |file_path|
|
44
|
+
logger.debug("Considering #{file_path}")
|
34
45
|
next unless valid_file?(file_path)
|
35
46
|
files << UnitF::Tag::File.new(file_path)
|
36
47
|
end
|
37
48
|
files
|
38
49
|
end
|
50
|
+
|
51
|
+
def self.list(files, format: :json)
|
52
|
+
buff = []
|
53
|
+
files.each do |file|
|
54
|
+
file.open do |o|
|
55
|
+
case format
|
56
|
+
when :json
|
57
|
+
buff << o.info
|
58
|
+
when :line
|
59
|
+
puts o.format_line
|
60
|
+
else
|
61
|
+
o.print
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
puts JSON.pretty_generate(buff) if format == :json
|
66
|
+
end
|
39
67
|
end
|
40
68
|
end
|
data/unitf-tag.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: unitf-tag
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Baron
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-12-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: taglib-ruby
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: unitf-logging
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
27
41
|
description: Audio File Tagging
|
28
42
|
email:
|
29
43
|
- mwb@unitf.net
|
@@ -47,11 +61,12 @@ files:
|
|
47
61
|
- bin/test.rb
|
48
62
|
- exe/rtag
|
49
63
|
- lib/unitf/tag.rb
|
64
|
+
- lib/unitf/tag/export/exporter.rb
|
50
65
|
- lib/unitf/tag/file.rb
|
66
|
+
- lib/unitf/tag/fileset.rb
|
51
67
|
- lib/unitf/tag/flac.rb
|
52
68
|
- lib/unitf/tag/mp3.rb
|
53
69
|
- lib/unitf/tag/version.rb
|
54
|
-
- lib/unitf/version.rb
|
55
70
|
- tag
|
56
71
|
- test.rb
|
57
72
|
- unitf-tag.gemspec
|
@@ -78,7 +93,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
78
93
|
- !ruby/object:Gem::Version
|
79
94
|
version: '0'
|
80
95
|
requirements: []
|
81
|
-
rubygems_version: 3.2.
|
96
|
+
rubygems_version: 3.2.32
|
82
97
|
signing_key:
|
83
98
|
specification_version: 4
|
84
99
|
summary: Audio File Tagging
|