rubycue 0.0.1
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/.gitignore +1 -0
- data/MIT-LICENSE +21 -0
- data/README.rdoc +48 -0
- data/Rakefile +23 -0
- data/VERSION +1 -0
- data/lib/rubycue/cuesheet.rb +92 -0
- data/lib/rubycue/exceptions.rb +3 -0
- data/lib/rubycue/index.rb +108 -0
- data/lib/rubycue.rb +5 -0
- data/spec/fixtures/malformed.cue +214 -0
- data/spec/fixtures/test.cue +215 -0
- data/spec/spec_helper.rb +8 -0
- data/spec/unit/cuesheet_spec.rb +102 -0
- data/spec/unit/index_spec.rb +243 -0
- metadata +82 -0
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
*.swp
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Copyright (c) 2010 Blake Smith
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
data/README.rdoc
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
= RubyCue: A library to parse cuesheet song files
|
2
|
+
|
3
|
+
RubyCue is a Ruby interface for parsing and accessing cuesheet data.
|
4
|
+
|
5
|
+
= Usage:
|
6
|
+
|
7
|
+
=== Basic usage
|
8
|
+
|
9
|
+
require 'rubycue'
|
10
|
+
|
11
|
+
cuesheet = RubyCue::Cuesheet.new(File.read("cuesheet.cue"))
|
12
|
+
cuesheet.parse!
|
13
|
+
|
14
|
+
cuesheet.songs.each do |song|
|
15
|
+
puts "#{song[:performer]} - #{song[:title]} at #{song[:index]}"
|
16
|
+
end
|
17
|
+
|
18
|
+
=== Calculated Song Durations
|
19
|
+
|
20
|
+
RubyCue will also calculate song durations. In order to calculate the last song's duration, you must pass the optional track duration (in seconds) for the entire file.
|
21
|
+
|
22
|
+
cuesheet = RubyCue::Cuesheet.new(File.read("cuesheet.cue"), 7143)
|
23
|
+
|
24
|
+
=== Current Song Position
|
25
|
+
|
26
|
+
After a cuesheet is instantiated, you can pass a current track position, and the cuesheet will return which song is currently playing at that position:
|
27
|
+
|
28
|
+
# with seconds
|
29
|
+
cuesheet.position(4352)
|
30
|
+
=> {:index=>#<RubyCue::Index:0x101025240 @seconds=7, @minutes=71, @frames=31>, :track=>32, :performer=>"Netsky", :title=>"Iron Heart", :duration=>#<RubyCue::Index:0x10100f2d8 @seconds=55, @minutes=2, @frames=38>}
|
31
|
+
|
32
|
+
# with an array [minutes, seconds, frames]
|
33
|
+
cuesheet.position([43, 23, 45])
|
34
|
+
=> {:index=>#<RubyCue::Index:0x101027590 @seconds=27, @minutes=39, @frames=57>, :track=>19, :performer=>"Legion feat. Adam Wright", :title=>"Both Sides", :duration=>#<RubyCue::Index:0x101013130 @seconds=45, @minutes=4, @frames=13>}
|
35
|
+
|
36
|
+
=== Index objects
|
37
|
+
|
38
|
+
Index objects are a time representation of the position in a track. They are represented with fields [minutes, seconds, frames]. There are 75 frames in each second. You can access the values of the index object like so:
|
39
|
+
|
40
|
+
index = Index.new([30, 23, 73])
|
41
|
+
index.minutes => 30
|
42
|
+
index.seconds => 23
|
43
|
+
index.frames => 73
|
44
|
+
index.to_i => 1823
|
45
|
+
index.to_f => 1823.97333333333
|
46
|
+
|
47
|
+
There's other stuff you can do with them, check out the source for more in-depth usage.
|
48
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'spec/rake/spectask'
|
3
|
+
|
4
|
+
Spec::Rake::SpecTask.new(:spec) do |t|
|
5
|
+
t.spec_files = FileList['spec/unit/*_spec.rb']
|
6
|
+
end
|
7
|
+
|
8
|
+
task :default => :spec
|
9
|
+
|
10
|
+
begin
|
11
|
+
require 'jeweler'
|
12
|
+
Jeweler::Tasks.new do |gemspec|
|
13
|
+
gemspec.name = "rubycue"
|
14
|
+
gemspec.summary = "Ruby cuesheet track parser"
|
15
|
+
gemspec.description = "Basic ruby parser for song cuesheets"
|
16
|
+
gemspec.email = "blakesmith0@gmail.com"
|
17
|
+
gemspec.homepage = "http://github.com/blakesmith/rubycue"
|
18
|
+
gemspec.authors = ["Blake Smith"]
|
19
|
+
end
|
20
|
+
rescue LoadError
|
21
|
+
puts "Jeweler not available. Install it with: gem install jeweler"
|
22
|
+
end
|
23
|
+
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
@@ -0,0 +1,92 @@
|
|
1
|
+
module RubyCue
|
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 = RubyCue::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 RubyCue::InvalidCuesheet.new("Field amounts are not all present. 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| RubyCue::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
|
@@ -0,0 +1,108 @@
|
|
1
|
+
module RubyCue
|
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 +(other)
|
35
|
+
self.class.new(carrying_addition(other))
|
36
|
+
end
|
37
|
+
|
38
|
+
def -(other)
|
39
|
+
self.class.new(carrying_subtraction(other))
|
40
|
+
end
|
41
|
+
|
42
|
+
def >(other)
|
43
|
+
self.to_f > other.to_f
|
44
|
+
end
|
45
|
+
|
46
|
+
def <(other)
|
47
|
+
self.to_f < other.to_f
|
48
|
+
end
|
49
|
+
|
50
|
+
def ==(other)
|
51
|
+
self.to_a == other.to_a
|
52
|
+
end
|
53
|
+
|
54
|
+
def each
|
55
|
+
to_a.each {|value| yield value }
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def carrying_addition(other)
|
61
|
+
minutes, seconds, frames = *[@minutes + other.minutes,
|
62
|
+
@seconds + other.seconds, @frames + other.frames]
|
63
|
+
|
64
|
+
seconds, frames = *convert_with_rate(frames, seconds, FRAMES_PER_SECOND)
|
65
|
+
minutes, seconds = *convert_with_rate(seconds, minutes, SECONDS_PER_MINUTE)
|
66
|
+
[minutes, seconds, frames]
|
67
|
+
end
|
68
|
+
|
69
|
+
def carrying_subtraction(other)
|
70
|
+
seconds = minutes = 0
|
71
|
+
|
72
|
+
my_frames = @frames + (@seconds * FRAMES_PER_SECOND) + (@minutes * FRAMES_PER_MINUTE)
|
73
|
+
other_frames = other.frames + (other.seconds * FRAMES_PER_SECOND) + (other.minutes * FRAMES_PER_MINUTE)
|
74
|
+
frames = my_frames - other_frames
|
75
|
+
|
76
|
+
seconds, frames = *convert_with_rate(frames, seconds, FRAMES_PER_SECOND)
|
77
|
+
minutes, seconds = *convert_with_rate(seconds, minutes, SECONDS_PER_MINUTE)
|
78
|
+
[minutes, seconds, frames]
|
79
|
+
end
|
80
|
+
|
81
|
+
def convert_with_rate(from, to, rate, step=1)
|
82
|
+
while from >= rate
|
83
|
+
to += step
|
84
|
+
from -= rate
|
85
|
+
end
|
86
|
+
[to, from]
|
87
|
+
end
|
88
|
+
|
89
|
+
def set_from_array!(array)
|
90
|
+
if array.size != 3 || array.any?{|element| !element.is_a?(Integer)}
|
91
|
+
raise ArgumentError.new("Must be initialized with an array in the format of [minutes, seconds,frames], all integers")
|
92
|
+
end
|
93
|
+
@minutes, @seconds, @frames = *array
|
94
|
+
end
|
95
|
+
|
96
|
+
def set_from_integer!(seconds)
|
97
|
+
@minutes = 0
|
98
|
+
@frames = 0
|
99
|
+
@seconds = seconds
|
100
|
+
|
101
|
+
while @seconds >= SECONDS_PER_MINUTE
|
102
|
+
@minutes += 1
|
103
|
+
@seconds -= SECONDS_PER_MINUTE
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
end
|
data/lib/rubycue.rb
ADDED
@@ -0,0 +1,214 @@
|
|
1
|
+
PERFORMER "Netsky"
|
2
|
+
TITLE "Essential Mix (2010-10-09)"
|
3
|
+
FILE "2010-10-09 - Essential Mix - Netsky.mp3" MP3
|
4
|
+
TRACK 01 AUDIO
|
5
|
+
PERFORMER "Essential Mix"
|
6
|
+
TITLE "Intro"
|
7
|
+
INDEX 01 00:00:00
|
8
|
+
TRACK 02 AUDIO
|
9
|
+
PERFORMER "Shameboy vs. Friction, Camo & Krooked feat. Dynamite MC"
|
10
|
+
TITLE "Strobot (Netsky Remix) vs. Stand Up"
|
11
|
+
INDEX 01 01:50:07
|
12
|
+
TRACK 03 AUDIO
|
13
|
+
PERFORMER "Danny Byrd feat. I-Kay"
|
14
|
+
TITLE "Ill Behaviour"
|
15
|
+
INDEX 01 05:26:67
|
16
|
+
TRACK 04 AUDIO
|
17
|
+
PERFORMER "Die & Interface feat. William Cartwright"
|
18
|
+
TITLE "Bright Lights (Netsky Remix)"
|
19
|
+
INDEX 01 07:16:59
|
20
|
+
TRACK 05 AUDIO
|
21
|
+
PERFORMER "Nu:Tone feat. Natalie Williams"
|
22
|
+
TITLE "Shine In"
|
23
|
+
INDEX 01 10:33:72
|
24
|
+
TRACK 06 AUDIO
|
25
|
+
PERFORMER "Netsky"
|
26
|
+
TITLE "Porcelain VIP vs. I Refuse (Acapella)"
|
27
|
+
INDEX 01 12:56:64
|
28
|
+
TRACK 07 AUDIO
|
29
|
+
PERFORMER "Netsky"
|
30
|
+
TITLE "Do It Do It vs. I Refuse (Acapella)"
|
31
|
+
INDEX 01 15:52:31
|
32
|
+
TRACK 08 AUDIO
|
33
|
+
PERFORMER "Brookes Brothers"
|
34
|
+
TITLE "Beautiful"
|
35
|
+
INDEX 01 17:31:10
|
36
|
+
TRACK 09 AUDIO
|
37
|
+
PERFORMER "Muffler"
|
38
|
+
TITLE "Uplifter"
|
39
|
+
INDEX 01 20:26:47
|
40
|
+
TRACK 10 AUDIO
|
41
|
+
PERFORMER "Indivision & Livewire feat. Nelver"
|
42
|
+
TITLE "Irresistible"
|
43
|
+
INDEX 01 22:15:03
|
44
|
+
TRACK 11 AUDIO
|
45
|
+
PERFORMER "Bcee & S.P.Y."
|
46
|
+
TITLE "Is There Anybody Out There?"
|
47
|
+
INDEX 01 23:44:12
|
48
|
+
TRACK 12 AUDIO
|
49
|
+
PERFORMER "Nu:Logic vs. Brooklyn"
|
50
|
+
TITLE "Bleeper vs. With All My Heart"
|
51
|
+
INDEX 01 25:33:68
|
52
|
+
TRACK 13 AUDIO
|
53
|
+
PERFORMER "Chords"
|
54
|
+
TITLE "Radio"
|
55
|
+
INDEX 01 27:23:42
|
56
|
+
TRACK 14 AUDIO
|
57
|
+
PERFORMER "Danny Byrd feat. Netsky"
|
58
|
+
TITLE "Tonight"
|
59
|
+
INDEX 01 29:46:15
|
60
|
+
TRACK 15 AUDIO
|
61
|
+
PERFORMER "Leftfield"
|
62
|
+
TITLE "Release The Pressure (Netsky Remix)"
|
63
|
+
INDEX 01 31:24:68
|
64
|
+
TRACK 16 AUDIO
|
65
|
+
PERFORMER "Danny Byrd feat. London Elektricity"
|
66
|
+
TITLE "Failsafe"
|
67
|
+
INDEX 01 35:04:31
|
68
|
+
TRACK 17 AUDIO
|
69
|
+
PERFORMER "Netsky"
|
70
|
+
TITLE "Everyday"
|
71
|
+
INDEX 01 37:16:06
|
72
|
+
TRACK 18 AUDIO
|
73
|
+
PERFORMER "Zero 7"
|
74
|
+
TITLE "In The Waiting Line (D+B Remix)"
|
75
|
+
INDEX 01 38:21:66
|
76
|
+
TRACK 19 AUDIO
|
77
|
+
PERFORMER "Legion feat. Adam Wright"
|
78
|
+
TITLE "Both Sides"
|
79
|
+
INDEX 01 39:27:57
|
80
|
+
TRACK 20 AUDIO
|
81
|
+
PERFORMER "New Zealand Shapeshifter"
|
82
|
+
TITLE "The Touch (Netsky Remix)"
|
83
|
+
INDEX 01 44:12:70
|
84
|
+
TRACK 21 AUDIO
|
85
|
+
PERFORMER "Swedish House Mafia"
|
86
|
+
TITLE "One (Netsky Remix)"
|
87
|
+
INDEX 01 46:23:20
|
88
|
+
TRACK 22 AUDIO
|
89
|
+
PERFORMER "Netsky"
|
90
|
+
TITLE "Pirate Bay VIP"
|
91
|
+
INDEX 01 48:36:23
|
92
|
+
TRACK 23 AUDIO
|
93
|
+
PERFORMER "Danny Byrd feat. Cyantific"
|
94
|
+
TITLE "Judgement Day VIP"
|
95
|
+
INDEX 01 51:09:68
|
96
|
+
TRACK 24 AUDIO
|
97
|
+
PERFORMER "Netsky vs. Sidney Samson"
|
98
|
+
TITLE "Tomorrow's Another Dub VIP vs. Riverside (Breakage Remix)"
|
99
|
+
INDEX 01 53:21:46
|
100
|
+
TRACK 25 AUDIO
|
101
|
+
PERFORMER "The Bloody Beetroots feat. Steve Aoki"
|
102
|
+
TITLE "Warp (Dirtyphonics Remix)"
|
103
|
+
INDEX 01 55:37:44
|
104
|
+
TRACK 26 AUDIO
|
105
|
+
PERFORMER "Danny Byrd vs. Burial"
|
106
|
+
TITLE "We Can Have It All vs. Archangel (Edit)"
|
107
|
+
INDEX 01 56:05:01
|
108
|
+
TRACK 27 AUDIO
|
109
|
+
PERFORMER "DJ Fresh & Sigma vs. Netsky"
|
110
|
+
TITLE "Lassitude VIP vs. Escape"
|
111
|
+
INDEX 01 59:03:20
|
112
|
+
TRACK 28 AUDIO
|
113
|
+
PERFORMER "Commix"
|
114
|
+
TITLE "Painted Smile"
|
115
|
+
INDEX 01 63:04:52
|
116
|
+
TRACK 29 AUDIO
|
117
|
+
PERFORMER "Eastcolors"
|
118
|
+
TITLE "Go To Nowhere"
|
119
|
+
INDEX 01 66:00:20
|
120
|
+
TRACK 30 AUDIO
|
121
|
+
PERFORMER "Nu:Logic"
|
122
|
+
TITLE "Bigfoot"
|
123
|
+
INDEX 01 67:49:73
|
124
|
+
TRACK 31 AUDIO
|
125
|
+
PERFORMER "Random Movement"
|
126
|
+
TITLE "Can't Resist (S.P.Y. Remix)"
|
127
|
+
INDEX 01 69:17:50
|
128
|
+
TRACK 32 AUDIO
|
129
|
+
PERFORMER "Netsky"
|
130
|
+
TITLE "Iron Heart"
|
131
|
+
INDEX 01 71:07:31
|
132
|
+
TRACK 33 AUDIO
|
133
|
+
PERFORMER "Unicorn Kid vs. DJ Fresh & Sigma"
|
134
|
+
TITLE "Wild Life (Nu:Tone Remix) vs. Cylon"
|
135
|
+
INDEX 01 74:02:69
|
136
|
+
TRACK 34 AUDIO
|
137
|
+
PERFORMER "Agent Alvin"
|
138
|
+
TITLE "Move"
|
139
|
+
INDEX 01 76:35:15
|
140
|
+
TRACK 35 AUDIO
|
141
|
+
PERFORMER "S.P.Y."
|
142
|
+
TITLE "Go With The Flow"
|
143
|
+
INDEX 01 78:01:51
|
144
|
+
TRACK 36 AUDIO
|
145
|
+
PERFORMER "Metrik"
|
146
|
+
TITLE "T 1000"
|
147
|
+
INDEX 01 79:37:45
|
148
|
+
TRACK 37 AUDIO
|
149
|
+
PERFORMER "Culture Shock"
|
150
|
+
TITLE "Cathedral"
|
151
|
+
INDEX 01 81:21:27
|
152
|
+
TRACK 38 AUDIO
|
153
|
+
PERFORMER "Blokhe4d"
|
154
|
+
TITLE "The Way Life Used To Be"
|
155
|
+
INDEX 01 83:33:35
|
156
|
+
TRACK 39 AUDIO
|
157
|
+
PERFORMER "Hamilton"
|
158
|
+
TITLE "Soundboy"
|
159
|
+
INDEX 01 85:45:13
|
160
|
+
TRACK 40 AUDIO
|
161
|
+
PERFORMER "Squash"
|
162
|
+
TITLE "Divine"
|
163
|
+
INDEX 01 87:34:63
|
164
|
+
TRACK 41 AUDIO
|
165
|
+
PERFORMER "Above & Beyond & Gareth Emery"
|
166
|
+
TITLE "On A Good Day (J Majik & Wickaman Remix)"
|
167
|
+
INDEX 01 89:24:45
|
168
|
+
TRACK 42 AUDIO
|
169
|
+
PERFORMER "Metrik"
|
170
|
+
TITLE "Arrival (Instrumental)"
|
171
|
+
INDEX 01 91:36:16
|
172
|
+
TRACK 43 AUDIO
|
173
|
+
PERFORMER "Spy"
|
174
|
+
TITLE "By Your Side (Logistics Remix)"
|
175
|
+
INDEX 01 94:09:53
|
176
|
+
TRACK 44 AUDIO
|
177
|
+
PERFORMER "Netsky"
|
178
|
+
TITLE "Come Back Home"
|
179
|
+
INDEX 01 97:05:34
|
180
|
+
TRACK 45 AUDIO
|
181
|
+
PERFORMER "Axwell & Sebastian Ingrosso"
|
182
|
+
TITLE "Together (D+B Remix)"
|
183
|
+
INDEX 01 99:16:36
|
184
|
+
TRACK 46 AUDIO
|
185
|
+
PERFORMER "Netsky"
|
186
|
+
TITLE "Rise & Shine"
|
187
|
+
INDEX 01 101:28:54
|
188
|
+
TRACK 47 AUDIO
|
189
|
+
PERFORMER "Apex"
|
190
|
+
TITLE "String Theory"
|
191
|
+
INDEX 01 102:56:39
|
192
|
+
TRACK 48 AUDIO
|
193
|
+
PERFORMER "DJ Marky & S.P.Y."
|
194
|
+
TITLE "Touch Me"
|
195
|
+
INDEX 01 105:52:04
|
196
|
+
TRACK 49 AUDIO
|
197
|
+
PERFORMER "Subwave"
|
198
|
+
TITLE "Road Rage"
|
199
|
+
INDEX 01 107:19:56
|
200
|
+
TRACK 50 AUDIO
|
201
|
+
PERFORMER "Joe Syntax"
|
202
|
+
TITLE "Slingshot"
|
203
|
+
INDEX 01 109:53:36
|
204
|
+
TRACK 51 AUDIO
|
205
|
+
PERFORMER "Pendulum"
|
206
|
+
TITLE "Witchcraft (Netsky Remix)"
|
207
|
+
INDEX 01 110:58:14
|
208
|
+
TRACK 52 AUDIO
|
209
|
+
PERFORMER "London Elektricity"
|
210
|
+
TITLE "The Great Drum & Bass Swindle (Logistics Remix)"
|
211
|
+
INDEX 01 112:27:02
|
212
|
+
TRACK 53 AUDIO
|
213
|
+
PERFORMER "Netsky vs. Genetic Bros"
|
214
|
+
TITLE "The Lotus Symphony vs. Uplifting"
|
@@ -0,0 +1,215 @@
|
|
1
|
+
PERFORMER "Netsky"
|
2
|
+
TITLE "Essential Mix (2010-10-09)"
|
3
|
+
FILE "2010-10-09 - Essential Mix - Netsky.mp3" MP3
|
4
|
+
TRACK 01 AUDIO
|
5
|
+
PERFORMER "Essential Mix"
|
6
|
+
TITLE "Intro"
|
7
|
+
INDEX 01 00:00:00
|
8
|
+
TRACK 02 AUDIO
|
9
|
+
PERFORMER "Shameboy vs. Friction, Camo & Krooked feat. Dynamite MC"
|
10
|
+
TITLE "Strobot (Netsky Remix) vs. Stand Up"
|
11
|
+
INDEX 01 01:50:07
|
12
|
+
TRACK 03 AUDIO
|
13
|
+
PERFORMER "Danny Byrd feat. I-Kay"
|
14
|
+
TITLE "Ill Behaviour"
|
15
|
+
INDEX 01 05:26:67
|
16
|
+
TRACK 04 AUDIO
|
17
|
+
PERFORMER "Die & Interface feat. William Cartwright"
|
18
|
+
TITLE "Bright Lights (Netsky Remix)"
|
19
|
+
INDEX 01 07:16:59
|
20
|
+
TRACK 05 AUDIO
|
21
|
+
PERFORMER "Nu:Tone feat. Natalie Williams"
|
22
|
+
TITLE "Shine In"
|
23
|
+
INDEX 01 10:33:72
|
24
|
+
TRACK 06 AUDIO
|
25
|
+
PERFORMER "Netsky"
|
26
|
+
TITLE "Porcelain VIP vs. I Refuse (Acapella)"
|
27
|
+
INDEX 01 12:56:64
|
28
|
+
TRACK 07 AUDIO
|
29
|
+
PERFORMER "Netsky"
|
30
|
+
TITLE "Do It Do It vs. I Refuse (Acapella)"
|
31
|
+
INDEX 01 15:52:31
|
32
|
+
TRACK 08 AUDIO
|
33
|
+
PERFORMER "Brookes Brothers"
|
34
|
+
TITLE "Beautiful"
|
35
|
+
INDEX 01 17:31:10
|
36
|
+
TRACK 09 AUDIO
|
37
|
+
PERFORMER "Muffler"
|
38
|
+
TITLE "Uplifter"
|
39
|
+
INDEX 01 20:26:47
|
40
|
+
TRACK 10 AUDIO
|
41
|
+
PERFORMER "Indivision & Livewire feat. Nelver"
|
42
|
+
TITLE "Irresistible"
|
43
|
+
INDEX 01 22:15:03
|
44
|
+
TRACK 11 AUDIO
|
45
|
+
PERFORMER "Bcee & S.P.Y."
|
46
|
+
TITLE "Is There Anybody Out There?"
|
47
|
+
INDEX 01 23:44:12
|
48
|
+
TRACK 12 AUDIO
|
49
|
+
PERFORMER "Nu:Logic vs. Brooklyn"
|
50
|
+
TITLE "Bleeper vs. With All My Heart"
|
51
|
+
INDEX 01 25:33:68
|
52
|
+
TRACK 13 AUDIO
|
53
|
+
PERFORMER "Chords"
|
54
|
+
TITLE "Radio"
|
55
|
+
INDEX 01 27:23:42
|
56
|
+
TRACK 14 AUDIO
|
57
|
+
PERFORMER "Danny Byrd feat. Netsky"
|
58
|
+
TITLE "Tonight"
|
59
|
+
INDEX 01 29:46:15
|
60
|
+
TRACK 15 AUDIO
|
61
|
+
PERFORMER "Leftfield"
|
62
|
+
TITLE "Release The Pressure (Netsky Remix)"
|
63
|
+
INDEX 01 31:24:68
|
64
|
+
TRACK 16 AUDIO
|
65
|
+
PERFORMER "Danny Byrd feat. London Elektricity"
|
66
|
+
TITLE "Failsafe"
|
67
|
+
INDEX 01 35:04:31
|
68
|
+
TRACK 17 AUDIO
|
69
|
+
PERFORMER "Netsky"
|
70
|
+
TITLE "Everyday"
|
71
|
+
INDEX 01 37:16:06
|
72
|
+
TRACK 18 AUDIO
|
73
|
+
PERFORMER "Zero 7"
|
74
|
+
TITLE "In The Waiting Line (D+B Remix)"
|
75
|
+
INDEX 01 38:21:66
|
76
|
+
TRACK 19 AUDIO
|
77
|
+
PERFORMER "Legion feat. Adam Wright"
|
78
|
+
TITLE "Both Sides"
|
79
|
+
INDEX 01 39:27:57
|
80
|
+
TRACK 20 AUDIO
|
81
|
+
PERFORMER "New Zealand Shapeshifter"
|
82
|
+
TITLE "The Touch (Netsky Remix)"
|
83
|
+
INDEX 01 44:12:70
|
84
|
+
TRACK 21 AUDIO
|
85
|
+
PERFORMER "Swedish House Mafia"
|
86
|
+
TITLE "One (Netsky Remix)"
|
87
|
+
INDEX 01 46:23:20
|
88
|
+
TRACK 22 AUDIO
|
89
|
+
PERFORMER "Netsky"
|
90
|
+
TITLE "Pirate Bay VIP"
|
91
|
+
INDEX 01 48:36:23
|
92
|
+
TRACK 23 AUDIO
|
93
|
+
PERFORMER "Danny Byrd feat. Cyantific"
|
94
|
+
TITLE "Judgement Day VIP"
|
95
|
+
INDEX 01 51:09:68
|
96
|
+
TRACK 24 AUDIO
|
97
|
+
PERFORMER "Netsky vs. Sidney Samson"
|
98
|
+
TITLE "Tomorrow's Another Dub VIP vs. Riverside (Breakage Remix)"
|
99
|
+
INDEX 01 53:21:46
|
100
|
+
TRACK 25 AUDIO
|
101
|
+
PERFORMER "The Bloody Beetroots feat. Steve Aoki"
|
102
|
+
TITLE "Warp (Dirtyphonics Remix)"
|
103
|
+
INDEX 01 55:37:44
|
104
|
+
TRACK 26 AUDIO
|
105
|
+
PERFORMER "Danny Byrd vs. Burial"
|
106
|
+
TITLE "We Can Have It All vs. Archangel (Edit)"
|
107
|
+
INDEX 01 56:05:01
|
108
|
+
TRACK 27 AUDIO
|
109
|
+
PERFORMER "DJ Fresh & Sigma vs. Netsky"
|
110
|
+
TITLE "Lassitude VIP vs. Escape"
|
111
|
+
INDEX 01 59:03:20
|
112
|
+
TRACK 28 AUDIO
|
113
|
+
PERFORMER "Commix"
|
114
|
+
TITLE "Painted Smile"
|
115
|
+
INDEX 01 63:04:52
|
116
|
+
TRACK 29 AUDIO
|
117
|
+
PERFORMER "Eastcolors"
|
118
|
+
TITLE "Go To Nowhere"
|
119
|
+
INDEX 01 66:00:20
|
120
|
+
TRACK 30 AUDIO
|
121
|
+
PERFORMER "Nu:Logic"
|
122
|
+
TITLE "Bigfoot"
|
123
|
+
INDEX 01 67:49:73
|
124
|
+
TRACK 31 AUDIO
|
125
|
+
PERFORMER "Random Movement"
|
126
|
+
TITLE "Can't Resist (S.P.Y. Remix)"
|
127
|
+
INDEX 01 69:17:50
|
128
|
+
TRACK 32 AUDIO
|
129
|
+
PERFORMER "Netsky"
|
130
|
+
TITLE "Iron Heart"
|
131
|
+
INDEX 01 71:07:31
|
132
|
+
TRACK 33 AUDIO
|
133
|
+
PERFORMER "Unicorn Kid vs. DJ Fresh & Sigma"
|
134
|
+
TITLE "Wild Life (Nu:Tone Remix) vs. Cylon"
|
135
|
+
INDEX 01 74:02:69
|
136
|
+
TRACK 34 AUDIO
|
137
|
+
PERFORMER "Agent Alvin"
|
138
|
+
TITLE "Move"
|
139
|
+
INDEX 01 76:35:15
|
140
|
+
TRACK 35 AUDIO
|
141
|
+
PERFORMER "S.P.Y."
|
142
|
+
TITLE "Go With The Flow"
|
143
|
+
INDEX 01 78:01:51
|
144
|
+
TRACK 36 AUDIO
|
145
|
+
PERFORMER "Metrik"
|
146
|
+
TITLE "T 1000"
|
147
|
+
INDEX 01 79:37:45
|
148
|
+
TRACK 37 AUDIO
|
149
|
+
PERFORMER "Culture Shock"
|
150
|
+
TITLE "Cathedral"
|
151
|
+
INDEX 01 81:21:27
|
152
|
+
TRACK 38 AUDIO
|
153
|
+
PERFORMER "Blokhe4d"
|
154
|
+
TITLE "The Way Life Used To Be"
|
155
|
+
INDEX 01 83:33:35
|
156
|
+
TRACK 39 AUDIO
|
157
|
+
PERFORMER "Hamilton"
|
158
|
+
TITLE "Soundboy"
|
159
|
+
INDEX 01 85:45:13
|
160
|
+
TRACK 40 AUDIO
|
161
|
+
PERFORMER "Squash"
|
162
|
+
TITLE "Divine"
|
163
|
+
INDEX 01 87:34:63
|
164
|
+
TRACK 41 AUDIO
|
165
|
+
PERFORMER "Above & Beyond & Gareth Emery"
|
166
|
+
TITLE "On A Good Day (J Majik & Wickaman Remix)"
|
167
|
+
INDEX 01 89:24:45
|
168
|
+
TRACK 42 AUDIO
|
169
|
+
PERFORMER "Metrik"
|
170
|
+
TITLE "Arrival (Instrumental)"
|
171
|
+
INDEX 01 91:36:16
|
172
|
+
TRACK 43 AUDIO
|
173
|
+
PERFORMER "Spy"
|
174
|
+
TITLE "By Your Side (Logistics Remix)"
|
175
|
+
INDEX 01 94:09:53
|
176
|
+
TRACK 44 AUDIO
|
177
|
+
PERFORMER "Netsky"
|
178
|
+
TITLE "Come Back Home"
|
179
|
+
INDEX 01 97:05:34
|
180
|
+
TRACK 45 AUDIO
|
181
|
+
PERFORMER "Axwell & Sebastian Ingrosso"
|
182
|
+
TITLE "Together (D+B Remix)"
|
183
|
+
INDEX 01 99:16:36
|
184
|
+
TRACK 46 AUDIO
|
185
|
+
PERFORMER "Netsky"
|
186
|
+
TITLE "Rise & Shine"
|
187
|
+
INDEX 01 101:28:54
|
188
|
+
TRACK 47 AUDIO
|
189
|
+
PERFORMER "Apex"
|
190
|
+
TITLE "String Theory"
|
191
|
+
INDEX 01 102:56:39
|
192
|
+
TRACK 48 AUDIO
|
193
|
+
PERFORMER "DJ Marky & S.P.Y."
|
194
|
+
TITLE "Touch Me"
|
195
|
+
INDEX 01 105:52:04
|
196
|
+
TRACK 49 AUDIO
|
197
|
+
PERFORMER "Subwave"
|
198
|
+
TITLE "Road Rage"
|
199
|
+
INDEX 01 107:19:56
|
200
|
+
TRACK 50 AUDIO
|
201
|
+
PERFORMER "Joe Syntax"
|
202
|
+
TITLE "Slingshot"
|
203
|
+
INDEX 01 109:53:36
|
204
|
+
TRACK 51 AUDIO
|
205
|
+
PERFORMER "Pendulum"
|
206
|
+
TITLE "Witchcraft (Netsky Remix)"
|
207
|
+
INDEX 01 110:58:14
|
208
|
+
TRACK 52 AUDIO
|
209
|
+
PERFORMER "London Elektricity"
|
210
|
+
TITLE "The Great Drum & Bass Swindle (Logistics Remix)"
|
211
|
+
INDEX 01 112:27:02
|
212
|
+
TRACK 53 AUDIO
|
213
|
+
PERFORMER "Netsky vs. Genetic Bros"
|
214
|
+
TITLE "The Lotus Symphony vs. Uplifting"
|
215
|
+
INDEX 01 115:22:47
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "../spec_helper")
|
2
|
+
|
3
|
+
describe RubyCue::Cuesheet do
|
4
|
+
before do
|
5
|
+
@cuesheet_file = load_cuesheet("test")
|
6
|
+
@cuesheet = RubyCue::Cuesheet.new(@cuesheet_file)
|
7
|
+
@cuesheet.parse!
|
8
|
+
end
|
9
|
+
|
10
|
+
it "stores the cuesheet string" do
|
11
|
+
cuesheet = RubyCue::Cuesheet.new(@cuesheet_file)
|
12
|
+
cuesheet.cuesheet.should == @cuesheet_file
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#parse!" do
|
16
|
+
context "properly formatted cuesheet" do
|
17
|
+
it "returns true if successfully parsed" do
|
18
|
+
@cuesheet.parse!.should be_true
|
19
|
+
end
|
20
|
+
|
21
|
+
it "has the right first track" do
|
22
|
+
@cuesheet.songs.first[:title].should == "Intro"
|
23
|
+
end
|
24
|
+
|
25
|
+
it "has the right last track" do
|
26
|
+
@cuesheet.songs.last[:title].should == "The Lotus Symphony vs. Uplifting"
|
27
|
+
end
|
28
|
+
|
29
|
+
it "has the right first performer" do
|
30
|
+
@cuesheet.songs.first[:performer].should == "Essential Mix"
|
31
|
+
end
|
32
|
+
|
33
|
+
it "has the right last performer" do
|
34
|
+
@cuesheet.songs.last[:performer].should == "Netsky vs. Genetic Bros"
|
35
|
+
end
|
36
|
+
|
37
|
+
it "has the right first index" do
|
38
|
+
@cuesheet.songs.first[:index].should == [0, 0, 0]
|
39
|
+
end
|
40
|
+
|
41
|
+
it "has the right last index" do
|
42
|
+
@cuesheet.songs.last[:index].should == [115, 22, 47]
|
43
|
+
end
|
44
|
+
|
45
|
+
it "has the right first track" do
|
46
|
+
@cuesheet.songs.first[:track].should == 1
|
47
|
+
end
|
48
|
+
|
49
|
+
it "has the right last track" do
|
50
|
+
@cuesheet.songs.last[:track].should == 53
|
51
|
+
end
|
52
|
+
|
53
|
+
it "has the right amonut of tracks" do
|
54
|
+
@cuesheet.songs.size.should == 53
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "#calculate_song_duration!" do
|
58
|
+
it "properly calculates song duration at the beginning of the track" do
|
59
|
+
@cuesheet.songs.first[:duration].to_a.should == [1, 50, 07]
|
60
|
+
end
|
61
|
+
|
62
|
+
it "properly calculates song duration in the middle of the track" do
|
63
|
+
@cuesheet.songs[20][:duration].to_a.should == [2, 13, 3]
|
64
|
+
end
|
65
|
+
|
66
|
+
it "properly calculates song duration of the last song given the user inputs the total track length" do
|
67
|
+
cuesheet = RubyCue::Cuesheet.new(load_cuesheet('test'), 7185)
|
68
|
+
cuesheet.parse!
|
69
|
+
cuesheet.songs.last[:duration].to_a.should == [4, 22, 28]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context "improperly formatted cuesheet" do
|
75
|
+
it "should raise an exception for a bogus formatted cuesheet" do
|
76
|
+
cuesheet = RubyCue::Cuesheet.new("Something bogus")
|
77
|
+
lambda { cuesheet.parse! }.should raise_error(RubyCue::InvalidCuesheet)
|
78
|
+
end
|
79
|
+
|
80
|
+
it "raises an exception if all our fields don't find the same amount of items" do
|
81
|
+
cue = load_cuesheet('malformed')
|
82
|
+
cuesheet = RubyCue::Cuesheet.new(cue)
|
83
|
+
lambda { cuesheet.parse! }.should raise_error(RubyCue::InvalidCuesheet)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
describe "#position" do
|
89
|
+
it "returns the current song in the cuesheet based on the designated position" do
|
90
|
+
@cuesheet.position(1943).should == @cuesheet.songs[14]
|
91
|
+
end
|
92
|
+
|
93
|
+
it "returns the first song if a negative position is passed" do
|
94
|
+
@cuesheet.position(-5).should == @cuesheet.songs[0]
|
95
|
+
end
|
96
|
+
|
97
|
+
it "returns the last song if a position greater than the last index is passed" do
|
98
|
+
@cuesheet.position(10000000).should == @cuesheet.songs.last
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
@@ -0,0 +1,243 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "../spec_helper")
|
2
|
+
|
3
|
+
describe RubyCue::Index do
|
4
|
+
describe "init" do
|
5
|
+
it "allows empty initialization" do
|
6
|
+
lambda { RubyCue::Index.new }.should_not raise_error
|
7
|
+
end
|
8
|
+
|
9
|
+
it "initializes from an array if specified default" do
|
10
|
+
index = RubyCue::Index.new([5, 0, 75])
|
11
|
+
index.minutes.should == 5
|
12
|
+
index.seconds.should == 0
|
13
|
+
index.frames.should == 75
|
14
|
+
end
|
15
|
+
|
16
|
+
it "initializes from integer seconds less than a minute" do
|
17
|
+
index = RubyCue::Index.new(30)
|
18
|
+
index.minutes.should == 0
|
19
|
+
index.seconds.should == 30
|
20
|
+
index.frames.should == 0
|
21
|
+
end
|
22
|
+
|
23
|
+
it "initializes from integer seconds over a minute" do
|
24
|
+
index = RubyCue::Index.new(90)
|
25
|
+
index.minutes.should == 1
|
26
|
+
index.seconds.should == 30
|
27
|
+
index.frames.should == 0
|
28
|
+
end
|
29
|
+
|
30
|
+
it "initializes from integer seconds at a minute" do
|
31
|
+
index = RubyCue::Index.new(60)
|
32
|
+
index.minutes.should == 1
|
33
|
+
index.seconds.should == 0
|
34
|
+
index.frames.should == 0
|
35
|
+
end
|
36
|
+
|
37
|
+
it "raises an error if the array size is not size 3" do
|
38
|
+
lambda { RubyCue::Index.new([0, 0, 0, 0]) }.should raise_error(ArgumentError)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "raises an error if not all the array elements are integers" do
|
42
|
+
lambda { RubyCue::Index.new([0, "moose", 0]) }.should raise_error(ArgumentError)
|
43
|
+
end
|
44
|
+
|
45
|
+
context "conversions" do
|
46
|
+
describe "#to_f" do
|
47
|
+
it "converts an array value under a minute" do
|
48
|
+
index = RubyCue::Index.new([0, 30, 0])
|
49
|
+
index.to_f.should == 30.0
|
50
|
+
end
|
51
|
+
|
52
|
+
it "converts an array value over a minute" do
|
53
|
+
index = RubyCue::Index.new([1, 30, 0])
|
54
|
+
index.to_f.should == 90.0
|
55
|
+
end
|
56
|
+
|
57
|
+
it "converts an array value over a minute with frames" do
|
58
|
+
index = RubyCue::Index.new([1, 30, 74])
|
59
|
+
index.to_f.should == (90 + (74 / 75.0)).to_f
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe "#to_s" do
|
64
|
+
it "renders the index as a string with leading zeroes" do
|
65
|
+
index = RubyCue::Index.new([1, 30, 74]).to_s.should == "01:30:74"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "#to_i" do
|
70
|
+
it "converts to seconds and rounds down" do
|
71
|
+
index = RubyCue::Index.new([0, 30, 74])
|
72
|
+
index.to_i.should == 30
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe "#to_a" do
|
77
|
+
it "converts to an array" do
|
78
|
+
index = RubyCue::Index.new([1, 2, 3])
|
79
|
+
index.to_a.should == [1, 2, 3]
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context "computations" do
|
85
|
+
describe "#+" do
|
86
|
+
it "returns an object of Class Index" do
|
87
|
+
index1 = RubyCue::Index.new([0, 30, 0])
|
88
|
+
index2 = RubyCue::Index.new([0, 30, 0])
|
89
|
+
|
90
|
+
(index1 + index2).class.should == RubyCue::Index
|
91
|
+
end
|
92
|
+
|
93
|
+
it "adds two indices under a minute" do
|
94
|
+
index1 = RubyCue::Index.new([0, 30, 0])
|
95
|
+
index2 = RubyCue::Index.new([0, 30, 0])
|
96
|
+
|
97
|
+
(index1 + index2).to_a.should == [1, 0, 0]
|
98
|
+
end
|
99
|
+
|
100
|
+
it "adds two indices over a minute" do
|
101
|
+
index1 = RubyCue::Index.new([1, 30, 0])
|
102
|
+
index2 = RubyCue::Index.new([2, 20, 0])
|
103
|
+
|
104
|
+
(index1 + index2).to_a.should == [3, 50, 0]
|
105
|
+
end
|
106
|
+
|
107
|
+
it "adds two indices with frames" do
|
108
|
+
index1 = RubyCue::Index.new([1, 30, 50])
|
109
|
+
index2 = RubyCue::Index.new([2, 20, 50])
|
110
|
+
|
111
|
+
(index1 + index2).to_a.should == [3, 51, 25]
|
112
|
+
end
|
113
|
+
|
114
|
+
it "adds two indices with only frames" do
|
115
|
+
index1 = RubyCue::Index.new([0, 0, 50])
|
116
|
+
index2 = RubyCue::Index.new([0, 0, 25])
|
117
|
+
|
118
|
+
(index1 + index2).to_a.should == [0, 1, 0]
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
describe "#-" do
|
123
|
+
it "returns an object of Class Index" do
|
124
|
+
index1 = RubyCue::Index.new([0, 30, 0])
|
125
|
+
index2 = RubyCue::Index.new([0, 30, 0])
|
126
|
+
|
127
|
+
(index1 - index2).class.should == RubyCue::Index
|
128
|
+
end
|
129
|
+
|
130
|
+
it "subtracts two indices with only frames" do
|
131
|
+
index1 = RubyCue::Index.new([0, 0, 50])
|
132
|
+
index2 = RubyCue::Index.new([0, 0, 25])
|
133
|
+
|
134
|
+
(index1 - index2).to_a.should == [0, 0, 25]
|
135
|
+
end
|
136
|
+
|
137
|
+
it "subtracts two indices with minutes" do
|
138
|
+
index1 = RubyCue::Index.new([3, 20, 50])
|
139
|
+
index2 = RubyCue::Index.new([2, 40, 25])
|
140
|
+
|
141
|
+
(index1 - index2).to_a.should == [0, 40, 25]
|
142
|
+
end
|
143
|
+
|
144
|
+
it "subtracts two indices with even minutes" do
|
145
|
+
index1 = RubyCue::Index.new([3, 0, 0])
|
146
|
+
index2 = RubyCue::Index.new([2, 0, 0])
|
147
|
+
|
148
|
+
(index1 - index2).to_a.should == [1, 0, 0]
|
149
|
+
end
|
150
|
+
|
151
|
+
end
|
152
|
+
|
153
|
+
describe "#>" do
|
154
|
+
it "returns true for frames" do
|
155
|
+
index1 = RubyCue::Index.new([0, 0, 50])
|
156
|
+
index2 = RubyCue::Index.new([0, 0, 25])
|
157
|
+
|
158
|
+
(index1 > index2).should be_true
|
159
|
+
end
|
160
|
+
|
161
|
+
it "returns true for seconds" do
|
162
|
+
index1 = RubyCue::Index.new([0, 30, 50])
|
163
|
+
index2 = RubyCue::Index.new([0, 29, 25])
|
164
|
+
|
165
|
+
(index1 > index2).should be_true
|
166
|
+
end
|
167
|
+
|
168
|
+
it "returns true for minutes" do
|
169
|
+
index1 = RubyCue::Index.new([2, 30, 50])
|
170
|
+
index2 = RubyCue::Index.new([1, 29, 25])
|
171
|
+
|
172
|
+
(index1 > index2).should be_true
|
173
|
+
end
|
174
|
+
|
175
|
+
it "returns true for the same time" do
|
176
|
+
index1 = RubyCue::Index.new([1, 30, 50])
|
177
|
+
index2 = RubyCue::Index.new([1, 30, 50])
|
178
|
+
|
179
|
+
(index1 > index2).should be_false
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
describe "#<" do
|
184
|
+
it "returns false for frames" do
|
185
|
+
index1 = RubyCue::Index.new([0, 0, 50])
|
186
|
+
index2 = RubyCue::Index.new([0, 0, 25])
|
187
|
+
|
188
|
+
(index1 < index2).should be_false
|
189
|
+
end
|
190
|
+
|
191
|
+
it "returns false for seconds" do
|
192
|
+
index1 = RubyCue::Index.new([0, 30, 50])
|
193
|
+
index2 = RubyCue::Index.new([0, 29, 25])
|
194
|
+
|
195
|
+
(index1 < index2).should be_false
|
196
|
+
end
|
197
|
+
|
198
|
+
it "returns false for minutes" do
|
199
|
+
index1 = RubyCue::Index.new([2, 30, 50])
|
200
|
+
index2 = RubyCue::Index.new([1, 29, 25])
|
201
|
+
|
202
|
+
(index1 < index2).should be_false
|
203
|
+
end
|
204
|
+
|
205
|
+
it "returns false for the same time" do
|
206
|
+
index1 = RubyCue::Index.new([1, 30, 50])
|
207
|
+
index2 = RubyCue::Index.new([1, 30, 50])
|
208
|
+
|
209
|
+
(index1 < index2).should be_false
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
describe "#==" do
|
214
|
+
it "returns true if they're the same" do
|
215
|
+
index1 = RubyCue::Index.new([1, 30, 50])
|
216
|
+
index2 = RubyCue::Index.new([1, 30, 50])
|
217
|
+
|
218
|
+
(index1 == index2).should be_true
|
219
|
+
end
|
220
|
+
|
221
|
+
it "returns false if they're not the same" do
|
222
|
+
index1 = RubyCue::Index.new([1, 30, 50])
|
223
|
+
index2 = RubyCue::Index.new([1, 30, 51])
|
224
|
+
|
225
|
+
(index1 == index2).should be_false
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
describe "#each" do
|
231
|
+
it "yields each minute, second, frame value" do
|
232
|
+
array = []
|
233
|
+
index = RubyCue::Index.new([1, 30, 45])
|
234
|
+
index.each do |value|
|
235
|
+
array << value
|
236
|
+
end
|
237
|
+
|
238
|
+
array.to_a.should == index.to_a
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
end
|
243
|
+
end
|
metadata
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rubycue
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Blake Smith
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-10-26 00:00:00 -05:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: Basic ruby parser for song cuesheets
|
23
|
+
email: blakesmith0@gmail.com
|
24
|
+
executables: []
|
25
|
+
|
26
|
+
extensions: []
|
27
|
+
|
28
|
+
extra_rdoc_files:
|
29
|
+
- README.rdoc
|
30
|
+
files:
|
31
|
+
- .gitignore
|
32
|
+
- MIT-LICENSE
|
33
|
+
- README.rdoc
|
34
|
+
- Rakefile
|
35
|
+
- VERSION
|
36
|
+
- lib/rubycue.rb
|
37
|
+
- lib/rubycue/cuesheet.rb
|
38
|
+
- lib/rubycue/exceptions.rb
|
39
|
+
- lib/rubycue/index.rb
|
40
|
+
- spec/fixtures/malformed.cue
|
41
|
+
- spec/fixtures/test.cue
|
42
|
+
- spec/spec_helper.rb
|
43
|
+
- spec/unit/cuesheet_spec.rb
|
44
|
+
- spec/unit/index_spec.rb
|
45
|
+
has_rdoc: true
|
46
|
+
homepage: http://github.com/blakesmith/rubycue
|
47
|
+
licenses: []
|
48
|
+
|
49
|
+
post_install_message:
|
50
|
+
rdoc_options:
|
51
|
+
- --charset=UTF-8
|
52
|
+
require_paths:
|
53
|
+
- lib
|
54
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
hash: 3
|
60
|
+
segments:
|
61
|
+
- 0
|
62
|
+
version: "0"
|
63
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
64
|
+
none: false
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
hash: 3
|
69
|
+
segments:
|
70
|
+
- 0
|
71
|
+
version: "0"
|
72
|
+
requirements: []
|
73
|
+
|
74
|
+
rubyforge_project:
|
75
|
+
rubygems_version: 1.3.7
|
76
|
+
signing_key:
|
77
|
+
specification_version: 3
|
78
|
+
summary: Ruby cuesheet track parser
|
79
|
+
test_files:
|
80
|
+
- spec/spec_helper.rb
|
81
|
+
- spec/unit/cuesheet_spec.rb
|
82
|
+
- spec/unit/index_spec.rb
|