popcap 0.7.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/.rspec +4 -0
- data/Gemfile +13 -0
- data/Gemfile.lock +52 -0
- data/LICENSE +9 -0
- data/README.md +137 -0
- data/lib/pop_cap/audio_file.rb +100 -0
- data/lib/pop_cap/commander.rb +64 -0
- data/lib/pop_cap/converter.rb +40 -0
- data/lib/pop_cap/ffmpeg.rb +130 -0
- data/lib/pop_cap/fileable.rb +134 -0
- data/lib/pop_cap/formatters/bit_rate.rb +29 -0
- data/lib/pop_cap/formatters/date.rb +42 -0
- data/lib/pop_cap/formatters/duration.rb +44 -0
- data/lib/pop_cap/formatters/filesize.rb +69 -0
- data/lib/pop_cap/formatters.rb +33 -0
- data/lib/pop_cap/helper.rb +53 -0
- data/lib/pop_cap/tag_key.rb +32 -0
- data/lib/pop_cap/tag_line.rb +36 -0
- data/lib/pop_cap/tag_struct.rb +45 -0
- data/lib/pop_cap/taggable.rb +100 -0
- data/lib/pop_cap/version.rb +3 -0
- data/lib/popcap.rb +5 -0
- data/popcap.gemspec +27 -0
- data/spec/integration/convert_audio_file_spec.rb +15 -0
- data/spec/integration/read_metatags_spec.rb +12 -0
- data/spec/integration/update_metatags_spec.rb +20 -0
- data/spec/lib/pop_cap/audio_file_spec.rb +72 -0
- data/spec/lib/pop_cap/commander_spec.rb +64 -0
- data/spec/lib/pop_cap/converter_spec.rb +67 -0
- data/spec/lib/pop_cap/ffmpeg_spec.rb +96 -0
- data/spec/lib/pop_cap/fileable_spec.rb +118 -0
- data/spec/lib/pop_cap/formatters/bit_rate_spec.rb +53 -0
- data/spec/lib/pop_cap/formatters/date_spec.rb +74 -0
- data/spec/lib/pop_cap/formatters/duration_spec.rb +64 -0
- data/spec/lib/pop_cap/formatters/filesize_spec.rb +89 -0
- data/spec/lib/pop_cap/formatters_spec.rb +36 -0
- data/spec/lib/pop_cap/helper_spec.rb +42 -0
- data/spec/lib/pop_cap/tag_key_spec.rb +48 -0
- data/spec/lib/pop_cap/tag_line_spec.rb +26 -0
- data/spec/lib/pop_cap/tag_struct_spec.rb +50 -0
- data/spec/lib/pop_cap/taggable_spec.rb +62 -0
- data/spec/spec_helper.rb +11 -0
- data/spec/support/popcap_spec_helper.rb +86 -0
- data/spec/support/reek_spec.rb +8 -0
- data/spec/support/sample.flac +0 -0
- metadata +163 -0
@@ -0,0 +1,29 @@
|
|
1
|
+
module PopCap
|
2
|
+
module Formatters
|
3
|
+
# Public: This is a formatter for the bit_rate tag. It is used
|
4
|
+
# to make the bitrate human readable.
|
5
|
+
#
|
6
|
+
# bitrate - The bitrate can be sent as a string or integer.
|
7
|
+
#
|
8
|
+
class BitRate
|
9
|
+
def initialize(bitrate)
|
10
|
+
@bitrate = bitrate
|
11
|
+
end
|
12
|
+
|
13
|
+
# Public: This method returns a bitrate represented in kilobytes.
|
14
|
+
#
|
15
|
+
# It returns nil for anything that is not a number greater than
|
16
|
+
# zero.
|
17
|
+
#
|
18
|
+
# Examples
|
19
|
+
# br = BitRate.new(128456)
|
20
|
+
# br.format
|
21
|
+
# # => '128 kb/s'
|
22
|
+
#
|
23
|
+
def format
|
24
|
+
return unless @bitrate.to_i > 0
|
25
|
+
@bitrate.to_s[0..-4] + ' kb/s'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module PopCap
|
2
|
+
module Formatters
|
3
|
+
# Public: This is a formatter for the date tag. It is used
|
4
|
+
# to match and return the year.
|
5
|
+
#
|
6
|
+
# date - The date can be sent as a string or integer.
|
7
|
+
# options - An optional hash for a start & end date range.
|
8
|
+
# The start_date defaults to 1800, end_date defaults
|
9
|
+
# to 2100.
|
10
|
+
#
|
11
|
+
class Date
|
12
|
+
attr_reader :start_date, :end_date
|
13
|
+
|
14
|
+
def initialize(date, options={})
|
15
|
+
@date = date.to_s
|
16
|
+
@start_date = options[:start_date] || 1800
|
17
|
+
@end_date = options[:end_date] || 2100
|
18
|
+
end
|
19
|
+
|
20
|
+
# Public: This method returns a year if it is matched.
|
21
|
+
#
|
22
|
+
# Examples
|
23
|
+
# date = Date.new('October 5, 1975')
|
24
|
+
# date.format
|
25
|
+
# # => '1975'
|
26
|
+
#
|
27
|
+
def format
|
28
|
+
return unless ( date_match && within_date_range? )
|
29
|
+
@match[0].to_i
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
def date_match
|
34
|
+
@match ||= @date.match(/\b\d{4}\b/)
|
35
|
+
end
|
36
|
+
|
37
|
+
def within_date_range?
|
38
|
+
(start_date..end_date).include?(@match[0].to_i)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module PopCap
|
2
|
+
module Formatters
|
3
|
+
# Public: This will format a duration tag as strftime.
|
4
|
+
#
|
5
|
+
# time - Provide a string, float, or integer.
|
6
|
+
class Duration
|
7
|
+
def initialize(time)
|
8
|
+
@time = time
|
9
|
+
end
|
10
|
+
|
11
|
+
# Public: This will format a duration tag as strftime.
|
12
|
+
# It will raise a warning if the time is greater than 24 hours.
|
13
|
+
# Leading zeroes & colons are removed.
|
14
|
+
#
|
15
|
+
# Examples
|
16
|
+
# dur = Duration.new(420)
|
17
|
+
# dur.format
|
18
|
+
# # => '7:00'
|
19
|
+
#
|
20
|
+
def format
|
21
|
+
return unless @time.to_i > 0
|
22
|
+
return warning_message if over_twenty_four_hours?
|
23
|
+
remove_leading_zeroes(to_strftime)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
def to_strftime
|
28
|
+
@strftime = Time.at(@time.to_f).gmtime.strftime('%H:%M:%S')
|
29
|
+
end
|
30
|
+
|
31
|
+
def remove_leading_zeroes(strftime)
|
32
|
+
@strftime.sub(/^(0+|:)+/,'')
|
33
|
+
end
|
34
|
+
|
35
|
+
def over_twenty_four_hours?
|
36
|
+
@time.to_i > 86399
|
37
|
+
end
|
38
|
+
|
39
|
+
def warning_message
|
40
|
+
'Warning: Time is greater than 24 hours.'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module PopCap
|
2
|
+
module Formatters
|
3
|
+
# Public: This class formats a filesize as human readable,
|
4
|
+
# following a UNIX formatting standard.
|
5
|
+
#
|
6
|
+
# filesize - Provide a filesize as string, integer, or float.
|
7
|
+
#
|
8
|
+
class Filesize
|
9
|
+
::BASE = 1024
|
10
|
+
::UNITS = %W{B K M G T}
|
11
|
+
|
12
|
+
def initialize(filesize)
|
13
|
+
@filesize = filesize
|
14
|
+
end
|
15
|
+
|
16
|
+
# Public: This method will format the filesize.
|
17
|
+
# It raises a warning message if size is greater than 999 terabytes.
|
18
|
+
#
|
19
|
+
# Examples
|
20
|
+
# fs = Filesize.new(12345678)
|
21
|
+
# fs.format
|
22
|
+
# # => '11.8M'
|
23
|
+
#
|
24
|
+
def format
|
25
|
+
return if @filesize.to_i == 0
|
26
|
+
return warning_message if too_large?
|
27
|
+
converted_filesize.to_s + measurement_character
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
def binary_filesize
|
32
|
+
float / ::BASE ** exponent
|
33
|
+
end
|
34
|
+
|
35
|
+
def converted_filesize
|
36
|
+
rounded = rounded_filesize
|
37
|
+
is_zero_decimal? ? rounded.ceil : rounded
|
38
|
+
end
|
39
|
+
|
40
|
+
def exponent
|
41
|
+
(Math.log(float)/Math.log(::BASE)).to_i
|
42
|
+
end
|
43
|
+
|
44
|
+
def float
|
45
|
+
Float(@filesize)
|
46
|
+
end
|
47
|
+
|
48
|
+
def is_zero_decimal?
|
49
|
+
rounded_filesize.denominator == 1
|
50
|
+
end
|
51
|
+
|
52
|
+
def measurement_character
|
53
|
+
::UNITS[exponent]
|
54
|
+
end
|
55
|
+
|
56
|
+
def rounded_filesize
|
57
|
+
binary_filesize.round(1)
|
58
|
+
end
|
59
|
+
|
60
|
+
def too_large?
|
61
|
+
@filesize.to_i > 1099400000000000
|
62
|
+
end
|
63
|
+
|
64
|
+
def warning_message
|
65
|
+
'Warning: Number is larger than 999 terabytes.'
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module PopCap
|
2
|
+
# Internal: This module requires all formatters in "formatters/."
|
3
|
+
#
|
4
|
+
module Formatters
|
5
|
+
# Internal: This constant is a hash of all files in "formatters/."
|
6
|
+
# To add new custom formatters to Taggable#tags, add the formatter
|
7
|
+
# to "formatters/."
|
8
|
+
#
|
9
|
+
# Formatters should follow this format:
|
10
|
+
#
|
11
|
+
# Examples
|
12
|
+
# attribute - :custom_formatter
|
13
|
+
# path - lib/pop_cap/formatters/custom_formatter.rb
|
14
|
+
# class - CustomFormatter
|
15
|
+
# format instance method - #format
|
16
|
+
#
|
17
|
+
# # lib/pop_cap/formatters/custom_formatter.rb
|
18
|
+
# class CustomFormatter
|
19
|
+
# def format
|
20
|
+
# # code that formats
|
21
|
+
# end
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
::INCLUDED_FORMATTERS= {}
|
25
|
+
|
26
|
+
Dir["#{File.dirname(__FILE__)}/formatters/*.rb"].each do |path|
|
27
|
+
@file_name = File.basename(path , '.rb')
|
28
|
+
@required = 'pop_cap/formatters/' + @file_name
|
29
|
+
require @required
|
30
|
+
::INCLUDED_FORMATTERS[@file_name.to_sym] = @required
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module PopCap
|
2
|
+
# Public: This class adds helper methods to construct a class.
|
3
|
+
#
|
4
|
+
# name - This is the name of the class.
|
5
|
+
#
|
6
|
+
# Examples
|
7
|
+
# Helper.new('array')
|
8
|
+
# Helper.new('active_support')
|
9
|
+
# Helper.new('active_record/base')
|
10
|
+
#
|
11
|
+
class Helper
|
12
|
+
def initialize(name)
|
13
|
+
@name = name.to_s
|
14
|
+
end
|
15
|
+
|
16
|
+
# Public: This method camel cases a string or symbol.
|
17
|
+
#
|
18
|
+
# Examples
|
19
|
+
# helper = Helper.new('active_support')
|
20
|
+
# helper.camelize
|
21
|
+
# # => 'ActiveSupport'
|
22
|
+
#
|
23
|
+
def camelize
|
24
|
+
@name.split('_').map { |word| word.capitalize }.join
|
25
|
+
end
|
26
|
+
|
27
|
+
# Public: This namespaces a string by converting a filepath
|
28
|
+
# to a namespaced constant.
|
29
|
+
#
|
30
|
+
# Examples
|
31
|
+
# helper = Helper.new('active_record/base')
|
32
|
+
# helper.namespace
|
33
|
+
# # => 'ActiveRecord::Base'
|
34
|
+
#
|
35
|
+
def namespace
|
36
|
+
camelize.split('/').map do |word|
|
37
|
+
_,head,tail = word.partition(%r(^[a-zA-Z]))
|
38
|
+
head.upcase + tail
|
39
|
+
end.join('::')
|
40
|
+
end
|
41
|
+
|
42
|
+
# Public: This converts a string into a constant.
|
43
|
+
#
|
44
|
+
# Examples
|
45
|
+
# helper = Helper.new('active_record/base')
|
46
|
+
# helper.constantize
|
47
|
+
# # => ActiveSupport::Base
|
48
|
+
#
|
49
|
+
def constantize
|
50
|
+
Object.module_eval(namespace)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module PopCap
|
2
|
+
# Internal: This class sanitizes the raw output of FFmpeg to
|
3
|
+
# be used as a hash key.
|
4
|
+
#
|
5
|
+
# key - This is a single key as created by TagLine.
|
6
|
+
#
|
7
|
+
class TagKey
|
8
|
+
def initialize(key)
|
9
|
+
@key = key
|
10
|
+
end
|
11
|
+
|
12
|
+
# Internal: This method removes unwanted strings, downcases,
|
13
|
+
# & symbolizes a key. Additionally, it renames keys named
|
14
|
+
# 'size' to 'filesize' in order to avoid potential conflicts
|
15
|
+
# with Ruby's build-in method of the same name.
|
16
|
+
#
|
17
|
+
# Examples
|
18
|
+
# tk = TagKey.new('size')
|
19
|
+
# tk.format
|
20
|
+
# # => :filesize
|
21
|
+
#
|
22
|
+
def format
|
23
|
+
return '' if ( @key.nil? || @key.empty? )
|
24
|
+
|
25
|
+
@key.
|
26
|
+
sub(/^TAG:/,'').
|
27
|
+
sub(/^size\b/,'filesize').
|
28
|
+
downcase.
|
29
|
+
to_sym
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'pop_cap/tag_key'
|
2
|
+
require 'pop_cap/formatters'
|
3
|
+
|
4
|
+
module PopCap
|
5
|
+
# Internal: This class sanitizes the raw output of FFmpeg to
|
6
|
+
# and builds a hash.
|
7
|
+
#
|
8
|
+
# line - This is a single line of raw output from FFmpeg.
|
9
|
+
#
|
10
|
+
class TagLine
|
11
|
+
include
|
12
|
+
def initialize(line)
|
13
|
+
@line = line
|
14
|
+
end
|
15
|
+
|
16
|
+
# Internal: This method builds a hash by splitting on the
|
17
|
+
# first equal sign in a single line of content from FFmpeg.
|
18
|
+
# It uses TagKey to create the key for the hash.
|
19
|
+
#
|
20
|
+
# Examples
|
21
|
+
# tl = TagLine.new('TAG:ARTIST=David Bowie')
|
22
|
+
# to.to_hash
|
23
|
+
# # => {artist: 'David Bowie'}
|
24
|
+
#
|
25
|
+
def to_hash
|
26
|
+
return {} unless ( @line && is_a_tag? )
|
27
|
+
key,val = @line.split('=',2)
|
28
|
+
{TagKey.new(key).format => val}
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
def is_a_tag?
|
33
|
+
@line.match('=')
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module PopCap
|
2
|
+
# Public: This class is a simple implementation of a Ruby struct
|
3
|
+
# like object. It has a custom #to_s method & creates getter methods.
|
4
|
+
#
|
5
|
+
# new - This method takes a hash. It raises an error if anything else
|
6
|
+
# is provided.
|
7
|
+
#
|
8
|
+
# Examples
|
9
|
+
# ts = TagStruct.new({artist: 'Artist', date: 1984})
|
10
|
+
# ts.artist => 'Artist'
|
11
|
+
# ts.date => 1984
|
12
|
+
#
|
13
|
+
class TagStruct
|
14
|
+
def initialize(hash)
|
15
|
+
raise(ArgumentError, argument_error_message) unless hash.kind_of?(Hash)
|
16
|
+
@hash = hash
|
17
|
+
define_instance_methods
|
18
|
+
end
|
19
|
+
|
20
|
+
# Public: This method shows the class name & hash values as a string.
|
21
|
+
#
|
22
|
+
# Examples
|
23
|
+
# ts = TagStruct.new({artist: 'Artist', date: 1984})
|
24
|
+
# puts ts
|
25
|
+
# #=> '#<PopCap::TagStruct artist: Artist, date: 1984>'
|
26
|
+
#
|
27
|
+
def to_s
|
28
|
+
methods = @hash.map { |key,val| %(#{key}: #{val}) }.join(', ')
|
29
|
+
"#<#{self.class.name} " + methods + '>'
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
def argument_error_message
|
34
|
+
'Initialize with a hash.'
|
35
|
+
end
|
36
|
+
|
37
|
+
def define_instance_methods
|
38
|
+
@hash.each do |key, val|
|
39
|
+
unless self.class.respond_to? key
|
40
|
+
define_singleton_method(key) { val }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'pop_cap/helper'
|
2
|
+
require 'pop_cap/formatters'
|
3
|
+
require 'pop_cap/tag_line'
|
4
|
+
require 'pop_cap/tag_struct'
|
5
|
+
|
6
|
+
module PopCap
|
7
|
+
# Internal: This module is included in anything with a #raw_tags
|
8
|
+
# attribute. It is used to parse and build tags from FFmpeg raw output.
|
9
|
+
#
|
10
|
+
module Taggable
|
11
|
+
include Formatters
|
12
|
+
|
13
|
+
# Internal: This method reloads memoized tags.
|
14
|
+
def reload!
|
15
|
+
@lined, @tags, @hash = nil, nil, nil
|
16
|
+
end
|
17
|
+
|
18
|
+
# Internal: This method builds a sanitized hash from #raw_tags.
|
19
|
+
#
|
20
|
+
# Examples
|
21
|
+
# class SomeClass
|
22
|
+
# def raw_tags
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# klass = SomeClass.new
|
27
|
+
# klass.to_hash
|
28
|
+
# # =>
|
29
|
+
# { filename: 'spec/support/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 to_hash
|
42
|
+
@hash ||= lined_hash.merge(formatted_hash)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Public: This method builds an tag structure from #to_hash. Also,
|
46
|
+
# TagFormatters are applied to any tag with a custom formatter.
|
47
|
+
#
|
48
|
+
# Examples
|
49
|
+
# class SomeClass
|
50
|
+
# def raw_tags
|
51
|
+
# end
|
52
|
+
# end
|
53
|
+
#
|
54
|
+
# klass = SomeClass.new
|
55
|
+
# klass.tags
|
56
|
+
#
|
57
|
+
# # =>
|
58
|
+
# .album => 'Sample Album'
|
59
|
+
# .artist => 'Sample Artist'
|
60
|
+
# .bit_rate => '146 kb/s'
|
61
|
+
# .date => 2012
|
62
|
+
# .duration => '1'
|
63
|
+
# .filename => 'spec/support/sample.flac'
|
64
|
+
# .filesize => '17.9K'
|
65
|
+
# .format_long_name => 'raw FLAC'
|
66
|
+
# .format_name => 'flac'
|
67
|
+
# .genre => 'Sample Genre'
|
68
|
+
# .nb_streams => '1'
|
69
|
+
# .start_time => 'N/A'
|
70
|
+
# .title => 'Sample Title'
|
71
|
+
# .track => '01'
|
72
|
+
#
|
73
|
+
def tags
|
74
|
+
@tags ||= build_tag_struct(to_hash)
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
def lines
|
79
|
+
self.raw_tags.split("\n")
|
80
|
+
end
|
81
|
+
|
82
|
+
def build_tag_struct(hash)
|
83
|
+
TagStruct.new(hash)
|
84
|
+
end
|
85
|
+
|
86
|
+
def lined_hash
|
87
|
+
@lined ||=
|
88
|
+
lines.inject({}) { |hsh,line| hsh.merge(TagLine.new(line)).to_hash }
|
89
|
+
end
|
90
|
+
|
91
|
+
def formatted_hash
|
92
|
+
::INCLUDED_FORMATTERS.inject({}) do |formatted, formatter|
|
93
|
+
key, value = formatter
|
94
|
+
helper = Helper.new(value)
|
95
|
+
klass = helper.constantize
|
96
|
+
formatted.merge({key => klass.new(lined_hash[key]).format})
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
data/lib/popcap.rb
ADDED
data/popcap.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib/', __FILE__)
|
3
|
+
$:.unshift lib unless $:.include?(lib)
|
4
|
+
|
5
|
+
require 'popcap'
|
6
|
+
|
7
|
+
Gem::Specification.new do |s|
|
8
|
+
s.name = 'popcap'
|
9
|
+
s.version = PopCap::VERSION
|
10
|
+
s.authors = ["Culley Smith"]
|
11
|
+
s.email = ["culley.smith@gmail.com"]
|
12
|
+
s.homepage = %q{http://madstance.com}
|
13
|
+
s.summary = %q{A library work with audio files on the filesystem .}
|
14
|
+
s.description = %q{Read & write metadata tags, convert audio files to alternate formats, manage files on the filesystem.}
|
15
|
+
|
16
|
+
s.required_ruby_version = '>= 1.9.3'
|
17
|
+
s.required_rubygems_version = '>= 1.3.6'
|
18
|
+
|
19
|
+
s.add_development_dependency 'reek', '~> 1.2'
|
20
|
+
s.add_development_dependency 'rspec', '~> 2.11'
|
21
|
+
s.add_development_dependency 'simplecov', '~> 0.7'
|
22
|
+
|
23
|
+
git_files = `git ls-files -z`.split("\0") rescue ''
|
24
|
+
s.files = git_files
|
25
|
+
s.test_files = `git ls-files -z -- {test,spec,features}/*`.split("\0")
|
26
|
+
s.require_paths = ['lib']
|
27
|
+
end
|
@@ -0,0 +1,15 @@
|
|
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('spec/support/sample.flac')
|
11
|
+
audio_file.convert(:mp3, 128)
|
12
|
+
expect(File.exists?('spec/support/sample.mp3')).to be_true
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,12 @@
|
|
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) { 'spec/support/sample.flac' }
|
8
|
+
|
9
|
+
it '#raw_tags' do
|
10
|
+
expect(audio_file.raw_tags).to eq PopCapSpecHelper.raw_tags
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,20 @@
|
|
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) { 'spec/support/sample.flac' }
|
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
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'pop_cap/audio_file'
|
2
|
+
require 'spec_helper'
|
3
|
+
require 'support/popcap_spec_helper'
|
4
|
+
|
5
|
+
module PopCap
|
6
|
+
describe AudioFile do
|
7
|
+
let(:audio_file) { AudioFile.new(filepath) }
|
8
|
+
let(:filepath) { 'spec/support/sample.flac' }
|
9
|
+
let(:included_modules) { AudioFile.included_modules }
|
10
|
+
|
11
|
+
before { PopCapSpecHelper.setup }
|
12
|
+
after { PopCapSpecHelper.teardown }
|
13
|
+
|
14
|
+
subject { audio_file }
|
15
|
+
|
16
|
+
context '#filepath' do
|
17
|
+
its(:filepath) { should eq File.realpath(filepath) }
|
18
|
+
|
19
|
+
it 'raises an error if file does not exist' do
|
20
|
+
expect do
|
21
|
+
AudioFile.new('not here.file')
|
22
|
+
end.to raise_error(FileNotFound, 'not here.file')
|
23
|
+
end
|
24
|
+
end
|
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
|
+
context 'included modules' do
|
33
|
+
it 'includes Fileable' do
|
34
|
+
expect(included_modules).to include Fileable
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'includes Taggable' do
|
38
|
+
expect(included_modules).to include Taggable
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context '#raw_tags' do
|
43
|
+
it 'is memoized' do
|
44
|
+
audio_file.raw_tags
|
45
|
+
expect(audio_file.instance_variable_get('@raw')).
|
46
|
+
to eq PopCapSpecHelper.raw_tags
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context '#reload!' do
|
51
|
+
it 'reloads raw tags' do
|
52
|
+
audio_file.raw_tags
|
53
|
+
audio_file.reload!
|
54
|
+
expect(audio_file.instance_variable_get('@raw')).to be_nil
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'calls up to Taggable#reload!' do
|
58
|
+
audio_file.raw_tags
|
59
|
+
audio_file.reload!
|
60
|
+
expect(audio_file.instance_variable_get('@tags')).to be_nil
|
61
|
+
expect(audio_file.instance_variable_get('@to_hash')).to be_nil
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context '#update_tags' do
|
66
|
+
it 'reloads after tags updated' do
|
67
|
+
audio_file.should_receive(:reload!)
|
68
|
+
expect(audio_file.update_tags({foo: 'foo'}))
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|