flacky 0.9.0 → 1.0.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.
- data/bin/flacky +2 -0
- data/flacky.gemspec +3 -1
- data/lib/flacky/cli.rb +22 -5
- data/lib/flacky/flac_metadata_importer.rb +50 -0
- data/lib/flacky/flac_tagger.rb +49 -0
- data/lib/flacky/metadata_generator.rb +34 -10
- data/lib/flacky/mp3_convertor.rb +64 -20
- data/lib/flacky/mp3_tagger.rb +79 -0
- data/lib/flacky/version.rb +1 -1
- data/spec/fixtures/silence.flac +0 -0
- data/spec/flacky/flac_tagger_spec.rb +99 -0
- metadata +9 -7
- data/lib/flacky/tagger.rb +0 -27
- data/spec/flacky/tagger_spec.rb +0 -67
data/bin/flacky
CHANGED
data/flacky.gemspec
CHANGED
@@ -17,9 +17,11 @@ Gem::Specification.new do |gem|
|
|
17
17
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
18
|
gem.require_paths = ["lib"]
|
19
19
|
|
20
|
+
gem.required_ruby_version = ">= 1.9.3"
|
21
|
+
|
20
22
|
gem.add_dependency 'thor'
|
21
23
|
gem.add_dependency 'nokogiri'
|
22
|
-
gem.add_dependency '
|
24
|
+
gem.add_dependency 'taglib-ruby'
|
23
25
|
|
24
26
|
gem.add_development_dependency 'minitest'
|
25
27
|
gem.add_development_dependency 'vcr'
|
data/lib/flacky/cli.rb
CHANGED
@@ -5,6 +5,7 @@ require 'json'
|
|
5
5
|
require 'thor'
|
6
6
|
|
7
7
|
require 'flacky'
|
8
|
+
require 'flacky/flac_metadata_importer'
|
8
9
|
require 'flacky/metadata_generator'
|
9
10
|
require 'flacky/mp3_convertor'
|
10
11
|
|
@@ -14,8 +15,8 @@ module Flacky
|
|
14
15
|
|
15
16
|
include Thor::Actions
|
16
17
|
|
17
|
-
desc "
|
18
|
-
def
|
18
|
+
desc "generate_json <root_path>", "Generate and populate metadata as JSON"
|
19
|
+
def generate_json(root_dir = ENV['PWD'])
|
19
20
|
start_dir = File.join(File.expand_path(root_dir), '**/*.flac')
|
20
21
|
Dir.glob(start_dir).map { |f| File.dirname(f) }.uniq.each do |dir|
|
21
22
|
mdf = File.join(dir, "metadata.json")
|
@@ -25,6 +26,11 @@ module Flacky
|
|
25
26
|
end
|
26
27
|
end
|
27
28
|
|
29
|
+
desc "import_json [file ...]|[**/*.flac ...]", "Import metadata JSON into Flac files"
|
30
|
+
def import_json(*args)
|
31
|
+
args.each { |glob| import_metadata_for_files(glob) }
|
32
|
+
end
|
33
|
+
|
28
34
|
desc "missing_urls <root_path>", "List all metadata files with missing URLs"
|
29
35
|
method_option :print0, :aliases => "-0", :type => :boolean
|
30
36
|
def missing_urls(root_dir = ENV['PWD'])
|
@@ -43,14 +49,14 @@ module Flacky
|
|
43
49
|
end
|
44
50
|
end
|
45
51
|
|
46
|
-
desc "to_mp3 [file ...]|[**/*.flac ...]", "Convert Flac files to MP3 files"
|
52
|
+
desc "to_mp3 [file ...]|[**/*.flac ...] [options]", "Convert Flac files to MP3 files"
|
47
53
|
method_option :destination, :aliases => "-d",
|
48
54
|
:desc => "Sets optional destination directory"
|
49
55
|
method_option :'lame-opts', :aliases => "-l",
|
50
|
-
:default => "--vbr-new -V 0 -b 320",
|
56
|
+
:default => "--vbr-new --verbose -V 0 -b 320",
|
51
57
|
:desc => "Set the lame encoding arguments"
|
52
58
|
def to_mp3(*args)
|
53
|
-
%w{flac
|
59
|
+
%w{flac lame}.each do |cmd|
|
54
60
|
abort "Command #{cmd} must be on your PATH" unless %x{which #{cmd}}
|
55
61
|
end
|
56
62
|
|
@@ -75,6 +81,17 @@ module Flacky
|
|
75
81
|
end
|
76
82
|
end
|
77
83
|
|
84
|
+
def import_metadata_for_files(glob)
|
85
|
+
Dir.glob(glob).each do |file|
|
86
|
+
next unless file =~ /\.flac$/
|
87
|
+
|
88
|
+
say("Processing #{file}...", :cyan)
|
89
|
+
response = Flacky::FlacMetadataImporter.new(file).import!
|
90
|
+
say("Imported #{response.metadata_filename} into #{file} " +
|
91
|
+
"#{duration(response.elapsed)}", :yellow)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
78
95
|
def duration(total)
|
79
96
|
minutes = (total / 60).to_i
|
80
97
|
seconds = (total - (minutes * 60))
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'flacky/flac_tagger'
|
4
|
+
|
5
|
+
module Flacky
|
6
|
+
|
7
|
+
class FlacMetadataImporter
|
8
|
+
|
9
|
+
def initialize(file)
|
10
|
+
@file = file
|
11
|
+
end
|
12
|
+
|
13
|
+
def import!
|
14
|
+
return Resonse.new(nil, 0) if ! File.exists?(metadata_file)
|
15
|
+
|
16
|
+
md = JSON.parse(IO.read(metadata_file))
|
17
|
+
|
18
|
+
elapsed = Benchmark.measure do
|
19
|
+
FlacTagger.update(@file) do
|
20
|
+
trackn_good = self["TRACKNUMBER"] && self["TRACKNUMBER"].to_i > 0
|
21
|
+
discn_good = self["DISCNUMBER"] && self["DISCNUMBER"].to_i > 0
|
22
|
+
md_good = md["flac"] && md["flac"]["totaltracks"] \
|
23
|
+
&& md["flac"]["totaltracks"].is_a?(Array)
|
24
|
+
totaltracks = md["flac"]["totaltracks"][self["DISCNUMBER"].to_i - 1]
|
25
|
+
|
26
|
+
%w{artist album genre style mood fileowner}.each do |t|
|
27
|
+
tag(t, md["flac"][t]) if md["flac"] && md["flac"][t]
|
28
|
+
end
|
29
|
+
|
30
|
+
tag "DATE", md["flac"]["year"] if md["flac"]["year"]
|
31
|
+
|
32
|
+
if trackn_good && discn_good && md_good
|
33
|
+
tag('TOTALTRACKS', totaltracks.to_s)
|
34
|
+
tag('TOTALDISCS', md["flac"]["totaltracks"].size.to_s)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
Response.new(metadata_file, elapsed.real)
|
40
|
+
end
|
41
|
+
|
42
|
+
Response = Struct.new(:metadata_filename, :elapsed)
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def metadata_file
|
47
|
+
@metadata_file ||= File.join(File.dirname(@file), "metadata.json")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'taglib'
|
4
|
+
|
5
|
+
module Flacky
|
6
|
+
class FlacTagger
|
7
|
+
|
8
|
+
def self.update(file, &block)
|
9
|
+
instance = self.new(file)
|
10
|
+
instance.instance_eval(&block)
|
11
|
+
instance.update!
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(file)
|
15
|
+
@taglib = TagLib::FLAC::File.new(file)
|
16
|
+
@tag = @taglib.xiph_comment
|
17
|
+
end
|
18
|
+
|
19
|
+
def [](attr)
|
20
|
+
result = @tag.field_list_map[attr]
|
21
|
+
|
22
|
+
if result.nil?
|
23
|
+
nil
|
24
|
+
elsif result.is_a?(Array) && result.size == 1
|
25
|
+
result.first
|
26
|
+
else
|
27
|
+
result
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def find(attr)
|
32
|
+
key = @tag.field_list_map.keys.find { |key| key =~ /#{attr}/i }
|
33
|
+
key ? self[key] : nil
|
34
|
+
end
|
35
|
+
|
36
|
+
def tag(name, value)
|
37
|
+
@tag.add_field(name.to_s.upcase, value, true)
|
38
|
+
end
|
39
|
+
|
40
|
+
def cleanup
|
41
|
+
@taglib.close
|
42
|
+
end
|
43
|
+
|
44
|
+
def update!
|
45
|
+
@taglib.save
|
46
|
+
cleanup
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# -*- encoding: UTF-8 -*-
|
2
2
|
|
3
|
-
require '
|
3
|
+
require 'taglib'
|
4
4
|
|
5
5
|
require 'flacky/core_ext'
|
6
6
|
require 'flacky/scraper'
|
@@ -19,16 +19,23 @@ module Flacky
|
|
19
19
|
flacs = Dir.glob(File.join(dir, '*.flac'))
|
20
20
|
return Hash.new if flacs.empty?
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
22
|
+
result = Hash.new
|
23
|
+
result["totaltracks"] = []
|
24
|
+
|
25
|
+
flacs.each do |flac|
|
26
|
+
md = read_flac_metadata(flac)
|
27
|
+
track_total = (md["totaltracks"] || -1).to_i
|
28
|
+
disc_number = (md["discnumber"] || -1).to_i
|
29
|
+
|
30
|
+
next if track_total < 0 || disc_number < 0
|
31
|
+
next if result["totaltracks"][disc_number - 1]
|
32
|
+
|
33
|
+
result["totaltracks"][disc_number - 1] = track_total
|
34
|
+
|
35
|
+
common_tags.each { |t| result[t] = md[t] if md[t] }
|
27
36
|
end
|
37
|
+
result["year"] = result.delete("date") if result["date"]
|
28
38
|
|
29
|
-
info.each_pair { |k,v| v.force_encoding('UTF-8') if v.is_a? String }
|
30
|
-
result = Hash.new
|
31
|
-
common_tags.each { |t| result[t] = info[t] }
|
32
39
|
result
|
33
40
|
end
|
34
41
|
|
@@ -55,7 +62,24 @@ module Flacky
|
|
55
62
|
end
|
56
63
|
|
57
64
|
def common_tags
|
58
|
-
%w[
|
65
|
+
%w[artist album date year genre style mood fileowner].freeze
|
66
|
+
end
|
67
|
+
|
68
|
+
def read_flac_metadata(flac)
|
69
|
+
info = TagLib::FLAC::File.open(flac) do |file|
|
70
|
+
file.xiph_comment.field_list_map
|
71
|
+
end
|
72
|
+
|
73
|
+
info.each_pair do |k, v|
|
74
|
+
value = Array(v).first
|
75
|
+
value.force_encoding('UTF-8') if v.is_a? String
|
76
|
+
info[k] = value
|
77
|
+
end
|
78
|
+
info.keys.each do |key|
|
79
|
+
info[key.downcase] = info.delete(key)
|
80
|
+
end
|
81
|
+
|
82
|
+
info
|
59
83
|
end
|
60
84
|
end
|
61
85
|
end
|
data/lib/flacky/mp3_convertor.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
|
3
|
+
require 'flacky/flac_tagger'
|
4
|
+
require 'flacky/mp3_tagger'
|
5
|
+
|
3
6
|
module Flacky
|
4
7
|
|
5
8
|
class Mp3Convertor
|
@@ -9,19 +12,16 @@ module Flacky
|
|
9
12
|
@dest_root = opts[:dest_root]
|
10
13
|
end
|
11
14
|
|
12
|
-
def convert_file!(
|
13
|
-
|
14
|
-
if dest_root
|
15
|
-
dst = File.join(dest_root, dst)
|
16
|
-
FileUtils.mkdir_p File.dirname(dst)
|
17
|
-
end
|
15
|
+
def convert_file!(flac_file)
|
16
|
+
mp3_file = calculate_mp3_filename(flac_file)
|
18
17
|
|
19
|
-
|
20
|
-
|
21
|
-
|
18
|
+
elapsed = Benchmark.measure do
|
19
|
+
FileUtils.mkdir_p File.dirname(mp3_file)
|
20
|
+
transcode_file(flac_file, mp3_file)
|
21
|
+
tag_file(flac_file, mp3_file)
|
22
|
+
end
|
22
23
|
|
23
|
-
elapsed
|
24
|
-
Response.new(dst, elapsed.real)
|
24
|
+
Response.new(mp3_file, elapsed.real)
|
25
25
|
end
|
26
26
|
|
27
27
|
Response = Struct.new(:mp3_filename, :elapsed)
|
@@ -30,18 +30,62 @@ module Flacky
|
|
30
30
|
|
31
31
|
attr_reader :lame_opts, :dest_root
|
32
32
|
|
33
|
-
def
|
34
|
-
|
35
|
-
|
33
|
+
def calculate_mp3_filename(flac_file)
|
34
|
+
mp3_file = flac_file.sub(/\.flac$/, ".mp3")
|
35
|
+
mp3_file = File.join(dest_root, mp3_file) if dest_root
|
36
|
+
File.expand_path(mp3_file)
|
37
|
+
end
|
38
|
+
|
39
|
+
def transcode_file(flac_file, mp3_file)
|
40
|
+
%x{flac -dcs "#{flac_file}" | lame #{lame_opts} - "#{mp3_file}"}
|
41
|
+
end
|
42
|
+
|
43
|
+
def tag_file(flac_file, mp3_file)
|
44
|
+
flac_tags = Flacky::FlacTagger.new(flac_file)
|
45
|
+
track = track_tag(flac_tags)
|
46
|
+
disc = disc_tag(flac_tags)
|
47
|
+
comment = comment_tag(flac_tags)
|
48
|
+
|
49
|
+
Flacky::Mp3Tagger.update(mp3_file) do
|
50
|
+
tag "album", flac_tags.find(:album)
|
51
|
+
tag "artist", flac_tags.find(:artist)
|
52
|
+
tag "title", flac_tags.find(:title)
|
53
|
+
tag "year", flac_tags.find(:date).to_i
|
54
|
+
tag "genre", flac_tags.find(:genre)
|
55
|
+
tag "track", track
|
56
|
+
tag "disc", disc
|
57
|
+
tag "comment", comment
|
58
|
+
end
|
59
|
+
|
60
|
+
flac_tags.cleanup
|
36
61
|
end
|
37
62
|
|
38
|
-
def
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
63
|
+
def track_tag(flac_tags)
|
64
|
+
track_number = flac_tags.find(:tracknumber) || "0"
|
65
|
+
track_total = flac_tags.find(:totaltracks) || "1"
|
66
|
+
|
67
|
+
"#{track_number}/#{track_total}"
|
68
|
+
end
|
69
|
+
|
70
|
+
def disc_tag(flac_tags)
|
71
|
+
disc_number = flac_tags.find(:discnumber) || "0"
|
72
|
+
disc_total = flac_tags.find(:totaldiscs) || "1"
|
73
|
+
|
74
|
+
"#{disc_number}/#{disc_total}"
|
75
|
+
end
|
76
|
+
|
77
|
+
def comment_tag(flac_tags)
|
78
|
+
comment = []
|
79
|
+
if owner = flac_tags.find(:fileowner)
|
80
|
+
comment << "o=#{owner}"
|
81
|
+
end
|
82
|
+
(flac_tags.find(:style) || "").split(';').each do |style|
|
83
|
+
comment << "s=#{style}"
|
84
|
+
end
|
85
|
+
(flac_tags.find(:mood) || "").split(';').each do |mood|
|
86
|
+
comment << "m=#{mood}"
|
44
87
|
end
|
88
|
+
comment.join("\n")
|
45
89
|
end
|
46
90
|
end
|
47
91
|
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'taglib'
|
4
|
+
|
5
|
+
module Flacky
|
6
|
+
class Mp3Tagger
|
7
|
+
|
8
|
+
def self.update(file, &block)
|
9
|
+
instance = self.new(file)
|
10
|
+
instance.instance_eval(&block)
|
11
|
+
instance.update!
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(file)
|
15
|
+
@taglib = TagLib::MPEG::File.new(file)
|
16
|
+
@tag = @taglib.id3v2_tag
|
17
|
+
end
|
18
|
+
|
19
|
+
def [](attr)
|
20
|
+
result = @tag.field_list_map[attr]
|
21
|
+
|
22
|
+
if result.nil?
|
23
|
+
nil
|
24
|
+
elsif result.is_a?(Array) && result.size == 1
|
25
|
+
result.first
|
26
|
+
else
|
27
|
+
result
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def find(attr)
|
32
|
+
key = @tag.field_list_map.keys.find { |key| key =~ /#{attr}/i }
|
33
|
+
key ? self[key] : nil
|
34
|
+
end
|
35
|
+
|
36
|
+
def tag(name, value)
|
37
|
+
if TAGS.include?(name.to_sym)
|
38
|
+
@tag.public_send("#{name}=", value)
|
39
|
+
elsif name =~ /track/i
|
40
|
+
@tag.add_frame(new_text_frame("TRCK", value))
|
41
|
+
elsif name =~ /disc/i
|
42
|
+
@tag.add_frame(new_text_frame("TPOS", value))
|
43
|
+
elsif name =~ /comment/i
|
44
|
+
@tag.add_frame(new_comment_frame(value))
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def cleanup
|
49
|
+
@taglib.close
|
50
|
+
end
|
51
|
+
|
52
|
+
def update!
|
53
|
+
@taglib.save
|
54
|
+
cleanup
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
TAGS = [:album, :artist, :title, :year, :genre].freeze
|
60
|
+
|
61
|
+
def encoding
|
62
|
+
TagLib::String::Latin1
|
63
|
+
end
|
64
|
+
|
65
|
+
def new_text_frame(type, value)
|
66
|
+
frame = TagLib::ID3v2::TextIdentificationFrame.new(type, encoding)
|
67
|
+
frame.text = value
|
68
|
+
frame
|
69
|
+
end
|
70
|
+
|
71
|
+
def new_comment_frame(value)
|
72
|
+
frame = TagLib::ID3v2::CommentsFrame.new
|
73
|
+
frame.text_encoding = encoding
|
74
|
+
frame.language = "eng"
|
75
|
+
frame.text = value
|
76
|
+
frame
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
data/lib/flacky/version.rb
CHANGED
data/spec/fixtures/silence.flac
CHANGED
Binary file
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require 'mocha/setup'
|
5
|
+
require 'flacky/flac_tagger'
|
6
|
+
|
7
|
+
describe Flacky::FlacTagger do
|
8
|
+
|
9
|
+
let(:flac_file) do
|
10
|
+
File.join(File.dirname(__FILE__), '../fixtures/silence.flac')
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:tagger) do
|
14
|
+
Flacky::FlacTagger.new(flac_file)
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "when writing tags" do
|
18
|
+
|
19
|
+
let(:tag) do
|
20
|
+
mock('xiph_comment')
|
21
|
+
end
|
22
|
+
|
23
|
+
let(:taglib_flac) do
|
24
|
+
mock = TagLib::FLAC::File.new(flac_file)
|
25
|
+
mock.stubs(:save).returns(true)
|
26
|
+
mock.stubs(:xiph_comment).returns(tag)
|
27
|
+
mock
|
28
|
+
end
|
29
|
+
|
30
|
+
before do
|
31
|
+
taglib_flac
|
32
|
+
TagLib::FLAC::File.stubs(:new).returns(taglib_flac)
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "#tag" do
|
36
|
+
it "sets a tag if none exist" do
|
37
|
+
tag.expects(:add_field).with("DISCNUMBER", "1", true)
|
38
|
+
|
39
|
+
tagger.tag "DISCNUMBER", "1"
|
40
|
+
end
|
41
|
+
|
42
|
+
it "sets a tag if one exists" do
|
43
|
+
tag.expects(:add_field).with("TITLE", "Foopants", true)
|
44
|
+
|
45
|
+
tagger.tag "TITLE", "Foopants"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe ".update" do
|
50
|
+
|
51
|
+
it "add the tag and updates" do
|
52
|
+
tag.expects(:add_field).with("ARTIST", "The MiniTest", true)
|
53
|
+
taglib_flac.expects(:save)
|
54
|
+
taglib_flac.expects(:close).at_least_once
|
55
|
+
|
56
|
+
Flacky::FlacTagger.update(flac_file) do
|
57
|
+
tag "ARTIST", "The MiniTest"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe "when reading" do
|
64
|
+
|
65
|
+
after do
|
66
|
+
tagger.cleanup
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "#find" do
|
70
|
+
|
71
|
+
it "returns nil if attribute isn't found" do
|
72
|
+
tagger.find("haha").must_be_nil
|
73
|
+
end
|
74
|
+
|
75
|
+
it "returns a string if tag value array only has only one element" do
|
76
|
+
tagger.find("GENRE").must_equal "Avantgarde"
|
77
|
+
end
|
78
|
+
|
79
|
+
it "matches case insensitive attribute matches" do
|
80
|
+
tagger.find("artist").must_equal "Fletcher Nichol"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe "#[]" do
|
85
|
+
|
86
|
+
it "returns nil if attribute isn't found" do
|
87
|
+
tagger["nope"].must_be_nil
|
88
|
+
end
|
89
|
+
|
90
|
+
it "returns a string if tag value array only has only one element" do
|
91
|
+
tagger["GENRE"].must_equal "Avantgarde"
|
92
|
+
end
|
93
|
+
|
94
|
+
it "returns and array if tag value has multiple elements" do
|
95
|
+
tagger["MULTIPLE"].must_equal ["One", "Two"]
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flacky
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-02-04 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: thor
|
@@ -44,7 +44,7 @@ dependencies:
|
|
44
44
|
- !ruby/object:Gem::Version
|
45
45
|
version: '0'
|
46
46
|
- !ruby/object:Gem::Dependency
|
47
|
-
name:
|
47
|
+
name: taglib-ruby
|
48
48
|
requirement: !ruby/object:Gem::Requirement
|
49
49
|
none: false
|
50
50
|
requirements:
|
@@ -158,17 +158,19 @@ files:
|
|
158
158
|
- lib/flacky.rb
|
159
159
|
- lib/flacky/cli.rb
|
160
160
|
- lib/flacky/core_ext.rb
|
161
|
+
- lib/flacky/flac_metadata_importer.rb
|
162
|
+
- lib/flacky/flac_tagger.rb
|
161
163
|
- lib/flacky/metadata_generator.rb
|
162
164
|
- lib/flacky/mp3_convertor.rb
|
165
|
+
- lib/flacky/mp3_tagger.rb
|
163
166
|
- lib/flacky/scraper.rb
|
164
|
-
- lib/flacky/tagger.rb
|
165
167
|
- lib/flacky/version.rb
|
166
168
|
- spec/fixtures/silence.flac
|
167
169
|
- spec/fixtures/vcr_cassettes/audioslave_revelations.yml
|
168
170
|
- spec/fixtures/vcr_cassettes/bend_sinister_small_fame.yml
|
169
171
|
- spec/fixtures/vcr_cassettes/rush_moving_pictures.yml
|
172
|
+
- spec/flacky/flac_tagger_spec.rb
|
170
173
|
- spec/flacky/scraper_spec.rb
|
171
|
-
- spec/flacky/tagger_spec.rb
|
172
174
|
homepage: https://github.com/fnichol/flacky
|
173
175
|
licenses: []
|
174
176
|
post_install_message:
|
@@ -180,7 +182,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
180
182
|
requirements:
|
181
183
|
- - ! '>='
|
182
184
|
- !ruby/object:Gem::Version
|
183
|
-
version:
|
185
|
+
version: 1.9.3
|
184
186
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
185
187
|
none: false
|
186
188
|
requirements:
|
@@ -198,5 +200,5 @@ test_files:
|
|
198
200
|
- spec/fixtures/vcr_cassettes/audioslave_revelations.yml
|
199
201
|
- spec/fixtures/vcr_cassettes/bend_sinister_small_fame.yml
|
200
202
|
- spec/fixtures/vcr_cassettes/rush_moving_pictures.yml
|
203
|
+
- spec/flacky/flac_tagger_spec.rb
|
201
204
|
- spec/flacky/scraper_spec.rb
|
202
|
-
- spec/flacky/tagger_spec.rb
|
data/lib/flacky/tagger.rb
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
|
3
|
-
require 'flacinfo'
|
4
|
-
|
5
|
-
module Flacky
|
6
|
-
class Tagger
|
7
|
-
def self.update(flac_file, &block)
|
8
|
-
instance = self.new(flac_file)
|
9
|
-
instance.instance_eval(&block)
|
10
|
-
instance.update!
|
11
|
-
end
|
12
|
-
|
13
|
-
def initialize(flac_file)
|
14
|
-
@flac_file = flac_file
|
15
|
-
@flac = FlacInfo.new(@flac_file)
|
16
|
-
end
|
17
|
-
|
18
|
-
def tag(name, value)
|
19
|
-
@flac.comment_del(name) if @flac.tags.keys.include?(name)
|
20
|
-
@flac.comment_add("#{name}=#{value}")
|
21
|
-
end
|
22
|
-
|
23
|
-
def update!()
|
24
|
-
@flac.update!
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
data/spec/flacky/tagger_spec.rb
DELETED
@@ -1,67 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
|
3
|
-
require 'minitest/autorun'
|
4
|
-
require 'mocha/setup'
|
5
|
-
require 'flacky/tagger'
|
6
|
-
|
7
|
-
describe Flacky::Tagger do
|
8
|
-
let(:flac_file) do
|
9
|
-
File.join(File.dirname(__FILE__), '../fixtures/silence.flac')
|
10
|
-
end
|
11
|
-
|
12
|
-
let(:tagger) do
|
13
|
-
Flacky::Tagger.new(flac_file)
|
14
|
-
end
|
15
|
-
|
16
|
-
let(:flacinfo) do
|
17
|
-
mock = FlacInfo.new(flac_file)
|
18
|
-
mock.stubs(:tags).returns({ 'Title' => 'Silence' })
|
19
|
-
mock.stubs(:update!).returns(true)
|
20
|
-
mock
|
21
|
-
end
|
22
|
-
|
23
|
-
describe "#tag" do
|
24
|
-
it "adds a new comment tag if none exist" do
|
25
|
-
flacinfo.expects(:comment_add).with('DISCNUMBER=1').returns(true)
|
26
|
-
FlacInfo.stubs(:new).returns(flacinfo)
|
27
|
-
|
28
|
-
tagger.tag "DISCNUMBER", "1"
|
29
|
-
end
|
30
|
-
|
31
|
-
it "overwrites a comment tag if one exists" do
|
32
|
-
flacinfo.expects(:comment_del).with('Title').returns(true)
|
33
|
-
flacinfo.expects(:comment_add).with('Title=Le Silence').returns(true)
|
34
|
-
FlacInfo.stubs(:new).returns(flacinfo)
|
35
|
-
|
36
|
-
tagger.tag "Title", "Le Silence"
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
describe "#update!" do
|
41
|
-
it "calls update! on the FlacInfo object" do
|
42
|
-
flacinfo.expects(:update!).returns(true)
|
43
|
-
FlacInfo.stubs(:new).returns(flacinfo)
|
44
|
-
|
45
|
-
tagger.update!
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
describe ".update" do
|
50
|
-
it "adds the tag and updates" do
|
51
|
-
flacinfo.expects(:comment_add).with('DISCNUMBER=1').returns(true)
|
52
|
-
flacinfo.expects(:update!).returns(true)
|
53
|
-
FlacInfo.stubs(:new).returns(flacinfo)
|
54
|
-
|
55
|
-
Flacky::Tagger.update(flac_file) do
|
56
|
-
tag "DISCNUMBER", "1"
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
# it "does stuff" do
|
62
|
-
# Flacky::Tagger.update('file') do
|
63
|
-
# tag 'MOOD', "yep"
|
64
|
-
# tag 'FILEOWNER', "fletcher"
|
65
|
-
# end
|
66
|
-
# end
|
67
|
-
end
|