popcap 0.8.0 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +82 -45
- data/lib/pop_cap/audio_file.rb +102 -30
- data/lib/pop_cap/formatted_hash.rb +40 -0
- data/lib/pop_cap/{tag/tag_struct.rb → tag_struct.rb} +10 -0
- data/lib/pop_cap/{tag/tag_hash.rb → unformatted_hash.rb} +5 -3
- data/lib/pop_cap/version.rb +1 -1
- data/spec/lib/pop_cap/audio_file_spec.rb +73 -23
- data/spec/lib/pop_cap/formatted_hash_spec.rb +32 -0
- data/spec/lib/pop_cap/formatter_spec.rb +9 -8
- data/spec/lib/pop_cap/{tag/tag_struct_spec.rb → tag_struct_spec.rb} +16 -3
- data/spec/lib/pop_cap/unformatted_hash_spec.rb +43 -0
- data/spec/support/popcap_spec_helper.rb +2 -20
- metadata +11 -20
- data/lib/pop_cap/tag/formatted_tag.rb +0 -31
- data/lib/pop_cap/taggable.rb +0 -120
- data/spec/integration/convert_audio_file_spec.rb +0 -15
- data/spec/integration/read_metatags_spec.rb +0 -12
- data/spec/integration/update_metatags_spec.rb +0 -20
- data/spec/lib/pop_cap/tag/formatted_tag_spec.rb +0 -29
- data/spec/lib/pop_cap/tag/tag_hash_spec.rb +0 -35
- data/spec/lib/pop_cap/taggable_spec.rb +0 -76
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fe1804b885ed55227148832677e5697bd95d8ca8
|
4
|
+
data.tar.gz: f0d5ac62e3690a6aaaca546a7abc86a218268366
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6c0bd62beca21f4fe86bee66638c69a594deb3418e1b9b12e6c5072dac4930482bc953c4f7404ab71e3fc3fefeb641b906e67d32fb7fa7debffa8d90df35992e
|
7
|
+
data.tar.gz: 7d11a95c9bc6829996d744764006ab049fbc5ac3b67eada66ae779aeb96475df35b71bfdcc07eda01cf9b73796556345258733abfbd4a543132f7ccf1775923e
|
data/README.md
CHANGED
@@ -22,40 +22,71 @@ Read the metadata tags from an audio file.
|
|
22
22
|
```
|
23
23
|
audio_file = PopCap::AudioFile.new('sample.flac')
|
24
24
|
|
25
|
-
audio_file.
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
25
|
+
audio_file.raw_output => Returns JSON for the raw output from
|
26
|
+
running "ffprobe -show_format -print_format json."
|
27
|
+
|
28
|
+
{
|
29
|
+
"format":
|
30
|
+
{
|
31
|
+
"filename":"spec/fixtures/sample.flac",
|
32
|
+
"nb_streams":1,
|
33
|
+
"format_name":"flac",
|
34
|
+
"format_long_name":"raw FLAC",
|
35
|
+
"duration":"1.000000",
|
36
|
+
"size":"18291",
|
37
|
+
"bit_rate":"146328",
|
38
|
+
|
39
|
+
"tags":
|
40
|
+
{
|
41
|
+
"GENRE":"Sample Genre",
|
42
|
+
"track":"01",
|
43
|
+
"ALBUM":"Sample Album",
|
44
|
+
"DATE":"2012",
|
45
|
+
"TITLE":"Sample Title",
|
46
|
+
"ARTIST":"Sample Artist"
|
47
|
+
}
|
48
|
+
}
|
49
|
+
}
|
50
|
+
|
51
|
+
audio_file.unformatted => Returns a Ruby hash after sanitizing
|
52
|
+
the raw output of #raw_output.
|
53
|
+
|
54
|
+
{
|
55
|
+
filename: '$HOME/spec/fixtures/sample.flac',
|
56
|
+
nb_streams: 1,
|
57
|
+
format_name: 'flac',
|
58
|
+
format_long_name: 'raw FLAC',
|
59
|
+
duration: '1.000000',
|
60
|
+
filesize: '18291',
|
61
|
+
bit_rate: '146328',
|
62
|
+
genre: 'Sample Genre',
|
63
|
+
track: '01',
|
64
|
+
album: 'Sample Album',
|
65
|
+
date: '2012',
|
66
|
+
title: 'Sample Title',
|
67
|
+
artist: 'Sample Artist'
|
68
|
+
}
|
69
|
+
|
70
|
+
audio_file.formatted => Returns a Ruby hash after sanitizing
|
71
|
+
the raw output of #raw_output. It also applies internal formatters
|
72
|
+
on fields such as duration, bit_rate, filesize, & date,
|
73
|
+
returning human readable output.
|
74
|
+
|
75
|
+
{
|
76
|
+
filename: '$HOME/spec/fixtures/sample.flac',
|
77
|
+
nb_streams: 1,
|
78
|
+
format_name: 'flac',
|
79
|
+
format_long_name: 'raw FLAC',
|
80
|
+
duration: '1',
|
81
|
+
filesize: '17.9K',
|
82
|
+
bit_rate: '146 kb/s',
|
83
|
+
genre: 'Sample Genre',
|
84
|
+
track: '01',
|
85
|
+
album: 'Sample Album',
|
86
|
+
date: 2012,
|
87
|
+
title: 'Sample Title',
|
88
|
+
artist: 'Sample Artist'
|
89
|
+
}
|
59
90
|
|
60
91
|
audio_file.tags => Returns a tag structure using the #formatted values.
|
61
92
|
|
@@ -64,38 +95,43 @@ audio_file.tags => Returns a tag structure using the #formatted values.
|
|
64
95
|
.bit_rate => '146 kb/s'
|
65
96
|
.date => 2012
|
66
97
|
.duration => '1'
|
67
|
-
.filename => 'spec/fixtures/sample.flac'
|
98
|
+
.filename => ''$HOME/spec/fixtures/sample.flac'
|
68
99
|
.filesize => '17.9K'
|
69
100
|
.format_long_name => 'raw FLAC'
|
70
101
|
.format_name => 'flac'
|
71
102
|
.genre => 'Sample Genre'
|
72
|
-
.nb_streams =>
|
103
|
+
.nb_streams => 1
|
73
104
|
.start_time => 'N/A'
|
74
105
|
.title => 'Sample Title'
|
75
106
|
.track => '01'
|
76
107
|
|
77
|
-
audio_file.reload! => Reload an instance of itself,
|
108
|
+
audio_file.reload! => Reload an instance of itself,
|
109
|
+
useful when updating tags. This behavior is built in,
|
110
|
+
but will need to be called manually in certain situations;
|
111
|
+
(such as moving a file on the file system, deleting a file, etc.)
|
78
112
|
```
|
79
113
|
|
80
114
|
Update Tags
|
81
115
|
-----------
|
82
116
|
|
83
|
-
This will update the metadata tags for an audio file.
|
117
|
+
This will update the metadata tags for an audio file.
|
118
|
+
It will also dynamically add any newly provided tags.
|
119
|
+
It takes a hash of attributes.
|
84
120
|
|
85
121
|
```
|
86
122
|
audio_file = PopCap::AudioFile.new('sample.flac')
|
87
|
-
audio_file.
|
123
|
+
audio_file.update(artist: 'David Bowie')
|
88
124
|
|
89
|
-
audio_file.
|
125
|
+
audio_file.update(fancy_new_tag: 'Custom Tag Input')
|
90
126
|
```
|
91
127
|
|
92
128
|
Convert
|
93
129
|
-------
|
94
130
|
|
95
|
-
This will convert between audio file formats.
|
96
|
-
|
97
|
-
|
98
|
-
|
131
|
+
This will convert between audio file formats.
|
132
|
+
It is restricted to basic audio formats.
|
133
|
+
It also takes an optional bitrate for mp3 formats.
|
134
|
+
The original file is preserved during the conversion.
|
99
135
|
|
100
136
|
```
|
101
137
|
audio_file = PopCap::AudioFile.new('sample.flac')
|
@@ -128,7 +164,8 @@ audio_file.move('destination') # = > moves file to destination
|
|
128
164
|
|
129
165
|
audio_file.rename('new_name.flac') # => renames file
|
130
166
|
|
131
|
-
audio_file.restore # => restores file from backup_path
|
167
|
+
audio_file.restore # => restores file from backup_path;
|
168
|
+
takes an optional path
|
132
169
|
|
133
170
|
audio_file.tmppath # => returns the temporary path, e.g. '/tmp/sample.flac'
|
134
171
|
```
|
data/lib/pop_cap/audio_file.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
require 'pop_cap/ffmpeg/converter'
|
2
2
|
require 'pop_cap/ffmpeg/tag_reader'
|
3
3
|
require 'pop_cap/ffmpeg/tag_writer'
|
4
|
+
require 'pop_cap/unformatted_hash'
|
5
|
+
require 'pop_cap/formatted_hash'
|
6
|
+
require 'pop_cap/tag_struct'
|
4
7
|
require 'pop_cap/fileable'
|
5
|
-
require 'pop_cap/taggable'
|
6
8
|
|
7
9
|
module PopCap
|
8
10
|
FileNotFound = Class.new(StandardError)
|
@@ -17,10 +19,10 @@ module PopCap
|
|
17
19
|
#
|
18
20
|
#
|
19
21
|
class AudioFile
|
22
|
+
include Fileable
|
20
23
|
attr_accessor :filepath
|
21
24
|
|
22
|
-
|
23
|
-
include Taggable
|
25
|
+
::MEMOIZABLES = %w(@raw @unformatted_hash @formatted_hash @tag_struct)
|
24
26
|
|
25
27
|
# Public: Initialize
|
26
28
|
#
|
@@ -43,8 +45,8 @@ module PopCap
|
|
43
45
|
# audio_file.convert('mp3', 128)
|
44
46
|
# # => 'spec/fixtures/sample.mp3'
|
45
47
|
#
|
46
|
-
def convert(format, bitrate=192)
|
47
|
-
|
48
|
+
def convert(format, bitrate=192, converter: Converter)
|
49
|
+
converter.convert(filepath, {format: format, bitrate: bitrate})
|
48
50
|
end
|
49
51
|
|
50
52
|
# Public: raw_tags
|
@@ -54,25 +56,96 @@ module PopCap
|
|
54
56
|
# audio_file = AudioFile.new('spec/fixtures/sample.flac')
|
55
57
|
# audio_file.raw_tags
|
56
58
|
# # =>
|
57
|
-
#
|
58
|
-
#
|
59
|
-
#
|
60
|
-
#
|
61
|
-
#
|
62
|
-
#
|
63
|
-
#
|
64
|
-
#
|
65
|
-
#
|
66
|
-
#
|
67
|
-
#
|
68
|
-
#
|
69
|
-
#
|
70
|
-
#
|
71
|
-
#
|
72
|
-
#
|
73
|
-
#
|
74
|
-
|
75
|
-
|
59
|
+
#
|
60
|
+
# {
|
61
|
+
# "format":
|
62
|
+
# {
|
63
|
+
# "filename":"spec/fixtures/sample.flac",
|
64
|
+
# "nb_streams":1,
|
65
|
+
# "format_name":"flac",
|
66
|
+
# "format_long_name":"raw FLAC",
|
67
|
+
# "duration":"1.000000",
|
68
|
+
# "size":"18291",
|
69
|
+
# "bit_rate":"146328",
|
70
|
+
# "tags":
|
71
|
+
# {
|
72
|
+
# "GENRE":"Sample Genre",
|
73
|
+
# "track":"01",
|
74
|
+
# "ALBUM":"Sample Album",
|
75
|
+
# "DATE":"2012",
|
76
|
+
# "TITLE":"Sample Title",
|
77
|
+
# "ARTIST":"Sample Artist"
|
78
|
+
# }
|
79
|
+
# }
|
80
|
+
# }
|
81
|
+
#
|
82
|
+
def raw_output(tag_reader: TagReader)
|
83
|
+
@raw ||= tag_reader.read(filepath)
|
84
|
+
end
|
85
|
+
|
86
|
+
# Public: This method returns a sanitized version of #raw_tags.
|
87
|
+
#
|
88
|
+
# {
|
89
|
+
# filename: '$HOME/spec/fixtures/sample.flac',
|
90
|
+
# nb_streams: 1,
|
91
|
+
# format_name: 'flac',
|
92
|
+
# format_long_name: 'raw FLAC',
|
93
|
+
# duration: '1.000000',
|
94
|
+
# filesize: '18291',
|
95
|
+
# bit_rate: '146328',
|
96
|
+
# genre: 'Sample Genre',
|
97
|
+
# track: '01',
|
98
|
+
# album: 'Sample Album',
|
99
|
+
# date: '2012',
|
100
|
+
# title: 'Sample Title',
|
101
|
+
# artist: 'Sample Artist'
|
102
|
+
# }
|
103
|
+
#
|
104
|
+
def unformatted(unformatted_hash: UnformattedHash)
|
105
|
+
@unformatted_hash ||= unformatted_hash.hash(raw_output)
|
106
|
+
end
|
107
|
+
|
108
|
+
# Public: This method returns #unformatted tags with
|
109
|
+
# any available Formatters automatically applied.
|
110
|
+
#
|
111
|
+
# {
|
112
|
+
# filename: '$HOME/spec/fixtures/sample.flac',
|
113
|
+
# nb_streams: 1,
|
114
|
+
# format_name: 'flac',
|
115
|
+
# format_long_name: 'raw FLAC',
|
116
|
+
# duration: '1',
|
117
|
+
# filesize: '17.9K',
|
118
|
+
# bit_rate: '146 kb/s',
|
119
|
+
# genre: 'Sample Genre',
|
120
|
+
# track: '01',
|
121
|
+
# album: 'Sample Album',
|
122
|
+
# date: 2012,
|
123
|
+
# title: 'Sample Title',
|
124
|
+
# artist: 'Sample Artist'
|
125
|
+
# }
|
126
|
+
def formatted(formatted_hash: FormattedHash)
|
127
|
+
@formatted_hash ||= formatted_hash.formatted(unformatted)
|
128
|
+
end
|
129
|
+
|
130
|
+
# Public: This method builds a tag structure from #formatted.
|
131
|
+
#
|
132
|
+
# .album => 'Sample Album'
|
133
|
+
# .artist => 'Sample Artist'
|
134
|
+
# .bit_rate => '146 kb/s'
|
135
|
+
# .date => 2012
|
136
|
+
# .duration => '1'
|
137
|
+
# .filename => 'spec/fixtures/sample.flac'
|
138
|
+
# .filesize => '17.9K'
|
139
|
+
# .format_long_name => 'raw FLAC'
|
140
|
+
# .format_name => 'flac'
|
141
|
+
# .genre => 'Sample Genre'
|
142
|
+
# .nb_streams => '1'
|
143
|
+
# .start_time => 'N/A'
|
144
|
+
# .title => 'Sample Title'
|
145
|
+
# .track => '01'
|
146
|
+
#
|
147
|
+
def tags(tag_struct: TagStruct)
|
148
|
+
@tag_struct ||= tag_struct.new(formatted)
|
76
149
|
end
|
77
150
|
|
78
151
|
# Public: This method reloads the current instance.
|
@@ -81,20 +154,19 @@ module PopCap
|
|
81
154
|
# audio_file.reload!
|
82
155
|
#
|
83
156
|
def reload!
|
84
|
-
|
85
|
-
super
|
157
|
+
::MEMOIZABLES.each { |var| self.instance_variable_set(var, nil) }
|
86
158
|
end
|
87
159
|
|
88
|
-
# Public:
|
160
|
+
# Public: update(updates)
|
89
161
|
# Updates existing tags, adds a tag if it does not exist.
|
90
162
|
#
|
91
|
-
# updates - This takes a hash of
|
163
|
+
# updates - This takes a hash of tags.
|
92
164
|
#
|
93
165
|
# Examples
|
94
166
|
#
|
95
|
-
# audio_file.
|
167
|
+
# audio_file.update(artist: 'New Artist', album: 'New Album')
|
96
168
|
#
|
97
|
-
def
|
169
|
+
def update(updates={})
|
98
170
|
TagWriter.write(filepath, updates)
|
99
171
|
self.reload!
|
100
172
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'pop_cap/class_support'
|
2
|
+
require 'pop_cap/formatter'
|
3
|
+
|
4
|
+
module PopCap
|
5
|
+
# Public: This class will apply all Formatters to
|
6
|
+
# the supplied hash.
|
7
|
+
#
|
8
|
+
# new - Supply an unformatted hash.
|
9
|
+
#
|
10
|
+
class FormattedHash
|
11
|
+
def initialize(unformatted)
|
12
|
+
@unformatted = unformatted
|
13
|
+
end
|
14
|
+
|
15
|
+
# Public: This class will apply all Formatters to
|
16
|
+
# the supplied hash.
|
17
|
+
#
|
18
|
+
def formatted
|
19
|
+
@unformatted.merge(formatted_hash)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Public: This wraps #new & #formatted.
|
23
|
+
#
|
24
|
+
def self.formatted(unformatted)
|
25
|
+
new(unformatted).formatted
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
def formatted_hash(formatters: Formatters::Formatter, support: ClassSupport)
|
30
|
+
formatters.subclasses.inject({}) do |formatted, formatter|
|
31
|
+
attribute = support.new(formatter).symbolize
|
32
|
+
formatted.merge(formatted_attribute(formatter, attribute))
|
33
|
+
end.reject { |_,val| val.nil? }
|
34
|
+
end
|
35
|
+
|
36
|
+
def formatted_attribute(formatter, attribute)
|
37
|
+
{attribute => formatter.format(@unformatted[attribute])}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -16,6 +16,7 @@ module PopCap
|
|
16
16
|
def initialize(hash)
|
17
17
|
raise(ArgumentError, argument_error_message) unless hash.kind_of?(Hash)
|
18
18
|
@hash = hash
|
19
|
+
@tags = {}
|
19
20
|
define_instance_methods
|
20
21
|
end
|
21
22
|
|
@@ -31,6 +32,14 @@ module PopCap
|
|
31
32
|
"#<#{self.class.name} " + methods + '>'
|
32
33
|
end
|
33
34
|
|
35
|
+
# Public: This method is a custom each iterator for tags.
|
36
|
+
#
|
37
|
+
def each(&block)
|
38
|
+
@tags.each do |tag|
|
39
|
+
block_given? ? block.call(tag) : tag
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
34
43
|
private
|
35
44
|
def argument_error_message
|
36
45
|
'Initialize with a hash.'
|
@@ -40,6 +49,7 @@ module PopCap
|
|
40
49
|
@hash.each do |key, val|
|
41
50
|
unless self.class.respond_to? key
|
42
51
|
define_singleton_method(key) { val }
|
52
|
+
@tags[key] = val
|
43
53
|
end
|
44
54
|
end
|
45
55
|
end
|
@@ -3,7 +3,7 @@ require 'json'
|
|
3
3
|
module PopCap
|
4
4
|
# Public: This class formats the JSON output of TagReader.
|
5
5
|
#
|
6
|
-
class
|
6
|
+
class UnformattedHash
|
7
7
|
attr_reader :json
|
8
8
|
|
9
9
|
def initialize(json)
|
@@ -14,7 +14,7 @@ module PopCap
|
|
14
14
|
# The keys have been converted to symbols.
|
15
15
|
#
|
16
16
|
def hash
|
17
|
-
renamed_hash
|
17
|
+
renamed_hash
|
18
18
|
end
|
19
19
|
|
20
20
|
# Public: This method wraps #new & #hash.
|
@@ -25,7 +25,9 @@ module PopCap
|
|
25
25
|
|
26
26
|
private
|
27
27
|
def renamed_hash
|
28
|
-
symbolized_hash.
|
28
|
+
symbolized_hash.
|
29
|
+
merge({filesize: size_element}).
|
30
|
+
reject { |key,_| key == :size }
|
29
31
|
end
|
30
32
|
|
31
33
|
def symbolized_hash
|
data/lib/pop_cap/version.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
|
-
require 'pop_cap/audio_file'
|
2
1
|
require 'spec_helper'
|
3
2
|
require 'support/popcap_spec_helper'
|
3
|
+
require 'pop_cap/audio_file'
|
4
4
|
|
5
5
|
module PopCap
|
6
6
|
describe AudioFile do
|
7
7
|
let(:audio_file) { AudioFile.new(filepath) }
|
8
|
-
let(:filepath) { PopCapSpecHelper::SAMPLE_FILE }
|
8
|
+
let(:filepath) { File.realpath(PopCapSpecHelper::SAMPLE_FILE) }
|
9
9
|
let(:included_modules) { AudioFile.included_modules }
|
10
10
|
|
11
11
|
before { PopCapSpecHelper.setup }
|
@@ -13,8 +13,8 @@ module PopCap
|
|
13
13
|
|
14
14
|
subject { audio_file }
|
15
15
|
|
16
|
-
|
17
|
-
its(:filepath) { should eq File.realpath(
|
16
|
+
describe '#filepath' do
|
17
|
+
its(:filepath) { should eq File.realpath(PopCapSpecHelper::SAMPLE_FILE) }
|
18
18
|
|
19
19
|
it 'raises an error if file does not exist' do
|
20
20
|
expect do
|
@@ -23,43 +23,93 @@ module PopCap
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
-
context 'ffmpeg methods' do
|
27
|
-
it { expect(audio_file).to respond_to(:convert) }
|
28
|
-
it { expect(audio_file).to respond_to(:raw_tags) }
|
29
|
-
it { expect(audio_file).to respond_to(:update_tags) }
|
30
|
-
end
|
31
|
-
|
32
26
|
context 'included modules' do
|
33
27
|
it 'includes Fileable' do
|
34
28
|
expect(included_modules).to include Fileable
|
35
29
|
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '#raw_output' do
|
33
|
+
it 'is memoized' do
|
34
|
+
audio_file.raw_output
|
35
|
+
TagReader.should_not_receive(:read).with(filepath)
|
36
|
+
audio_file.raw_output
|
37
|
+
end
|
38
|
+
|
39
|
+
it { expect(audio_file.raw_output).to eq(PopCapSpecHelper.raw_output) }
|
40
|
+
end
|
41
|
+
|
42
|
+
describe '#unformatted' do
|
43
|
+
it 'is memoized' do
|
44
|
+
audio_file.unformatted
|
45
|
+
UnformattedHash.should_not_receive(:hash).with(audio_file.raw_output)
|
46
|
+
audio_file.unformatted
|
47
|
+
end
|
48
|
+
|
49
|
+
it do
|
50
|
+
expect(audio_file.unformatted).to eq PopCapSpecHelper.unformatted_hash
|
51
|
+
end
|
52
|
+
end
|
36
53
|
|
37
|
-
|
38
|
-
|
54
|
+
describe '#formatted' do
|
55
|
+
it 'is memoized' do
|
56
|
+
audio_file.formatted
|
57
|
+
FormattedHash.should_not_receive(:formatted).
|
58
|
+
with(audio_file.unformatted)
|
59
|
+
audio_file.formatted
|
39
60
|
end
|
61
|
+
|
62
|
+
it { expect(audio_file.formatted).to eq(PopCapSpecHelper.formatted_hash) }
|
40
63
|
end
|
41
64
|
|
42
|
-
|
65
|
+
describe '#tags' do
|
43
66
|
it 'is memoized' do
|
44
|
-
audio_file.
|
45
|
-
|
46
|
-
|
67
|
+
audio_file.tags
|
68
|
+
TagStruct.should_not_receive(:new).with(audio_file.formatted)
|
69
|
+
audio_file.tags
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'includes all tags for the sample file' do
|
73
|
+
PopCapSpecHelper.formatted_hash.each do |key,val|
|
74
|
+
expect(audio_file.tags.send(key)).to eq val
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'is a TagStruct' do
|
79
|
+
expect(audio_file.tags).to be_a TagStruct
|
47
80
|
end
|
48
81
|
end
|
49
82
|
|
50
|
-
|
51
|
-
it '
|
52
|
-
audio_file.
|
53
|
-
expect(audio_file.instance_variable_get('@raw')).not_to be_nil
|
83
|
+
describe '#reload!' do
|
84
|
+
it 'resets all MEMOIZABLES' do
|
85
|
+
audio_file.tags
|
54
86
|
audio_file.reload!
|
55
|
-
|
87
|
+
::MEMOIZABLES.each do |var|
|
88
|
+
expect(audio_file.instance_variable_get(var)).to be_nil
|
89
|
+
end
|
56
90
|
end
|
57
91
|
end
|
58
92
|
|
59
|
-
|
93
|
+
describe '#update' do
|
60
94
|
it 'reloads after tags updated' do
|
61
95
|
audio_file.should_receive(:reload!)
|
62
|
-
audio_file.
|
96
|
+
audio_file.update({foo: 'foo'})
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'updates tags for file' do
|
100
|
+
expect(audio_file.tags.artist).to eq 'Sample Artist'
|
101
|
+
updates = {artist: 'New Artist'}
|
102
|
+
audio_file.update(updates)
|
103
|
+
expect(audio_file.tags.artist).to eq 'New Artist'
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe '#convert' do
|
108
|
+
after { PopCapSpecHelper.remove_converted }
|
109
|
+
|
110
|
+
it 'creates a new audio file with the specified format & bitrate' do
|
111
|
+
audio_file.convert(:mp3, 128)
|
112
|
+
expect(File.exists?('spec/fixtures/sample.mp3')).to be_true
|
63
113
|
end
|
64
114
|
end
|
65
115
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'pop_cap/formatted_hash'
|
3
|
+
|
4
|
+
module PopCap
|
5
|
+
describe FormattedHash do
|
6
|
+
describe '.formatted' do
|
7
|
+
it 'wraps #new & #formatted' do
|
8
|
+
instance = double('FormattedHash')
|
9
|
+
FormattedHash.should_receive(:new).with('foo') { instance }
|
10
|
+
instance.should_receive(:formatted)
|
11
|
+
FormattedHash.formatted('foo')
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '#formatted' do
|
16
|
+
it 'does not return the formatter element, if not supplied' do
|
17
|
+
hash = FormattedHash.new(filesize: 123456)
|
18
|
+
expect(hash.formatted).not_to have_key(:date)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'applies a formatter if it is in the supplied hash' do
|
22
|
+
hash = FormattedHash.new(filesize: 123456)
|
23
|
+
expect(hash.formatted).to eq(filesize: '120.6K')
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'merges in non-formattable attributes' do
|
27
|
+
hash = FormattedHash.new({filesize: 123456, artist: 'foo'})
|
28
|
+
expect(hash.formatted).to eq({filesize: '120.6K', artist: 'foo'})
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -4,15 +4,15 @@ require 'pop_cap/formatter'
|
|
4
4
|
module PopCap
|
5
5
|
module Formatters
|
6
6
|
describe Formatter do
|
7
|
-
class
|
7
|
+
class Filesize < Formatter
|
8
8
|
def format; 'baz'; end
|
9
9
|
end
|
10
10
|
|
11
11
|
describe '.format' do
|
12
|
-
let(:taggy) { Formatters::
|
12
|
+
let(:taggy) { Formatters::Filesize.new('foo', {option: 'bar'}) }
|
13
13
|
|
14
14
|
it 'wraps #format in a class method' do
|
15
|
-
klass = Formatters::
|
15
|
+
klass = Formatters::Filesize.format('foo', {option: 'bar'})
|
16
16
|
instance = taggy.format
|
17
17
|
expect(klass).to eq instance
|
18
18
|
end
|
@@ -20,12 +20,12 @@ module PopCap
|
|
20
20
|
|
21
21
|
describe '.subclasses' do
|
22
22
|
it 'returns a list of all subclasses in the ObjectSpace' do
|
23
|
-
expect(Formatter.subclasses).to include(PopCap::Formatters::
|
23
|
+
expect(Formatter.subclasses).to include(PopCap::Formatters::Filesize)
|
24
24
|
end
|
25
25
|
|
26
26
|
it 'includes the subclass only once' do
|
27
27
|
unique = Formatter.subclasses.select do |cls|
|
28
|
-
cls == PopCap::Formatters::
|
28
|
+
cls == PopCap::Formatters::Filesize
|
29
29
|
end
|
30
30
|
expect(unique.size).to eq 1
|
31
31
|
end
|
@@ -45,19 +45,20 @@ module PopCap
|
|
45
45
|
|
46
46
|
describe '.subclasses_demodulized' do
|
47
47
|
it 'returns of the subclasses with their names demodulized' do
|
48
|
-
expect(Formatter.subclasses_demodulized).
|
48
|
+
expect(Formatter.subclasses_demodulized).
|
49
|
+
to include('Filesize')
|
49
50
|
end
|
50
51
|
end
|
51
52
|
end
|
52
53
|
|
53
54
|
describe '#format' do
|
54
|
-
let(:taggy) { Formatters::
|
55
|
+
let(:taggy) { Formatters::Filesize.new('foo', {option: 'bar'}) }
|
55
56
|
|
56
57
|
it { expect(taggy).to respond_to(:format) }
|
57
58
|
end
|
58
59
|
|
59
60
|
describe '#new' do
|
60
|
-
let(:taggy) { Formatters::
|
61
|
+
let(:taggy) { Formatters::Filesize.new('foo', {option: 'bar'}) }
|
61
62
|
|
62
63
|
it 'has a getter for value' do
|
63
64
|
expect(taggy.value).to eq 'foo'
|
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require 'pop_cap/
|
2
|
+
require 'pop_cap/tag_struct'
|
3
3
|
|
4
4
|
module PopCap
|
5
5
|
describe TagStruct do
|
@@ -36,8 +36,21 @@ module PopCap
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
-
|
40
|
-
|
39
|
+
describe '#to_s' do
|
40
|
+
it 'has a custom #to_s method' do
|
41
|
+
expect(ts.to_s).to eq "#<PopCap::TagStruct artist: Artist, date: 1984>"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe '#each' do
|
46
|
+
let(:tags) { {foo: 'foo', bar: 'bar', baz: 'baz'} }
|
47
|
+
let(:tag_struct) { TagStruct.new tags }
|
48
|
+
|
49
|
+
it 'has a custom #each method for all defined methods' do
|
50
|
+
tag_struct.each do |key,val|
|
51
|
+
expect(tags[key]).to eq val
|
52
|
+
end
|
53
|
+
end
|
41
54
|
end
|
42
55
|
|
43
56
|
describe 'already defined methods' do
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'support/popcap_spec_helper'
|
3
|
+
require 'pop_cap/unformatted_hash'
|
4
|
+
|
5
|
+
module PopCap
|
6
|
+
describe UnformattedHash do
|
7
|
+
describe '#hash' do
|
8
|
+
let(:json) { '{"format":{"size":"10","tags":{"artist":"artist"}}}' }
|
9
|
+
let(:unformatted_hash) do
|
10
|
+
UnformattedHash.new(PopCapSpecHelper.raw_output)
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'symbolizes all keys' do
|
14
|
+
unformatted_hash.hash.each_key do |key|
|
15
|
+
expect(key).to be_a Symbol
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'renames filesize to size' do
|
20
|
+
expect(unformatted_hash.hash[:size]).to be_nil
|
21
|
+
expect(unformatted_hash.hash[:filesize]).not_to be_nil
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'formats json output as a hash' do
|
25
|
+
expect(unformatted_hash.hash).to be_a Hash
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'merges tags section with format section' do
|
29
|
+
unformatted = UnformattedHash.new(json)
|
30
|
+
expect(unformatted.hash).to eq({filesize: '10', artist: 'artist'})
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '.hash' do
|
35
|
+
it 'wraps #new & #hash' do
|
36
|
+
instance = double('UnformattedHash')
|
37
|
+
UnformattedHash.should_receive(:new).with('foo') { instance }
|
38
|
+
instance.should_receive(:hash)
|
39
|
+
UnformattedHash.hash('foo')
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -6,7 +6,7 @@ module PopCapSpecHelper
|
|
6
6
|
SAMPLE_FILE = 'spec/fixtures/sample.flac'
|
7
7
|
|
8
8
|
class << self
|
9
|
-
def
|
9
|
+
def raw_output
|
10
10
|
'{"format":{"filename":"/home/marsalis/.apps/popcap/spec/fixtures/'\
|
11
11
|
'sample.flac","nb_streams":1,"format_name":"flac","format_long_name"'\
|
12
12
|
':"raw FLAC","duration":"1.000000","size":"18291","bit_rate":"146328"'\
|
@@ -54,7 +54,7 @@ module PopCapSpecHelper
|
|
54
54
|
OpenStruct.new(
|
55
55
|
{
|
56
56
|
filename: File.realpath(SAMPLE_FILE),
|
57
|
-
nb_streams:
|
57
|
+
nb_streams: 1,
|
58
58
|
format_name: 'flac',
|
59
59
|
format_long_name: 'raw FLAC',
|
60
60
|
start_time: 'N/A',
|
@@ -81,23 +81,5 @@ module PopCapSpecHelper
|
|
81
81
|
FileUtils.mv('spec/fixtures/backup.flac', SAMPLE_FILE)
|
82
82
|
FileUtils.rm_f('spec/fixtures/sample.mp3')
|
83
83
|
end
|
84
|
-
|
85
|
-
def object_names(const)
|
86
|
-
ObjectSpace.each_object(const).map { |cls| cls.name }
|
87
|
-
end
|
88
|
-
|
89
|
-
def all_names
|
90
|
-
ObjectSpace.each_object(Object).map do |obj|
|
91
|
-
obj.name if(obj.is_a?(Class) || obj.is_a?(Module))
|
92
|
-
end.compact
|
93
|
-
end
|
94
|
-
|
95
|
-
def classes
|
96
|
-
ObjectSpace.each_object(Class).map { |cls| cls }
|
97
|
-
end
|
98
|
-
|
99
|
-
def modules
|
100
|
-
ObjectSpace.each_object(Module).map { |cls| cls }
|
101
|
-
end
|
102
84
|
end
|
103
85
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: popcap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Culley Smith
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-03-
|
11
|
+
date: 2013-03-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: reek
|
@@ -60,22 +60,18 @@ files:
|
|
60
60
|
- lib/pop_cap/ffmpeg/tag_reader.rb
|
61
61
|
- lib/pop_cap/ffmpeg/tag_writer.rb
|
62
62
|
- lib/pop_cap/fileable.rb
|
63
|
+
- lib/pop_cap/formatted_hash.rb
|
63
64
|
- lib/pop_cap/formatter.rb
|
64
65
|
- lib/pop_cap/formatters/bit_rate.rb
|
65
66
|
- lib/pop_cap/formatters/date.rb
|
66
67
|
- lib/pop_cap/formatters/duration.rb
|
67
68
|
- lib/pop_cap/formatters/filesize.rb
|
68
|
-
- lib/pop_cap/
|
69
|
-
- lib/pop_cap/
|
70
|
-
- lib/pop_cap/tag/tag_struct.rb
|
71
|
-
- lib/pop_cap/taggable.rb
|
69
|
+
- lib/pop_cap/tag_struct.rb
|
70
|
+
- lib/pop_cap/unformatted_hash.rb
|
72
71
|
- lib/pop_cap/version.rb
|
73
72
|
- lib/popcap.rb
|
74
73
|
- popcap.gemspec
|
75
74
|
- spec/fixtures/sample.flac
|
76
|
-
- spec/integration/convert_audio_file_spec.rb
|
77
|
-
- spec/integration/read_metatags_spec.rb
|
78
|
-
- spec/integration/update_metatags_spec.rb
|
79
75
|
- spec/lib/pop_cap/audio_file_spec.rb
|
80
76
|
- spec/lib/pop_cap/class_support_spec.rb
|
81
77
|
- spec/lib/pop_cap/ffmpeg/commander_spec.rb
|
@@ -84,15 +80,14 @@ files:
|
|
84
80
|
- spec/lib/pop_cap/ffmpeg/tag_reader_spec.rb
|
85
81
|
- spec/lib/pop_cap/ffmpeg/tag_writer_spec.rb
|
86
82
|
- spec/lib/pop_cap/fileable_spec.rb
|
83
|
+
- spec/lib/pop_cap/formatted_hash_spec.rb
|
87
84
|
- spec/lib/pop_cap/formatter_spec.rb
|
88
85
|
- spec/lib/pop_cap/formatters/bit_rate_spec.rb
|
89
86
|
- spec/lib/pop_cap/formatters/date_spec.rb
|
90
87
|
- spec/lib/pop_cap/formatters/duration_spec.rb
|
91
88
|
- spec/lib/pop_cap/formatters/filesize_spec.rb
|
92
|
-
- spec/lib/pop_cap/
|
93
|
-
- spec/lib/pop_cap/
|
94
|
-
- spec/lib/pop_cap/tag/tag_struct_spec.rb
|
95
|
-
- spec/lib/pop_cap/taggable_spec.rb
|
89
|
+
- spec/lib/pop_cap/tag_struct_spec.rb
|
90
|
+
- spec/lib/pop_cap/unformatted_hash_spec.rb
|
96
91
|
- spec/spec_helper.rb
|
97
92
|
- spec/support/popcap_spec_helper.rb
|
98
93
|
- spec/support/reek_spec.rb
|
@@ -121,9 +116,6 @@ specification_version: 4
|
|
121
116
|
summary: A library work with audio files on the filesystem .
|
122
117
|
test_files:
|
123
118
|
- spec/fixtures/sample.flac
|
124
|
-
- spec/integration/convert_audio_file_spec.rb
|
125
|
-
- spec/integration/read_metatags_spec.rb
|
126
|
-
- spec/integration/update_metatags_spec.rb
|
127
119
|
- spec/lib/pop_cap/audio_file_spec.rb
|
128
120
|
- spec/lib/pop_cap/class_support_spec.rb
|
129
121
|
- spec/lib/pop_cap/ffmpeg/commander_spec.rb
|
@@ -132,15 +124,14 @@ test_files:
|
|
132
124
|
- spec/lib/pop_cap/ffmpeg/tag_reader_spec.rb
|
133
125
|
- spec/lib/pop_cap/ffmpeg/tag_writer_spec.rb
|
134
126
|
- spec/lib/pop_cap/fileable_spec.rb
|
127
|
+
- spec/lib/pop_cap/formatted_hash_spec.rb
|
135
128
|
- spec/lib/pop_cap/formatter_spec.rb
|
136
129
|
- spec/lib/pop_cap/formatters/bit_rate_spec.rb
|
137
130
|
- spec/lib/pop_cap/formatters/date_spec.rb
|
138
131
|
- spec/lib/pop_cap/formatters/duration_spec.rb
|
139
132
|
- spec/lib/pop_cap/formatters/filesize_spec.rb
|
140
|
-
- spec/lib/pop_cap/
|
141
|
-
- spec/lib/pop_cap/
|
142
|
-
- spec/lib/pop_cap/tag/tag_struct_spec.rb
|
143
|
-
- spec/lib/pop_cap/taggable_spec.rb
|
133
|
+
- spec/lib/pop_cap/tag_struct_spec.rb
|
134
|
+
- spec/lib/pop_cap/unformatted_hash_spec.rb
|
144
135
|
- spec/spec_helper.rb
|
145
136
|
- spec/support/popcap_spec_helper.rb
|
146
137
|
- spec/support/reek_spec.rb
|
@@ -1,31 +0,0 @@
|
|
1
|
-
module PopCap
|
2
|
-
# Public: This class will apply a provided Formatter to
|
3
|
-
# the supplied value.
|
4
|
-
#
|
5
|
-
class FormattedTag
|
6
|
-
attr_reader :formatter, :value
|
7
|
-
|
8
|
-
# Public: To construct an instance, provide a Formatter
|
9
|
-
# and the value to format.
|
10
|
-
#
|
11
|
-
# formatter - A class of type Formatters::Formatter.
|
12
|
-
# value - The value to format.
|
13
|
-
#
|
14
|
-
def initialize(formatter, value)
|
15
|
-
@formatter, @value = formatter, value
|
16
|
-
end
|
17
|
-
|
18
|
-
# Public: This returns the formatted value.
|
19
|
-
#
|
20
|
-
def format
|
21
|
-
formatter.format(value)
|
22
|
-
end
|
23
|
-
|
24
|
-
# Public: A class level method that initializes the class
|
25
|
-
# and formats the value.
|
26
|
-
#
|
27
|
-
def self.format(formatter, value)
|
28
|
-
new(formatter, value).format
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
data/lib/pop_cap/taggable.rb
DELETED
@@ -1,120 +0,0 @@
|
|
1
|
-
require 'pop_cap/class_support'
|
2
|
-
require 'pop_cap/formatter'
|
3
|
-
require 'pop_cap/tag/formatted_tag'
|
4
|
-
require 'pop_cap/tag/tag_hash'
|
5
|
-
require 'pop_cap/tag/tag_struct'
|
6
|
-
|
7
|
-
module PopCap
|
8
|
-
# Public: This module is included in anything with a #raw_tags
|
9
|
-
# attribute. It is used to parse and build tags from FFmpeg raw output.
|
10
|
-
#
|
11
|
-
module Taggable
|
12
|
-
# Public: This method reloads memoized tags.
|
13
|
-
#
|
14
|
-
def reload!
|
15
|
-
@unformatted_hash, @formatted_hash, @tag_struct = nil, nil, nil
|
16
|
-
end
|
17
|
-
|
18
|
-
# Public: This method builds an unformatted hash of tags.
|
19
|
-
#
|
20
|
-
# Examples
|
21
|
-
# class SomeClass
|
22
|
-
# def raw_tags
|
23
|
-
# end
|
24
|
-
# end
|
25
|
-
#
|
26
|
-
# klass = SomeClass.new
|
27
|
-
# klass.unformatted
|
28
|
-
# # =>
|
29
|
-
# { filename: 'spec/fixtures/sample.flac',
|
30
|
-
# format_name: 'flac',
|
31
|
-
# duration: '1.000000',
|
32
|
-
# filesize: '18291',
|
33
|
-
# bit_rate: '146328',
|
34
|
-
# genre: 'Sample Genre',
|
35
|
-
# track: '01',
|
36
|
-
# album: 'Sample Album',
|
37
|
-
# date: '2012',
|
38
|
-
# title: 'Sample Title',
|
39
|
-
# artist: 'Sample Artist' }
|
40
|
-
#
|
41
|
-
def unformatted(tag_hash: TagHash)
|
42
|
-
@unformatted_hash ||= tag_hash.hash(self.raw_tags)
|
43
|
-
end
|
44
|
-
|
45
|
-
# Public: This method builds an unformatted hash of tags.
|
46
|
-
#
|
47
|
-
# Examples
|
48
|
-
# class SomeClass
|
49
|
-
# def raw_tags
|
50
|
-
# end
|
51
|
-
# end
|
52
|
-
#
|
53
|
-
# klass = SomeClass.new
|
54
|
-
# klass.unformatted
|
55
|
-
# # =>
|
56
|
-
# { filename: 'spec/fixtures/sample.flac',
|
57
|
-
# format_name: 'flac',
|
58
|
-
# duration: '1.000000',
|
59
|
-
# filesize: '18291',
|
60
|
-
# bit_rate: '146328',
|
61
|
-
# genre: 'Sample Genre',
|
62
|
-
# track: '01',
|
63
|
-
# album: 'Sample Album',
|
64
|
-
# date: '2012',
|
65
|
-
# title: 'Sample Title',
|
66
|
-
# artist: 'Sample Artist' }
|
67
|
-
#
|
68
|
-
def formatted
|
69
|
-
@formatted_hash ||= unformatted.merge(formatted_tags)
|
70
|
-
end
|
71
|
-
|
72
|
-
# Public: This method builds an tag structure from #to_hash. Also,
|
73
|
-
# TagFormatters are applied to any tag with a custom formatter.
|
74
|
-
#
|
75
|
-
# Examples
|
76
|
-
# class SomeClass
|
77
|
-
# def raw_tags
|
78
|
-
# end
|
79
|
-
# end
|
80
|
-
#
|
81
|
-
# klass = SomeClass.new
|
82
|
-
# klass.tags
|
83
|
-
#
|
84
|
-
# # =>
|
85
|
-
# .album => 'Sample Album'
|
86
|
-
# .artist => 'Sample Artist'
|
87
|
-
# .bit_rate => '146 kb/s'
|
88
|
-
# .date => 2012
|
89
|
-
# .duration => '1'
|
90
|
-
# .filename => 'spec/fixtures/sample.flac'
|
91
|
-
# .filesize => '17.9K'
|
92
|
-
# .format_long_name => 'raw FLAC'
|
93
|
-
# .format_name => 'flac'
|
94
|
-
# .genre => 'Sample Genre'
|
95
|
-
# .nb_streams => '1'
|
96
|
-
# .start_time => 'N/A'
|
97
|
-
# .title => 'Sample Title'
|
98
|
-
# .track => '01'
|
99
|
-
#
|
100
|
-
def tags
|
101
|
-
@tag_struct ||= build_tag_struct(formatted)
|
102
|
-
end
|
103
|
-
|
104
|
-
private
|
105
|
-
def build_tag_struct(hash)
|
106
|
-
TagStruct.new(hash)
|
107
|
-
end
|
108
|
-
|
109
|
-
def formatted_tags(support: ClassSupport)
|
110
|
-
Formatters::Formatter.subclasses.inject({}) do |formatted, formatter|
|
111
|
-
attribute = support.new(formatter).symbolize
|
112
|
-
formatted.merge({attribute => format(formatter, attribute)})
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
def format(formatter, attribute, tag: FormattedTag)
|
117
|
-
tag.format(formatter, unformatted[attribute])
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|
@@ -1,15 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'support/popcap_spec_helper'
|
3
|
-
require 'pop_cap/audio_file'
|
4
|
-
|
5
|
-
module PopCap
|
6
|
-
describe 'Convert Audio Files' do
|
7
|
-
after { PopCapSpecHelper.remove_converted }
|
8
|
-
|
9
|
-
it 'creates a new audio file with the specified format & bitrate' do
|
10
|
-
audio_file = AudioFile.new(PopCapSpecHelper::SAMPLE_FILE)
|
11
|
-
audio_file.convert(:mp3, 128)
|
12
|
-
expect(File.exists?('spec/fixtures/sample.mp3')).to be_true
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
@@ -1,12 +0,0 @@
|
|
1
|
-
require 'popcap'
|
2
|
-
require 'spec_helper'
|
3
|
-
require 'support/popcap_spec_helper'
|
4
|
-
|
5
|
-
describe PopCap do
|
6
|
-
let(:audio_file) { PopCap::AudioFile.new(filepath) }
|
7
|
-
let(:filepath) { PopCapSpecHelper::SAMPLE_FILE }
|
8
|
-
|
9
|
-
it '#raw_tags' do
|
10
|
-
expect(audio_file.raw_tags).to eq PopCapSpecHelper.raw_tags
|
11
|
-
end
|
12
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
require 'popcap'
|
2
|
-
require 'spec_helper'
|
3
|
-
require 'support/popcap_spec_helper'
|
4
|
-
|
5
|
-
describe PopCap do
|
6
|
-
let(:audio_file) { PopCap::AudioFile.new(filepath) }
|
7
|
-
let(:filepath) { PopCapSpecHelper::SAMPLE_FILE }
|
8
|
-
|
9
|
-
context '#update_tags' do
|
10
|
-
before { PopCapSpecHelper.setup }
|
11
|
-
after { PopCapSpecHelper.teardown }
|
12
|
-
|
13
|
-
it 'updates tags for file' do
|
14
|
-
expect(audio_file.tags.artist).to eq 'Sample Artist'
|
15
|
-
updates = {artist: 'New Artist'}
|
16
|
-
audio_file.update_tags(updates)
|
17
|
-
expect(audio_file.tags.artist).to eq 'New Artist'
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
@@ -1,29 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'pop_cap/tag/formatted_tag'
|
3
|
-
|
4
|
-
module PopCap
|
5
|
-
describe FormattedTag do
|
6
|
-
class FakeFormatter
|
7
|
-
def self.format(value)
|
8
|
-
value.to_i
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
describe '#format' do
|
13
|
-
it 'formats a value with the formatter' do
|
14
|
-
tag = FormattedTag.new(FakeFormatter, '123')
|
15
|
-
expect(tag.format).to eq 123
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
describe '.format' do
|
20
|
-
it 'wraps #new & #format' do
|
21
|
-
instance = double('FormattedTagInstance')
|
22
|
-
FormattedTag.should_receive(:new).with(FakeFormatter, '123').
|
23
|
-
and_return(instance)
|
24
|
-
instance.should_receive(:format)
|
25
|
-
FormattedTag.format(FakeFormatter, '123')
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
@@ -1,35 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'support/popcap_spec_helper'
|
3
|
-
require 'pop_cap/tag/tag_hash'
|
4
|
-
|
5
|
-
module PopCap
|
6
|
-
describe TagHash do
|
7
|
-
describe '#hash' do
|
8
|
-
let(:tag_hash) { TagHash.new(PopCapSpecHelper.raw_tags) }
|
9
|
-
|
10
|
-
it 'symbolizes all keys' do
|
11
|
-
tag_hash.hash.each_key do |key|
|
12
|
-
expect(key).to be_a Symbol
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
it 'renames filesize to size' do
|
17
|
-
expect(tag_hash.hash[:size]).to be_nil
|
18
|
-
expect(tag_hash.hash[:filesize]).not_to be_nil
|
19
|
-
end
|
20
|
-
|
21
|
-
it 'formats json output as a hash' do
|
22
|
-
expect(tag_hash.hash).to eq(PopCapSpecHelper.unformatted_hash)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
describe '.hash' do
|
27
|
-
it 'wraps #new & #hash' do
|
28
|
-
instance = double('TagHash')
|
29
|
-
TagHash.should_receive(:new).with('foo') { instance }
|
30
|
-
instance.should_receive(:hash)
|
31
|
-
TagHash.hash('foo')
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
@@ -1,76 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'support/popcap_spec_helper'
|
3
|
-
require 'pop_cap/taggable'
|
4
|
-
|
5
|
-
module PopCap
|
6
|
-
describe Taggable do
|
7
|
-
class SomeClass
|
8
|
-
include Taggable
|
9
|
-
def raw_tags
|
10
|
-
PopCapSpecHelper.raw_tags
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
let(:sc) { SomeClass.new }
|
15
|
-
|
16
|
-
it 'has #raw_tags' do
|
17
|
-
expect(sc).to respond_to(:raw_tags)
|
18
|
-
end
|
19
|
-
|
20
|
-
describe '#unformatted' do
|
21
|
-
it 'returns TagHash#hash' do
|
22
|
-
TagHash.should_receive(:hash).with(sc.raw_tags)
|
23
|
-
sc.unformatted
|
24
|
-
end
|
25
|
-
|
26
|
-
it 'is memoized' do
|
27
|
-
sc.unformatted
|
28
|
-
TagHash.should_not_receive(:new)
|
29
|
-
sc.unformatted
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
describe '#formatted' do
|
34
|
-
it 'builds a formatted hash' do
|
35
|
-
expect(sc.formatted).to include(PopCapSpecHelper.formatted_hash)
|
36
|
-
end
|
37
|
-
|
38
|
-
it 'is memoized' do
|
39
|
-
sc.formatted
|
40
|
-
FormattedTag.should_not_receive(:new)
|
41
|
-
sc.formatted
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
describe '#tags' do
|
46
|
-
it 'builds a tag structure from #formatted_hash' do
|
47
|
-
expect(sc.tags.album).to eq PopCapSpecHelper.tags.album
|
48
|
-
expect(sc.tags.artist).to eq PopCapSpecHelper.tags.artist
|
49
|
-
expect(sc.tags.bit_rate).to eq PopCapSpecHelper.tags.bit_rate
|
50
|
-
expect(sc.tags.date).to eq PopCapSpecHelper.tags.date
|
51
|
-
expect(sc.tags.duration).to eq PopCapSpecHelper.tags.duration
|
52
|
-
expect(sc.tags.filename).to eq PopCapSpecHelper.tags.filename
|
53
|
-
expect(sc.tags.filesize).to eq PopCapSpecHelper.tags.filesize
|
54
|
-
expect(sc.tags.format_name).to eq PopCapSpecHelper.tags.format_name
|
55
|
-
expect(sc.tags.genre).to eq PopCapSpecHelper.tags.genre
|
56
|
-
expect(sc.tags.title).to eq PopCapSpecHelper.tags.title
|
57
|
-
expect(sc.tags.track).to eq PopCapSpecHelper.tags.track
|
58
|
-
end
|
59
|
-
|
60
|
-
it 'is memoized' do
|
61
|
-
sc.tags
|
62
|
-
TagStruct.should_not_receive(:new)
|
63
|
-
sc.tags
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
context '#reload!' do
|
68
|
-
it 'sets instance variables to nil' do
|
69
|
-
%w(@formatted_hash @unformatted_hash @tag_struct).each do |instance|
|
70
|
-
sc.reload!
|
71
|
-
expect(sc.instance_variable_get(instance)).to be_nil
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|