alacit 0.1.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +33 -0
- data/{README.markdown → README.md} +5 -0
- data/alacit.gemspec +2 -2
- data/lib/alacit.rb +70 -23
- data/lib/cuesheet.rb +92 -0
- data/lib/index.rb +112 -0
- data/lib/version.rb +1 -1
- data/pkg/alacit-0.1.1.gem +0 -0
- data/pkg/alacit-1.0.0.gem +0 -0
- data/test/converter_test.rb +22 -6
- data/test/fixtures/{test.ape → test3.ape} +0 -0
- data/test/fixtures/test3.cue +19 -0
- metadata +15 -7
data/CHANGELOG.md
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# AlacIt Changelog
|
2
|
+
|
3
|
+
## 1.0.0
|
4
|
+
|
5
|
+
* Cue-Sheet Splitting (Extraction) - If a matching-named `.cue` sheet is found in the same directory as the audio file, then multiple M4A's are generated based on the Cue Sheet data.
|
6
|
+
|
7
|
+
## 0.1.1
|
8
|
+
|
9
|
+
* Fix RubyGems summary and description.
|
10
|
+
|
11
|
+
## 0.1.0
|
12
|
+
|
13
|
+
* APE support
|
14
|
+
|
15
|
+
## 0.0.3
|
16
|
+
|
17
|
+
* Accepts any assortment of files and directories, and it will process them all in batch.
|
18
|
+
* Non-destructive by default. Added `--force` option.
|
19
|
+
* Alacit is now a Gem.
|
20
|
+
* Suppress FFmpeg's loud output.
|
21
|
+
* More UNIX-standard exit codes.
|
22
|
+
* Added Unit tests.
|
23
|
+
* Code is more Object-oriented.
|
24
|
+
* Remove unnecessary install instructions now that it's a Gem.
|
25
|
+
* Fix error in help text.
|
26
|
+
|
27
|
+
## 0.0.2
|
28
|
+
|
29
|
+
* WAV support
|
30
|
+
|
31
|
+
## 0.0.1
|
32
|
+
|
33
|
+
* Convert FLAC files to ALAC M4A's.
|
@@ -6,6 +6,7 @@ Apple Lossless conversion utility. Converts APE, FLAC, and WAV audio files to A
|
|
6
6
|
* No quality loss
|
7
7
|
* Basic metadata survives: Song, Artist, etc.
|
8
8
|
* Converts entire directories, single files, or any combination thereof.
|
9
|
+
* Cue-Sheet splitting / extraction
|
9
10
|
* Puts converted files in same dir as source.
|
10
11
|
|
11
12
|
### Install
|
@@ -51,6 +52,10 @@ AlacIt won't overwrite existing files by default. If you need to, just force ove
|
|
51
52
|
alacit --force song.flac
|
52
53
|
alacit -f song.flac
|
53
54
|
|
55
|
+
#### Cue-Sheet Splitting
|
56
|
+
|
57
|
+
Have you ever downloaded an album and it's a single, large audio file along with a `.cue` file? AlacIt will split that into individual files for you. If a matching-named `.cue` sheet is found in the same directory as the audio file, then multiple M4A's are generated based on the Cue Sheet data.
|
58
|
+
|
54
59
|
### Dependencies
|
55
60
|
|
56
61
|
* **Ruby 1.9.2+**
|
data/alacit.gemspec
CHANGED
@@ -9,8 +9,8 @@ spec = Gem::Specification.new do |s|
|
|
9
9
|
s.email = 'me@russbrooks.com'
|
10
10
|
s.homepage = 'http://russbrooks.com'
|
11
11
|
s.platform = Gem::Platform::RUBY
|
12
|
-
s.summary = 'APE, FLAC, and WAV to Apple Lossless (ALAC) batch conversion utility.'
|
13
|
-
s.description = 'Quickly convert entire directories of APE, FLAC, and WAV files to Apple Lossless (ALAC) for importation into iTunes, iPhones, iPads, and iPods.'
|
12
|
+
s.summary = 'APE, FLAC, and WAV to Apple Lossless (ALAC) batch conversion utility and cue-sheet splitter.'
|
13
|
+
s.description = 'Quickly convert entire directories of APE, FLAC, and WAV files to Apple Lossless (ALAC) for importation into iTunes, iPhones, iPads, and iPods. It does Cue-Sheet splitting too.'
|
14
14
|
s.files = `git ls-files`.split("\n")
|
15
15
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
16
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
data/lib/alacit.rb
CHANGED
@@ -12,9 +12,11 @@
|
|
12
12
|
# On Linux: `sudo apt-get install flac ffmpeg`
|
13
13
|
# Windows : [untested]
|
14
14
|
|
15
|
+
require 'application'
|
16
|
+
require 'cuesheet'
|
17
|
+
require 'index'
|
15
18
|
require 'open3'
|
16
19
|
require 'version'
|
17
|
-
require 'application'
|
18
20
|
|
19
21
|
module AlacIt
|
20
22
|
class Converter < Application
|
@@ -44,22 +46,28 @@ module AlacIt
|
|
44
46
|
|
45
47
|
unless Dir.glob(source_glob).empty?
|
46
48
|
Dir.glob(source_glob) do |file|
|
47
|
-
|
49
|
+
cue_file = file.chomp(File.extname(file)) + '.cue'
|
50
|
+
|
51
|
+
if File.exists? cue_file
|
52
|
+
extract_songs file, cue_file
|
53
|
+
else
|
54
|
+
m4a_file = file.chomp(File.extname(file)) + '.m4a'
|
48
55
|
|
49
|
-
|
50
|
-
|
51
|
-
|
56
|
+
if !File.exists?(m4a_file) || @options[:force]
|
57
|
+
command = 'ffmpeg -y -i "' + file + '" -c:a alac "' + m4a_file + '"'
|
58
|
+
stdout_str, stderr_str, status = Open3.capture3(command)
|
52
59
|
|
53
|
-
|
54
|
-
|
60
|
+
if status.success?
|
61
|
+
puts "#{file} converted."
|
62
|
+
else
|
63
|
+
$stderr.puts "Error: #{file}: File could not be converted."
|
64
|
+
$stderr.puts stderr_str.split("\n").last
|
65
|
+
next
|
66
|
+
end
|
55
67
|
else
|
56
|
-
$stderr.puts "Error: #{
|
57
|
-
$stderr.puts stderr_str.split("\n").last
|
68
|
+
$stderr.puts "Error: \"#{m4a_file}\" exists. Use --force option to overwrite."
|
58
69
|
next
|
59
70
|
end
|
60
|
-
else
|
61
|
-
$stderr.puts "Error: #{m4a_file} exists. Use --force option to overwrite."
|
62
|
-
next
|
63
71
|
end
|
64
72
|
end
|
65
73
|
else
|
@@ -71,22 +79,30 @@ module AlacIt
|
|
71
79
|
def convert_file(file)
|
72
80
|
if File.extname(file) =~ /(\.ape|\.flac|\.wav)/i
|
73
81
|
if File.exists? file
|
74
|
-
|
82
|
+
cue_file = file.chomp(File.extname(file)) + '.cue'
|
75
83
|
|
76
|
-
if
|
77
|
-
|
78
|
-
|
84
|
+
if File.exists? cue_file
|
85
|
+
extract_songs file, cue_file
|
86
|
+
else
|
87
|
+
# File has no Cuesheet. Convert the entire file.
|
88
|
+
m4a_file = file.chomp(File.extname(file)) + '.m4a'
|
89
|
+
|
90
|
+
if !File.exists?(m4a_file) || @options[:force]
|
91
|
+
command = 'ffmpeg -y -i "' + file + '" -c:a alac "' + m4a_file + '"'
|
92
|
+
|
93
|
+
stdout_str, stderr_str, status = Open3.capture3(command)
|
79
94
|
|
80
|
-
|
81
|
-
|
95
|
+
if status.success?
|
96
|
+
puts "#{file} converted."
|
97
|
+
else
|
98
|
+
$stderr.puts "Error: #{file}: File could not be converted."
|
99
|
+
$stderr.puts stderr_str.split("\n").last
|
100
|
+
return
|
101
|
+
end
|
82
102
|
else
|
83
|
-
$stderr.puts "Error: #{
|
84
|
-
$stderr.puts stderr_str.split("\n").last
|
103
|
+
$stderr.puts "Error: \"#{m4a_file}\" exists. Use --force option to overwrite."
|
85
104
|
return
|
86
105
|
end
|
87
|
-
else
|
88
|
-
$stderr.puts "Error: #{m4a_file} exists."
|
89
|
-
return
|
90
106
|
end
|
91
107
|
else
|
92
108
|
$stderr.puts "Error: #{file}: No such file."
|
@@ -97,6 +113,37 @@ module AlacIt
|
|
97
113
|
return
|
98
114
|
end
|
99
115
|
end
|
116
|
+
|
117
|
+
def extract_songs(file, cue_file)
|
118
|
+
cuesheet = AlacIt::Cuesheet.new(File.read(cue_file))
|
119
|
+
cuesheet.parse!
|
120
|
+
|
121
|
+
cuesheet.songs.each do |song|
|
122
|
+
m4a_filename = song[:track].to_s.rjust(2, '0') + ' - ' + song[:title] + '.m4a'
|
123
|
+
m4a_file = File.join(File.dirname(file), m4a_filename)
|
124
|
+
|
125
|
+
if !File.exists?(m4a_file) || @options[:force]
|
126
|
+
command = 'ffmpeg -y'
|
127
|
+
command << ' -i "' + file + '" -c:a alac'
|
128
|
+
command << ' -ss ' + song[:index].to_human_ms
|
129
|
+
command << (song[:duration].nil? ? '' : ' -t ' + song[:duration].to_human_ms)
|
130
|
+
command << ' "' + m4a_file + '"'
|
131
|
+
|
132
|
+
stdout_str, stderr_str, status = Open3.capture3(command)
|
133
|
+
|
134
|
+
if status.success?
|
135
|
+
puts "\"#{m4a_filename}\" extracted based on cue sheet."
|
136
|
+
else
|
137
|
+
$stderr.puts "Error: \"#{m4a_filename}\": File could not be extracted."
|
138
|
+
$stderr.puts stderr_str.split("\n").last
|
139
|
+
next
|
140
|
+
end
|
141
|
+
else
|
142
|
+
$stderr.puts "Error: \"#{m4a_filename}\" exists. Use --force option to overwrite."
|
143
|
+
next
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
100
147
|
end
|
101
148
|
end
|
102
149
|
|
data/lib/cuesheet.rb
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
module AlacIt
|
2
|
+
class Cuesheet
|
3
|
+
attr_reader :cuesheet, :songs, :track_duration
|
4
|
+
|
5
|
+
def initialize(cuesheet, track_duration = nil)
|
6
|
+
@cuesheet = cuesheet
|
7
|
+
@reg = {
|
8
|
+
:track => %r(TRACK (\d{1,3}) AUDIO),
|
9
|
+
:performer => %r(PERFORMER "(.*)"),
|
10
|
+
:title => %r(TITLE "(.*)"),
|
11
|
+
:index => %r(INDEX \d{1,3} (\d{1,3}):(\d{1,2}):(\d{1,2}))
|
12
|
+
}
|
13
|
+
@track_duration = AlacIt::Index.new(track_duration) if track_duration
|
14
|
+
end
|
15
|
+
|
16
|
+
def parse!
|
17
|
+
@songs = parse_titles.map{ |title| {:title => title} }
|
18
|
+
@songs.each_with_index do |song, i|
|
19
|
+
song[:performer] = parse_performers[i]
|
20
|
+
song[:track] = parse_tracks[i]
|
21
|
+
song[:index] = parse_indices[i]
|
22
|
+
end
|
23
|
+
raise AlacIt::InvalidCuesheet.new('Cuesheet is malformed!') unless valid?
|
24
|
+
calculate_song_durations!
|
25
|
+
true
|
26
|
+
end
|
27
|
+
|
28
|
+
def position(value)
|
29
|
+
index = Index.new(value)
|
30
|
+
return @songs.first if index < @songs.first[:index]
|
31
|
+
@songs.each_with_index do |song, i|
|
32
|
+
return song if song == @songs.last
|
33
|
+
return song if between(song[:index], @songs[i + 1][:index], index)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def valid?
|
38
|
+
@songs.all? do |song|
|
39
|
+
[:performer, :track, :index, :title].all? do |key|
|
40
|
+
song[key] != nil
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def calculate_song_durations!
|
48
|
+
@songs.each_with_index do |song, i|
|
49
|
+
if song == @songs.last
|
50
|
+
song[:duration] = (@track_duration - song[:index]) if @track_duration
|
51
|
+
return
|
52
|
+
end
|
53
|
+
song[:duration] = @songs[i + 1][:index] - song[:index]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def between(a, b, position_index)
|
58
|
+
(position_index > a) && (position_index < b)
|
59
|
+
end
|
60
|
+
|
61
|
+
def parse_titles
|
62
|
+
unless @titles
|
63
|
+
@titles = cuesheet_scan(:title).map{ |title| title.first }
|
64
|
+
@titles.delete_at(0)
|
65
|
+
end
|
66
|
+
@titles
|
67
|
+
end
|
68
|
+
|
69
|
+
def parse_performers
|
70
|
+
unless @performers
|
71
|
+
@performers = cuesheet_scan(:performer).map{ |performer| performer.first }
|
72
|
+
@performers.delete_at(0)
|
73
|
+
end
|
74
|
+
@performers
|
75
|
+
end
|
76
|
+
|
77
|
+
def parse_tracks
|
78
|
+
@tracks ||= cuesheet_scan(:track).map{ |track| track.first.to_i }
|
79
|
+
end
|
80
|
+
|
81
|
+
def parse_indices
|
82
|
+
@indices ||= cuesheet_scan(:index).map{ |index| AlacIt::Index.new([index[0].to_i, index[1].to_i, index[2].to_i]) }
|
83
|
+
end
|
84
|
+
|
85
|
+
def cuesheet_scan(field)
|
86
|
+
scan = @cuesheet.scan(@reg[field])
|
87
|
+
raise InvalidCuesheet.new("No fields were found for #{field.to_s}") if scan.empty?
|
88
|
+
scan
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
end
|
data/lib/index.rb
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
module AlacIt
|
2
|
+
class Index
|
3
|
+
SECONDS_PER_MINUTE = 60
|
4
|
+
FRAMES_PER_SECOND = 75
|
5
|
+
FRAMES_PER_MINUTE = FRAMES_PER_SECOND * 60
|
6
|
+
|
7
|
+
attr_reader :minutes, :seconds, :frames
|
8
|
+
|
9
|
+
def initialize(value=nil)
|
10
|
+
case value
|
11
|
+
when Array
|
12
|
+
set_from_array!(value)
|
13
|
+
when Integer
|
14
|
+
set_from_integer!(value)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_f
|
19
|
+
((@minutes * SECONDS_PER_MINUTE) + (@seconds) + (@frames.to_f / FRAMES_PER_SECOND)).to_f
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_i
|
23
|
+
to_f.floor
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_a
|
27
|
+
[@minutes, @seconds, @frames]
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_s
|
31
|
+
"#{'%02d' % @minutes}:#{'%02d' % @seconds}:#{'%02d' % @frames}"
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_human_ms
|
35
|
+
"00:#{'%02d' % @minutes}:#{'%02d' % @seconds}" + (@frames.to_f / 75).round(3).to_s[1..-1]
|
36
|
+
end
|
37
|
+
|
38
|
+
def +(other)
|
39
|
+
self.class.new(carrying_addition(other))
|
40
|
+
end
|
41
|
+
|
42
|
+
def -(other)
|
43
|
+
self.class.new(carrying_subtraction(other))
|
44
|
+
end
|
45
|
+
|
46
|
+
def >(other)
|
47
|
+
self.to_f > other.to_f
|
48
|
+
end
|
49
|
+
|
50
|
+
def <(other)
|
51
|
+
self.to_f < other.to_f
|
52
|
+
end
|
53
|
+
|
54
|
+
def ==(other)
|
55
|
+
self.to_a == other.to_a
|
56
|
+
end
|
57
|
+
|
58
|
+
def each
|
59
|
+
to_a.each { |value| yield value }
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def carrying_addition(other)
|
65
|
+
minutes, seconds, frames = *[@minutes + other.minutes,
|
66
|
+
@seconds + other.seconds, @frames + other.frames]
|
67
|
+
|
68
|
+
seconds, frames = *convert_with_rate(frames, seconds, FRAMES_PER_SECOND)
|
69
|
+
minutes, seconds = *convert_with_rate(seconds, minutes, SECONDS_PER_MINUTE)
|
70
|
+
[minutes, seconds, frames]
|
71
|
+
end
|
72
|
+
|
73
|
+
def carrying_subtraction(other)
|
74
|
+
seconds = minutes = 0
|
75
|
+
|
76
|
+
my_frames = @frames + (@seconds * FRAMES_PER_SECOND) + (@minutes * FRAMES_PER_MINUTE)
|
77
|
+
other_frames = other.frames + (other.seconds * FRAMES_PER_SECOND) + (other.minutes * FRAMES_PER_MINUTE)
|
78
|
+
frames = my_frames - other_frames
|
79
|
+
|
80
|
+
seconds, frames = *convert_with_rate(frames, seconds, FRAMES_PER_SECOND)
|
81
|
+
minutes, seconds = *convert_with_rate(seconds, minutes, SECONDS_PER_MINUTE)
|
82
|
+
[minutes, seconds, frames]
|
83
|
+
end
|
84
|
+
|
85
|
+
def convert_with_rate(from, to, rate, step=1)
|
86
|
+
while from >= rate
|
87
|
+
to += step
|
88
|
+
from -= rate
|
89
|
+
end
|
90
|
+
[to, from]
|
91
|
+
end
|
92
|
+
|
93
|
+
def set_from_array!(array)
|
94
|
+
if array.size != 3 || array.any?{|element| !element.is_a?(Integer)}
|
95
|
+
raise ArgumentError.new("Must be initialized with an array in the format of [minutes, seconds,frames], all integers")
|
96
|
+
end
|
97
|
+
@minutes, @seconds, @frames = *array
|
98
|
+
end
|
99
|
+
|
100
|
+
def set_from_integer!(seconds)
|
101
|
+
@minutes = 0
|
102
|
+
@frames = 0
|
103
|
+
@seconds = seconds
|
104
|
+
|
105
|
+
while @seconds >= SECONDS_PER_MINUTE
|
106
|
+
@minutes += 1
|
107
|
+
@seconds -= SECONDS_PER_MINUTE
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
end
|
data/lib/version.rb
CHANGED
data/pkg/alacit-0.1.1.gem
CHANGED
Binary file
|
Binary file
|
data/test/converter_test.rb
CHANGED
@@ -36,12 +36,12 @@ class AlacItTest < MiniTest::Unit::TestCase
|
|
36
36
|
end
|
37
37
|
|
38
38
|
def test_single_ape
|
39
|
-
FileUtils.cp 'test/fixtures/
|
39
|
+
FileUtils.cp 'test/fixtures/test3.ape', @temp_dir
|
40
40
|
ARGV.clear
|
41
|
-
ARGV << File.join(@temp_dir, '
|
41
|
+
ARGV << File.join(@temp_dir, 'test3.ape')
|
42
42
|
out, = capture_io { @app.convert }
|
43
|
-
assert_match /
|
44
|
-
assert_equal File.exists?(File.join(@temp_dir, '
|
43
|
+
assert_match /test3\.ape converted/, out
|
44
|
+
assert_equal File.exists?(File.join(@temp_dir, 'test3.m4a')), true
|
45
45
|
end
|
46
46
|
|
47
47
|
def test_single_flac
|
@@ -62,6 +62,22 @@ class AlacItTest < MiniTest::Unit::TestCase
|
|
62
62
|
assert_equal File.exists?(File.join(@temp_dir, 'test2.m4a')), true
|
63
63
|
end
|
64
64
|
|
65
|
+
def test_single_ape_with_cue_file
|
66
|
+
FileUtils.cp 'test/fixtures/test3.ape', @temp_dir
|
67
|
+
FileUtils.cp 'test/fixtures/test3.cue', @temp_dir
|
68
|
+
ARGV.clear
|
69
|
+
ARGV << File.join(@temp_dir, 'test3.ape')
|
70
|
+
out, = capture_io { @app.convert }
|
71
|
+
refute_match /test3\.ape converted/, out
|
72
|
+
assert_match /01 - Track1.m4a\" extracted based on cue sheet/, out
|
73
|
+
assert_match /02 - Track2.m4a\" extracted based on cue sheet/, out
|
74
|
+
assert_match /03 - Track3.m4a\" extracted based on cue sheet/, out
|
75
|
+
assert_equal File.exists?(File.join(@temp_dir, 'test3.m4a')), false
|
76
|
+
assert_equal File.exists?(File.join(@temp_dir, '01 - Track1.m4a')), true
|
77
|
+
assert_equal File.exists?(File.join(@temp_dir, '02 - Track2.m4a')), true
|
78
|
+
assert_equal File.exists?(File.join(@temp_dir, '03 - Track3.m4a')), true
|
79
|
+
end
|
80
|
+
|
65
81
|
def test_mixed_directory
|
66
82
|
FileUtils.cp 'test/fixtures/test.flac', @temp_dir
|
67
83
|
FileUtils.cp 'test/fixtures/test2.wav', @temp_dir
|
@@ -80,7 +96,7 @@ class AlacItTest < MiniTest::Unit::TestCase
|
|
80
96
|
ARGV.clear
|
81
97
|
ARGV << File.join(@temp_dir, 'test.flac')
|
82
98
|
out, err = capture_io { @app.convert }
|
83
|
-
assert_match /test\.m4a exists/, err
|
99
|
+
assert_match /test\.m4a\" exists/, err
|
84
100
|
end
|
85
101
|
|
86
102
|
def test_single_flac_file_exists_force_overwrite
|
@@ -100,7 +116,7 @@ class AlacItTest < MiniTest::Unit::TestCase
|
|
100
116
|
ARGV.clear
|
101
117
|
ARGV << File.join(@temp_dir)
|
102
118
|
out, err = capture_io { @app.convert }
|
103
|
-
assert_match /test\.m4a exists/, err
|
119
|
+
assert_match /test\.m4a\" exists/, err
|
104
120
|
assert_match /test2\.wav converted/, out
|
105
121
|
assert_equal File.exists?(File.join(@temp_dir, 'test2.m4a')), true
|
106
122
|
end
|
File without changes
|
@@ -0,0 +1,19 @@
|
|
1
|
+
REM GENRE "Techno"
|
2
|
+
REM DATE 2012
|
3
|
+
REM DISCID CF0A720E
|
4
|
+
REM COMMENT "ExactAudioCopy v0.99pb5"
|
5
|
+
PERFORMER "Vader"
|
6
|
+
TITLE "Test Title"
|
7
|
+
FILE "test3.ape" WAVE
|
8
|
+
TRACK 01 AUDIO
|
9
|
+
TITLE "Track1"
|
10
|
+
PERFORMER "Faithless"
|
11
|
+
INDEX 01 00:00:00
|
12
|
+
TRACK 02 AUDIO
|
13
|
+
TITLE "Track2"
|
14
|
+
PERFORMER "Faithless"
|
15
|
+
INDEX 01 00:30:74
|
16
|
+
TRACK 03 AUDIO
|
17
|
+
TITLE "Track3"
|
18
|
+
PERFORMER "Faithless"
|
19
|
+
INDEX 01 00:60:39
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: alacit
|
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: 2012-04-
|
12
|
+
date: 2012-04-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -28,32 +28,38 @@ dependencies:
|
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: '0'
|
30
30
|
description: Quickly convert entire directories of APE, FLAC, and WAV files to Apple
|
31
|
-
Lossless (ALAC) for importation into iTunes, iPhones, iPads, and iPods.
|
31
|
+
Lossless (ALAC) for importation into iTunes, iPhones, iPads, and iPods. It does
|
32
|
+
Cue-Sheet splitting too.
|
32
33
|
email: me@russbrooks.com
|
33
34
|
executables:
|
34
35
|
- alacit
|
35
36
|
extensions: []
|
36
37
|
extra_rdoc_files: []
|
37
38
|
files:
|
39
|
+
- CHANGELOG.md
|
38
40
|
- Gemfile
|
39
41
|
- Gemfile.lock
|
40
42
|
- LICENSE.txt
|
41
|
-
- README.
|
43
|
+
- README.md
|
42
44
|
- Rakefile
|
43
45
|
- alacit.gemspec
|
44
46
|
- bin/alacit
|
45
47
|
- lib/alacit.rb
|
46
48
|
- lib/application.rb
|
49
|
+
- lib/cuesheet.rb
|
50
|
+
- lib/index.rb
|
47
51
|
- lib/version.rb
|
48
52
|
- pkg/alacit-0.0.2.gem
|
49
53
|
- pkg/alacit-0.0.3.gem
|
50
54
|
- pkg/alacit-0.1.0.gem
|
51
55
|
- pkg/alacit-0.1.1.gem
|
56
|
+
- pkg/alacit-1.0.0.gem
|
52
57
|
- test/converter_test.rb
|
53
|
-
- test/fixtures/test.ape
|
54
58
|
- test/fixtures/test.flac
|
55
59
|
- test/fixtures/test.m4a
|
56
60
|
- test/fixtures/test2.wav
|
61
|
+
- test/fixtures/test3.ape
|
62
|
+
- test/fixtures/test3.cue
|
57
63
|
homepage: http://russbrooks.com
|
58
64
|
licenses: []
|
59
65
|
post_install_message:
|
@@ -77,10 +83,12 @@ rubyforge_project:
|
|
77
83
|
rubygems_version: 1.8.21
|
78
84
|
signing_key:
|
79
85
|
specification_version: 3
|
80
|
-
summary: APE, FLAC, and WAV to Apple Lossless (ALAC) batch conversion utility
|
86
|
+
summary: APE, FLAC, and WAV to Apple Lossless (ALAC) batch conversion utility and
|
87
|
+
cue-sheet splitter.
|
81
88
|
test_files:
|
82
89
|
- test/converter_test.rb
|
83
|
-
- test/fixtures/test.ape
|
84
90
|
- test/fixtures/test.flac
|
85
91
|
- test/fixtures/test.m4a
|
86
92
|
- test/fixtures/test2.wav
|
93
|
+
- test/fixtures/test3.ape
|
94
|
+
- test/fixtures/test3.cue
|