rtsp 0.2.2 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog.rdoc +7 -0
- data/features/step_definitions/client_requests_steps.rb +1 -1
- data/lib/rtsp.rb +1 -3
- data/lib/rtsp/client.rb +7 -8
- data/lib/rtsp/message.rb +7 -5
- data/lib/rtsp/response.rb +8 -7
- data/lib/rtsp/version.rb +1 -1
- data/rtsp.gemspec +18 -22
- data/spec/rtsp/client_spec.rb +3 -3
- data/tasks/roodi.rake +9 -0
- data/tasks/{roodi_config.yml → roodi_config.yaml} +3 -3
- metadata +72 -41
- data/lib/rtsp/capturer.rb +0 -223
- data/spec/rtsp/capturer_spec.rb +0 -258
- data/tasks/metrics.rake +0 -27
data/ChangeLog.rdoc
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
=== 0.3.0 / 2012-03-02
|
2
|
+
|
3
|
+
* Extracted RTP-esque functionality to an +rtp+ gem, on which this gem is now
|
4
|
+
dependent on version 0.0.1 of that.
|
5
|
+
* Laxed dependency requirement on parslet.
|
6
|
+
* Bumped dependency requirement on sdp to ~> 0.2.6, due to parslet conflicts
|
7
|
+
|
1
8
|
=== 0.2.2 / 2011-11-02
|
2
9
|
|
3
10
|
* Added a queue for listening and building the RTP file from the received data.
|
@@ -41,7 +41,7 @@ Then /^I should receive an RTSP response to that OPTIONS request$/ do
|
|
41
41
|
@response.message.should == "OK"
|
42
42
|
@response.cseq.should == 1
|
43
43
|
@response.public.should == "DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE"
|
44
|
-
@response.body.should
|
44
|
+
@response.body.should be_empty
|
45
45
|
end
|
46
46
|
|
47
47
|
Then /^I should receive an RTSP response to that DESCRIBE request$/ do
|
data/lib/rtsp.rb
CHANGED
data/lib/rtsp/client.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
require 'socket'
|
2
2
|
require 'tempfile'
|
3
3
|
require 'timeout'
|
4
|
+
require 'rtp/receiver'
|
4
5
|
|
5
6
|
require_relative 'transport_parser'
|
6
|
-
require_relative 'capturer'
|
7
7
|
require_relative 'error'
|
8
8
|
require_relative 'global'
|
9
9
|
require_relative 'helpers'
|
@@ -13,7 +13,7 @@ require_relative 'response'
|
|
13
13
|
module RTSP
|
14
14
|
|
15
15
|
# This is the main interface to an RTSP server. A client object uses a couple
|
16
|
-
# main objects for configuration: an +
|
16
|
+
# main objects for configuration: an +RTP::Receiver+ and a Connection Struct.
|
17
17
|
# Use the capturer to configure how to capture the data which is the RTP
|
18
18
|
# stream provided by the RTSP server. Use the connection object to control
|
19
19
|
# the connection to the server.
|
@@ -56,7 +56,6 @@ module RTSP
|
|
56
56
|
include RTSP::Helpers
|
57
57
|
extend RTSP::Global
|
58
58
|
|
59
|
-
DEFAULT_CAPFILE_NAME = "ruby_rtsp_capture.rtsp"
|
60
59
|
MAX_BYTES_TO_RECEIVE = 3000
|
61
60
|
|
62
61
|
# @return [URI] The URI that points to the RTSP server's resource.
|
@@ -80,8 +79,8 @@ module RTSP
|
|
80
79
|
attr_accessor :connection
|
81
80
|
|
82
81
|
# Use to get/set an object for capturing received data.
|
83
|
-
# @param [
|
84
|
-
# @return [
|
82
|
+
# @param [RTP::Receiver]
|
83
|
+
# @return [RTP::Receiver]
|
85
84
|
attr_accessor :capturer
|
86
85
|
|
87
86
|
# @return [Symbol] See {RFC section A.1.}[http://tools.ietf.org/html/rfc2326#page-76]
|
@@ -95,7 +94,7 @@ module RTSP
|
|
95
94
|
|
96
95
|
# @param [String] server_url URL to the resource to stream. If no scheme is
|
97
96
|
# given, "rtsp" is assumed. If no port is given, 554 is assumed.
|
98
|
-
# @yield [Struct::Connection,
|
97
|
+
# @yield [Struct::Connection, RTP::Receiver]
|
99
98
|
# @yieldparam [Struct::Connection] server_url=
|
100
99
|
# @yieldparam [Struct::Connection] timeout=
|
101
100
|
# @yieldparam [Struct::Connection] socket=
|
@@ -111,7 +110,7 @@ module RTSP
|
|
111
110
|
end
|
112
111
|
|
113
112
|
@connection = Struct::Connection.new
|
114
|
-
@capturer =
|
113
|
+
@capturer = RTP::Receiver.new
|
115
114
|
|
116
115
|
yield(connection, capturer) if block_given?
|
117
116
|
|
@@ -124,7 +123,7 @@ module RTSP
|
|
124
123
|
@capturer.rtp_port ||= 9000
|
125
124
|
@capturer.transport_protocol ||= :UDP
|
126
125
|
@capturer.broadcast_type ||= :unicast
|
127
|
-
@capturer.rtp_file ||= Tempfile.new(DEFAULT_CAPFILE_NAME)
|
126
|
+
@capturer.rtp_file ||= Tempfile.new(RTP::Receiver::DEFAULT_CAPFILE_NAME)
|
128
127
|
|
129
128
|
@play_thread = nil
|
130
129
|
@cseq = 1
|
data/lib/rtsp/message.rb
CHANGED
@@ -138,8 +138,8 @@ module RTSP
|
|
138
138
|
end
|
139
139
|
|
140
140
|
# @param [String] value Content to send as the body of the message.
|
141
|
-
#
|
142
|
-
#
|
141
|
+
# Generally this will be a String of some sort, but could be binary data as
|
142
|
+
# well. Also, this adds the Content-Length header to the header list.
|
143
143
|
def body= value
|
144
144
|
add_body value
|
145
145
|
end
|
@@ -201,7 +201,9 @@ module RTSP
|
|
201
201
|
# @return [String]
|
202
202
|
def headers_to_s headers
|
203
203
|
header_string = headers.inject("") do |result, (key, value)|
|
204
|
-
header_name = key.to_s.split(/_/).map
|
204
|
+
header_name = key.to_s.split(/_/).map do |header|
|
205
|
+
header.capitalize
|
206
|
+
end.join('-')
|
205
207
|
|
206
208
|
header_name = "CSeq" if header_name == "Cseq"
|
207
209
|
|
@@ -248,8 +250,8 @@ module RTSP
|
|
248
250
|
# Turns header values into a single string.
|
249
251
|
#
|
250
252
|
# @param [] values The header values to put to string.
|
251
|
-
# @param [String] separator The character to use to separate multiple
|
252
|
-
# that define a header.
|
253
|
+
# @param [String] separator The character to use to separate multiple
|
254
|
+
# values that define a header.
|
253
255
|
# @return [String] The header values as a single string.
|
254
256
|
def values_to_s(values, separator=";")
|
255
257
|
result = values.inject("") do |values_string, (header_field, header_field_value)|
|
data/lib/rtsp/response.rb
CHANGED
@@ -16,7 +16,8 @@ module RTSP
|
|
16
16
|
# server/client.
|
17
17
|
def initialize(raw_response)
|
18
18
|
if raw_response.nil? || raw_response.empty?
|
19
|
-
raise RTSP::Error,
|
19
|
+
raise RTSP::Error,
|
20
|
+
"#{self.class} received nil string--this shouldn't happen."
|
20
21
|
end
|
21
22
|
|
22
23
|
@raw_response = raw_response
|
@@ -77,9 +78,9 @@ module RTSP
|
|
77
78
|
end
|
78
79
|
end
|
79
80
|
|
80
|
-
# Reads through each header line of the RTSP response, extracts the
|
81
|
-
# code, response message, response version, and creates a
|
82
|
-
# accessor with that value set.
|
81
|
+
# Reads through each header line of the RTSP response, extracts the
|
82
|
+
# response code, response message, response version, and creates a
|
83
|
+
# snake-case accessor with that value set.
|
83
84
|
#
|
84
85
|
# @param [String] head The section of headers from the response text.
|
85
86
|
def parse_head head
|
@@ -90,7 +91,7 @@ module RTSP
|
|
90
91
|
extract_status_line(line)
|
91
92
|
next
|
92
93
|
end
|
93
|
-
|
94
|
+
|
94
95
|
if line.include? ": "
|
95
96
|
header_and_value = line.strip.split(":", 2)
|
96
97
|
header_name = header_and_value.first.downcase.gsub(/-/, "_")
|
@@ -119,8 +120,8 @@ module RTSP
|
|
119
120
|
|
120
121
|
private
|
121
122
|
|
122
|
-
# Creates an attr_reader with the name given and sets it to the value
|
123
|
-
# given.
|
123
|
+
# Creates an attr_reader with the name given and sets it to the value
|
124
|
+
# that's given.
|
124
125
|
#
|
125
126
|
# @param [String] name
|
126
127
|
# @param [String] value
|
data/lib/rtsp/version.rb
CHANGED
data/rtsp.gemspec
CHANGED
@@ -8,37 +8,33 @@ Gem::Specification.new do |s|
|
|
8
8
|
s.name = "rtsp"
|
9
9
|
s.version = RTSP::VERSION
|
10
10
|
|
11
|
-
s.
|
12
|
-
s.authors = ["Steve Loveless, Mike Kirby"]
|
13
|
-
s.
|
11
|
+
s.homepage = %q{http://rubygems.org/gems/rtsp}
|
12
|
+
s.authors = ["Steve Loveless, Mike Kirby", "Sujin Philip"]
|
13
|
+
s.summary = %q{Library to allow RTSP streaming from RTSP-enabled devices.}
|
14
14
|
s.description = %q{This library intends to follow the RTSP RFC document (2326)
|
15
15
|
to allow for working with RTSP servers. At this point, it's up to you to parse
|
16
16
|
the data from a play call, but we'll get there. ...eventually.
|
17
17
|
For more information see: http://www.ietf.org/rfc/rfc2326.txt}
|
18
|
-
s.email =
|
19
|
-
s.
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
s.
|
26
|
-
%w(.gemtest rtsp.gemspec) +
|
27
|
-
%w(Gemfile ChangeLog.rdoc LICENSE.rdoc README.rdoc Rakefile)
|
28
|
-
s.homepage = %q{http://rubygems.org/gems/rtsp}
|
29
|
-
s.licenses = ["MIT"]
|
30
|
-
s.require_paths = ["lib"]
|
31
|
-
s.rubyforge_project = %q{rtsp}
|
18
|
+
s.email = %w{steve.loveless@gmail.com}
|
19
|
+
s.licenses = %w{MIT}
|
20
|
+
|
21
|
+
s.executables = %w{rtsp_client}
|
22
|
+
s.files = Dir.glob("{lib,bin,spec,tasks}/**/*") + Dir.glob("*.rdoc") +
|
23
|
+
%w(.gemtest rtsp.gemspec Gemfile Rakefile)
|
24
|
+
s.extra_rdoc_files = %w{ChangeLog.rdoc LICENSE.rdoc README.rdoc}
|
25
|
+
s.require_paths = %w{lib}
|
32
26
|
s.rubygems_version = %q{1.7.2}
|
33
|
-
s.summary = %q{Library to allow RTSP streaming from RTSP-enabled devices.}
|
34
27
|
s.test_files = Dir.glob("{spec,features}/**/*")
|
35
28
|
|
36
|
-
s.add_runtime_dependency(%q<parslet>, ["
|
37
|
-
s.add_runtime_dependency(%q<
|
29
|
+
s.add_runtime_dependency(%q<parslet>, [">= 1.1.0"])
|
30
|
+
s.add_runtime_dependency(%q<rtp>, [">= 0.0.1"])
|
31
|
+
s.add_runtime_dependency(%q<sdp>, ["~> 0.2.6"])
|
38
32
|
|
39
|
-
s.add_development_dependency(%q<bundler
|
33
|
+
s.add_development_dependency(%q<bundler>)
|
40
34
|
s.add_development_dependency(%q<code_statistics>, ["~> 0.2.13"])
|
41
|
-
s.add_development_dependency(%q<
|
35
|
+
s.add_development_dependency(%q<cucumber>, [">= 1.1.0"])
|
36
|
+
s.add_development_dependency(%q<roodi>, [">= 2.1.0"])
|
37
|
+
s.add_development_dependency(%q<rake>, [">= 0.8.7"])
|
42
38
|
s.add_development_dependency(%q<rspec>, [">= 2.5.0"])
|
43
39
|
s.add_development_dependency(%q<simplecov>, [">= 0.4.0"])
|
44
40
|
s.add_development_dependency(%q<yard>, [">= 0.6.0"])
|
data/spec/rtsp/client_spec.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'sdp'
|
2
2
|
require_relative '../spec_helper'
|
3
3
|
require 'rtsp/client'
|
4
|
-
|
4
|
+
require_relative '../support/fake_rtsp_server'
|
5
5
|
|
6
6
|
describe RTSP::Client do
|
7
7
|
def setup_client_at(url)
|
@@ -20,8 +20,8 @@ describe RTSP::Client do
|
|
20
20
|
end
|
21
21
|
|
22
22
|
before do
|
23
|
-
|
24
|
-
|
23
|
+
RTP::Receiver.any_instance.stub(:run)
|
24
|
+
RTP::Receiver.any_instance.stub(:stop)
|
25
25
|
end
|
26
26
|
|
27
27
|
describe "#initialize" do
|
data/tasks/roodi.rake
ADDED
@@ -2,13 +2,13 @@
|
|
2
2
|
AssignmentInConditionalCheck: { }
|
3
3
|
CaseMissingElseCheck: { }
|
4
4
|
ClassLineCountCheck: { line_count: 300 }
|
5
|
-
ClassNameCheck: { pattern: !ruby/regexp /^[A-Z][a-zA-Z0-9]*$/ }
|
5
|
+
ClassNameCheck: { pattern: !ruby/regexp '/^[A-Z][a-zA-Z0-9]*$/' }
|
6
6
|
CyclomaticComplexityBlockCheck: { complexity: 4 }
|
7
7
|
CyclomaticComplexityMethodCheck: { complexity: 8 }
|
8
8
|
EmptyRescueBodyCheck: { }
|
9
9
|
ForLoopCheck: { }
|
10
10
|
MethodLineCountCheck: { line_count: 30 }
|
11
|
-
MethodNameCheck: { pattern: !ruby/regexp /^[_a-z<>=\[\]|+-\/\*`]+[_a-z0-9_<>=~@\[\]]*[=!\?]?$/ }
|
11
|
+
MethodNameCheck: { pattern: !ruby/regexp '/^[_a-z<>=\[\]|+-\/\*`]+[_a-z0-9_<>=~@\[\]]*[=!\?]?$/' }
|
12
12
|
ModuleLineCountCheck: { line_count: 300 }
|
13
|
-
ModuleNameCheck: { pattern: !ruby/regexp /^[A-Z][a-zA-Z0-9]*$/ }
|
13
|
+
ModuleNameCheck: { pattern: !ruby/regexp '/^[A-Z][a-zA-Z0-9]*$/' }
|
14
14
|
ParameterNumberCheck: { parameter_count: 5 }
|
metadata
CHANGED
@@ -1,52 +1,64 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rtsp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Steve Loveless, Mike Kirby
|
9
|
+
- Sujin Philip
|
9
10
|
autorequire:
|
10
11
|
bindir: bin
|
11
12
|
cert_chain: []
|
12
|
-
date:
|
13
|
+
date: 2012-03-03 00:00:00.000000000 Z
|
13
14
|
dependencies:
|
14
15
|
- !ruby/object:Gem::Dependency
|
15
16
|
name: parslet
|
16
|
-
requirement: &
|
17
|
+
requirement: &70350646954280 !ruby/object:Gem::Requirement
|
17
18
|
none: false
|
18
19
|
requirements:
|
19
|
-
- -
|
20
|
+
- - ! '>='
|
20
21
|
- !ruby/object:Gem::Version
|
21
22
|
version: 1.1.0
|
22
23
|
type: :runtime
|
23
24
|
prerelease: false
|
24
|
-
version_requirements: *
|
25
|
+
version_requirements: *70350646954280
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: rtp
|
28
|
+
requirement: &70350646952740 !ruby/object:Gem::Requirement
|
29
|
+
none: false
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.0.1
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: *70350646952740
|
25
37
|
- !ruby/object:Gem::Dependency
|
26
38
|
name: sdp
|
27
|
-
requirement: &
|
39
|
+
requirement: &70350646950580 !ruby/object:Gem::Requirement
|
28
40
|
none: false
|
29
41
|
requirements:
|
30
42
|
- - ~>
|
31
43
|
- !ruby/object:Gem::Version
|
32
|
-
version: 0.2.
|
44
|
+
version: 0.2.6
|
33
45
|
type: :runtime
|
34
46
|
prerelease: false
|
35
|
-
version_requirements: *
|
47
|
+
version_requirements: *70350646950580
|
36
48
|
- !ruby/object:Gem::Dependency
|
37
49
|
name: bundler
|
38
|
-
requirement: &
|
50
|
+
requirement: &70350646949960 !ruby/object:Gem::Requirement
|
39
51
|
none: false
|
40
52
|
requirements:
|
41
|
-
- -
|
53
|
+
- - ! '>='
|
42
54
|
- !ruby/object:Gem::Version
|
43
|
-
version:
|
55
|
+
version: '0'
|
44
56
|
type: :development
|
45
57
|
prerelease: false
|
46
|
-
version_requirements: *
|
58
|
+
version_requirements: *70350646949960
|
47
59
|
- !ruby/object:Gem::Dependency
|
48
60
|
name: code_statistics
|
49
|
-
requirement: &
|
61
|
+
requirement: &70350646948280 !ruby/object:Gem::Requirement
|
50
62
|
none: false
|
51
63
|
requirements:
|
52
64
|
- - ~>
|
@@ -54,21 +66,43 @@ dependencies:
|
|
54
66
|
version: 0.2.13
|
55
67
|
type: :development
|
56
68
|
prerelease: false
|
57
|
-
version_requirements: *
|
69
|
+
version_requirements: *70350646948280
|
58
70
|
- !ruby/object:Gem::Dependency
|
59
|
-
name:
|
60
|
-
requirement: &
|
71
|
+
name: cucumber
|
72
|
+
requirement: &70350646946800 !ruby/object:Gem::Requirement
|
61
73
|
none: false
|
62
74
|
requirements:
|
63
75
|
- - ! '>='
|
64
76
|
- !ruby/object:Gem::Version
|
65
|
-
version:
|
77
|
+
version: 1.1.0
|
66
78
|
type: :development
|
67
79
|
prerelease: false
|
68
|
-
version_requirements: *
|
80
|
+
version_requirements: *70350646946800
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: roodi
|
83
|
+
requirement: &70350646945400 !ruby/object:Gem::Requirement
|
84
|
+
none: false
|
85
|
+
requirements:
|
86
|
+
- - ! '>='
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: 2.1.0
|
89
|
+
type: :development
|
90
|
+
prerelease: false
|
91
|
+
version_requirements: *70350646945400
|
92
|
+
- !ruby/object:Gem::Dependency
|
93
|
+
name: rake
|
94
|
+
requirement: &70350646944500 !ruby/object:Gem::Requirement
|
95
|
+
none: false
|
96
|
+
requirements:
|
97
|
+
- - ! '>='
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: 0.8.7
|
100
|
+
type: :development
|
101
|
+
prerelease: false
|
102
|
+
version_requirements: *70350646944500
|
69
103
|
- !ruby/object:Gem::Dependency
|
70
104
|
name: rspec
|
71
|
-
requirement: &
|
105
|
+
requirement: &70350646943460 !ruby/object:Gem::Requirement
|
72
106
|
none: false
|
73
107
|
requirements:
|
74
108
|
- - ! '>='
|
@@ -76,10 +110,10 @@ dependencies:
|
|
76
110
|
version: 2.5.0
|
77
111
|
type: :development
|
78
112
|
prerelease: false
|
79
|
-
version_requirements: *
|
113
|
+
version_requirements: *70350646943460
|
80
114
|
- !ruby/object:Gem::Dependency
|
81
115
|
name: simplecov
|
82
|
-
requirement: &
|
116
|
+
requirement: &70350646942580 !ruby/object:Gem::Requirement
|
83
117
|
none: false
|
84
118
|
requirements:
|
85
119
|
- - ! '>='
|
@@ -87,10 +121,10 @@ dependencies:
|
|
87
121
|
version: 0.4.0
|
88
122
|
type: :development
|
89
123
|
prerelease: false
|
90
|
-
version_requirements: *
|
124
|
+
version_requirements: *70350646942580
|
91
125
|
- !ruby/object:Gem::Dependency
|
92
126
|
name: yard
|
93
|
-
requirement: &
|
127
|
+
requirement: &70350646941760 !ruby/object:Gem::Requirement
|
94
128
|
none: false
|
95
129
|
requirements:
|
96
130
|
- - ! '>='
|
@@ -98,7 +132,7 @@ dependencies:
|
|
98
132
|
version: 0.6.0
|
99
133
|
type: :development
|
100
134
|
prerelease: false
|
101
|
-
version_requirements: *
|
135
|
+
version_requirements: *70350646941760
|
102
136
|
description: ! 'This library intends to follow the RTSP RFC document (2326)
|
103
137
|
|
104
138
|
to allow for working with RTSP servers. At this point, it''s up to you to parse
|
@@ -107,7 +141,7 @@ description: ! 'This library intends to follow the RTSP RFC document (2326)
|
|
107
141
|
|
108
142
|
For more information see: http://www.ietf.org/rfc/rfc2326.txt'
|
109
143
|
email:
|
110
|
-
- steve.loveless@gmail.com
|
144
|
+
- steve.loveless@gmail.com
|
111
145
|
executables:
|
112
146
|
- rtsp_client
|
113
147
|
extensions: []
|
@@ -117,7 +151,6 @@ extra_rdoc_files:
|
|
117
151
|
- README.rdoc
|
118
152
|
files:
|
119
153
|
- lib/ext/logger.rb
|
120
|
-
- lib/rtsp/capturer.rb
|
121
154
|
- lib/rtsp/client.rb
|
122
155
|
- lib/rtsp/error.rb
|
123
156
|
- lib/rtsp/global.rb
|
@@ -128,17 +161,6 @@ files:
|
|
128
161
|
- lib/rtsp/version.rb
|
129
162
|
- lib/rtsp.rb
|
130
163
|
- bin/rtsp_client
|
131
|
-
- tasks/metrics.rake
|
132
|
-
- tasks/roodi_config.yml
|
133
|
-
- tasks/stats.rake
|
134
|
-
- .gemtest
|
135
|
-
- rtsp.gemspec
|
136
|
-
- Gemfile
|
137
|
-
- ChangeLog.rdoc
|
138
|
-
- LICENSE.rdoc
|
139
|
-
- README.rdoc
|
140
|
-
- Rakefile
|
141
|
-
- spec/rtsp/capturer_spec.rb
|
142
164
|
- spec/rtsp/client_spec.rb
|
143
165
|
- spec/rtsp/helpers_spec.rb
|
144
166
|
- spec/rtsp/message_spec.rb
|
@@ -147,6 +169,16 @@ files:
|
|
147
169
|
- spec/rtsp_spec.rb
|
148
170
|
- spec/spec_helper.rb
|
149
171
|
- spec/support/fake_rtsp_server.rb
|
172
|
+
- tasks/roodi.rake
|
173
|
+
- tasks/roodi_config.yaml
|
174
|
+
- tasks/stats.rake
|
175
|
+
- ChangeLog.rdoc
|
176
|
+
- LICENSE.rdoc
|
177
|
+
- README.rdoc
|
178
|
+
- .gemtest
|
179
|
+
- rtsp.gemspec
|
180
|
+
- Gemfile
|
181
|
+
- Rakefile
|
150
182
|
- features/client_changes_state.feature
|
151
183
|
- features/client_requests.feature
|
152
184
|
- features/control_streams_as_client.feature
|
@@ -173,15 +205,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
173
205
|
requirements:
|
174
206
|
- - ! '>='
|
175
207
|
- !ruby/object:Gem::Version
|
176
|
-
version:
|
208
|
+
version: '0'
|
177
209
|
requirements: []
|
178
|
-
rubyforge_project:
|
179
|
-
rubygems_version: 1.8.
|
210
|
+
rubyforge_project:
|
211
|
+
rubygems_version: 1.8.17
|
180
212
|
signing_key:
|
181
213
|
specification_version: 3
|
182
214
|
summary: Library to allow RTSP streaming from RTSP-enabled devices.
|
183
215
|
test_files:
|
184
|
-
- spec/rtsp/capturer_spec.rb
|
185
216
|
- spec/rtsp/client_spec.rb
|
186
217
|
- spec/rtsp/helpers_spec.rb
|
187
218
|
- spec/rtsp/message_spec.rb
|
data/lib/rtsp/capturer.rb
DELETED
@@ -1,223 +0,0 @@
|
|
1
|
-
require 'tempfile'
|
2
|
-
require 'socket'
|
3
|
-
|
4
|
-
require_relative 'error'
|
5
|
-
|
6
|
-
module RTSP
|
7
|
-
|
8
|
-
# Objects of this type can be used with a +RTSP::Client+ object in order to
|
9
|
-
# capture the RTP data transmitted to the client as a result of an RTSP
|
10
|
-
# PLAY call.
|
11
|
-
#
|
12
|
-
# In this version, objects of this type don't do much other than just capture
|
13
|
-
# the data to a file; in later versions, objects of this type will be able
|
14
|
-
# to provide a "sink" and allow for ensuring that the received RTP packets
|
15
|
-
# will be reassembled in the correct order, as they're written to file
|
16
|
-
# (objects of this type don't don't currently allow for checking RTP sequence
|
17
|
-
# numbers on the data that's been received).
|
18
|
-
class Capturer
|
19
|
-
|
20
|
-
# Name of the file the data will be captured to unless #rtp_file is set.
|
21
|
-
DEFAULT_CAPFILE_NAME = "rtsp_capture.rtsp"
|
22
|
-
|
23
|
-
# Maximum number of bytes to receive on the socket.
|
24
|
-
MAX_BYTES_TO_RECEIVE = 3000
|
25
|
-
|
26
|
-
# Maximum times to retry using the next greatest port number.
|
27
|
-
MAX_PORT_NUMBER_RETRIES = 50
|
28
|
-
|
29
|
-
# @param [File] rtp_file The file to capture the RTP data to.
|
30
|
-
# @return [File]
|
31
|
-
attr_accessor :rtp_file
|
32
|
-
|
33
|
-
# @param [Fixnum] rtp_port The port on which to capture the RTP data.
|
34
|
-
# @return [Fixnum]
|
35
|
-
attr_accessor :rtp_port
|
36
|
-
|
37
|
-
# @param [Symbol] transport_protocol +:UDP+ or +:TCP+.
|
38
|
-
# @return [Symbol]
|
39
|
-
attr_accessor :transport_protocol
|
40
|
-
|
41
|
-
# @param [Symbol] broadcast_type +:multicast+ or +:unicast+.
|
42
|
-
# @return [Symbol]
|
43
|
-
attr_accessor :broadcast_type
|
44
|
-
|
45
|
-
# @param [Symbol] transport_protocol The type of socket to use for capturing
|
46
|
-
# the data. +:UDP+ or +:TCP+.
|
47
|
-
# @param [Fixnum] rtp_port The port on which to capture RTP data.
|
48
|
-
# @param [File] capture_file The file object to capture the RTP data to.
|
49
|
-
def initialize(transport_protocol=:UDP, rtp_port=9000, rtp_capture_file=nil)
|
50
|
-
@transport_protocol = transport_protocol
|
51
|
-
@rtp_port = rtp_port
|
52
|
-
@rtp_file = rtp_capture_file || Tempfile.new(DEFAULT_CAPFILE_NAME)
|
53
|
-
@listener = nil
|
54
|
-
@file_builder = nil
|
55
|
-
@queue = Queue.new
|
56
|
-
end
|
57
|
-
|
58
|
-
# Initializes a server of the correct socket type.
|
59
|
-
#
|
60
|
-
# @return [UDPSocket, TCPSocket]
|
61
|
-
# @raise [RTSP::Error] If +@transport_protocol was not set to +:UDP+ or
|
62
|
-
# +:TCP+.
|
63
|
-
def init_server(protocol, port=9000)
|
64
|
-
if protocol == :UDP
|
65
|
-
server = init_udp_server(port)
|
66
|
-
elsif protocol == :TCP
|
67
|
-
server = init_tcp_server(port)
|
68
|
-
else
|
69
|
-
raise RTSP::Error, "Unknown streaming_protocol requested: #{@transport_protocol}"
|
70
|
-
end
|
71
|
-
|
72
|
-
server
|
73
|
-
end
|
74
|
-
|
75
|
-
# Simply calls #start_file_builder and #start_listener.
|
76
|
-
def run
|
77
|
-
log "Starting #{self.class} on port #{@rtp_port}..."
|
78
|
-
|
79
|
-
start_file_builder
|
80
|
-
start_listener
|
81
|
-
end
|
82
|
-
|
83
|
-
# Starts the +@file_builder+ thread that pops data off of the Queue that
|
84
|
-
# #start_listener pushed data on to. It then takes that data and writes it
|
85
|
-
# to +@rtp_file+.
|
86
|
-
#
|
87
|
-
# @return [Thread] The file_builder thread (+@file_builder+)
|
88
|
-
def start_file_builder
|
89
|
-
return @file_builder if @file_builder and @file_builder.alive?
|
90
|
-
|
91
|
-
@file_builder = Thread.start(@rtp_file) do |rtp_file|
|
92
|
-
loop do
|
93
|
-
rtp_file.write @queue.pop until @queue.empty?
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
@file_builder.abort_on_exception = true
|
98
|
-
end
|
99
|
-
|
100
|
-
# Starts the +@listener+ thread that starts up the server, then takes the
|
101
|
-
# data received from the server and pushes it on to the +@queue+ so
|
102
|
-
# the +@file_builder+ thread can deal with it.
|
103
|
-
#
|
104
|
-
# @return [Thread] The listener thread (+@listener+).
|
105
|
-
def start_listener
|
106
|
-
return @listener if @listener and @listener.alive?
|
107
|
-
|
108
|
-
@listener = Thread.start do
|
109
|
-
server = init_server(@transport_protocol, @rtp_port)
|
110
|
-
|
111
|
-
loop do
|
112
|
-
data = server.recvfrom(MAX_BYTES_TO_RECEIVE).first
|
113
|
-
log "received data with size: #{data.size}"
|
114
|
-
@queue << data
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
@listener.abort_on_exception = true
|
119
|
-
end
|
120
|
-
|
121
|
-
# @return [Boolean] true if the +@listener+ thread is running; false if not.
|
122
|
-
def listening?
|
123
|
-
if @listener then @listener.alive? else false end
|
124
|
-
end
|
125
|
-
|
126
|
-
# @return [Boolean] true if the +@file_builder+ thread is running; false if
|
127
|
-
# not.
|
128
|
-
def file_building?
|
129
|
-
if @file_builder then @file_builder.alive? else false end
|
130
|
-
end
|
131
|
-
|
132
|
-
# Returns if the #run loop is in action.
|
133
|
-
#
|
134
|
-
# @return [Boolean] true if the run loop is running.
|
135
|
-
def running?
|
136
|
-
listening? || file_building?
|
137
|
-
end
|
138
|
-
|
139
|
-
# Breaks out of the run loop.
|
140
|
-
def stop
|
141
|
-
log "Stopping #{self.class} on port #{@rtp_port}..."
|
142
|
-
stop_listener
|
143
|
-
log "listening? #{listening?}"
|
144
|
-
stop_file_builder
|
145
|
-
log "file building? #{file_building?}"
|
146
|
-
log "running? #{running?}"
|
147
|
-
@queue = Queue.new
|
148
|
-
end
|
149
|
-
|
150
|
-
# Kills the +@listener+ thread and sets the variable to nil.
|
151
|
-
def stop_listener
|
152
|
-
@listener.kill if @listener
|
153
|
-
@listener = nil
|
154
|
-
end
|
155
|
-
|
156
|
-
# Kills the +@file_builder+ thread and sets the variable to nil.
|
157
|
-
def stop_file_builder
|
158
|
-
@file_builder.kill if @file_builder
|
159
|
-
@file_builder = nil
|
160
|
-
end
|
161
|
-
|
162
|
-
# Sets up to receive data on a UDP socket, using +@rtp_port+.
|
163
|
-
#
|
164
|
-
# @param [Fixnum] port Port number to listen for RTP data on.
|
165
|
-
# @return [UDPSocket]
|
166
|
-
def init_udp_server(port)
|
167
|
-
port_retries = 0
|
168
|
-
|
169
|
-
begin
|
170
|
-
server = UDPSocket.open
|
171
|
-
server.bind('0.0.0.0', port)
|
172
|
-
rescue Errno::EADDRINUSE
|
173
|
-
log "RTP port #{port} in use, trying #{port + 1}..."
|
174
|
-
port += 1
|
175
|
-
port_retries += 1
|
176
|
-
retry until port_retries == MAX_PORT_NUMBER_RETRIES + 1
|
177
|
-
port = 9000
|
178
|
-
raise
|
179
|
-
end
|
180
|
-
|
181
|
-
@rtp_port = port
|
182
|
-
log "UDP server setup to receive on port #{@rtp_port}"
|
183
|
-
|
184
|
-
server
|
185
|
-
end
|
186
|
-
|
187
|
-
# Sets up to receive data on a TCP socket, using +@rtp_port+.
|
188
|
-
#
|
189
|
-
# @param [Fixnum] port Port number to listen for RTP data on.
|
190
|
-
# @return [TCPServer]
|
191
|
-
def init_tcp_server(port)
|
192
|
-
port_retries = 0
|
193
|
-
|
194
|
-
begin
|
195
|
-
server = TCPServer.new(port)
|
196
|
-
rescue Errno::EADDRINUSE
|
197
|
-
log "RTP port #{port} in use, trying #{port + 1}..."
|
198
|
-
port += 1
|
199
|
-
port_retries += 1
|
200
|
-
retry until port_retries == MAX_PORT_NUMBER_RETRIES + 1
|
201
|
-
port = 9000
|
202
|
-
raise
|
203
|
-
end
|
204
|
-
|
205
|
-
@rtp_port = port
|
206
|
-
log "TCP server setup to receive on port #{@rtp_port}"
|
207
|
-
|
208
|
-
server
|
209
|
-
end
|
210
|
-
|
211
|
-
# PRIVATES!
|
212
|
-
private
|
213
|
-
|
214
|
-
# Quick wrapper for when not using RTSP::Client (i.e. during tests).
|
215
|
-
#
|
216
|
-
# @param [String] message The String to log.
|
217
|
-
def log(message)
|
218
|
-
if defined? RTSP::Client
|
219
|
-
RTSP::Client.log "<#{self.class}> #{message}"
|
220
|
-
end
|
221
|
-
end
|
222
|
-
end
|
223
|
-
end
|
data/spec/rtsp/capturer_spec.rb
DELETED
@@ -1,258 +0,0 @@
|
|
1
|
-
require_relative '../spec_helper'
|
2
|
-
require 'rtsp/capturer'
|
3
|
-
|
4
|
-
Thread.abort_on_exception = true
|
5
|
-
|
6
|
-
def use_udp_ports(range)
|
7
|
-
sockets = []
|
8
|
-
|
9
|
-
range.each do |port|
|
10
|
-
begin
|
11
|
-
socket = UDPSocket.open
|
12
|
-
socket.bind('0.0.0.0', port)
|
13
|
-
sockets << socket
|
14
|
-
rescue Errno::EADDRINUSE
|
15
|
-
# That's ok
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
sockets
|
20
|
-
end
|
21
|
-
|
22
|
-
describe RTSP::Capturer do
|
23
|
-
before do
|
24
|
-
if defined? RTSP::Client
|
25
|
-
RTSP::Client.log = false
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
describe "#initialize" do
|
30
|
-
context "with default parameters" do
|
31
|
-
it "uses UDP" do
|
32
|
-
subject.instance_variable_get(:@transport_protocol).should == :UDP
|
33
|
-
end
|
34
|
-
|
35
|
-
it "uses port 9000" do
|
36
|
-
subject.instance_variable_get(:@rtp_port).should == 9000
|
37
|
-
end
|
38
|
-
|
39
|
-
it "creates a new Tempfile" do
|
40
|
-
subject.instance_variable_get(:@rtp_file).should be_a Tempfile
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
context "non-default parameters" do
|
45
|
-
it "can use TCP" do
|
46
|
-
capturer = RTSP::Capturer.new(:TCP)
|
47
|
-
capturer.instance_variable_get(:@transport_protocol).should == :TCP
|
48
|
-
end
|
49
|
-
|
50
|
-
it "can take another port" do
|
51
|
-
capturer = RTSP::Capturer.new(:UDP, 12345)
|
52
|
-
capturer.instance_variable_get(:@rtp_port).should == 12345
|
53
|
-
end
|
54
|
-
|
55
|
-
it "can take an IO object" do
|
56
|
-
fd = IO.sysopen("/dev/null", "w")
|
57
|
-
io = IO.new(fd, 'w')
|
58
|
-
capturer = RTSP::Capturer.new(:UDP, 12345, io)
|
59
|
-
capturer.instance_variable_get(:@rtp_file).should be_a IO
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
it "isn't running" do
|
64
|
-
RTSP::Capturer.new.should_not be_running
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
describe "#init_server" do
|
69
|
-
context "UDP" do
|
70
|
-
it "calls #init_udp_server with port 9000" do
|
71
|
-
subject.should_receive(:init_udp_server).with(9000)
|
72
|
-
subject.init_server(:UDP)
|
73
|
-
end
|
74
|
-
|
75
|
-
it "returns a UDPSocket" do
|
76
|
-
subject.init_server(:UDP).should be_a(UDPSocket)
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
context "TCP" do
|
81
|
-
it "calls #init_tcp_server with port 9000" do
|
82
|
-
subject.should_receive(:init_tcp_server).with(9000)
|
83
|
-
subject.init_server(:TCP)
|
84
|
-
end
|
85
|
-
|
86
|
-
it "returns a TCPServer" do
|
87
|
-
subject.init_server(:TCP).should be_a(TCPServer)
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
it "raises an RTSP::Error when some other protocol is given" do
|
92
|
-
expect { subject.init_server(:BOBO) }.to raise_error RTSP::Error
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
describe "#init_udp_server" do
|
97
|
-
after :each do
|
98
|
-
unless @sockets.nil?
|
99
|
-
@sockets.each { |s| s.close }
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
it "returns a UDPSocket" do
|
104
|
-
server = subject.init_udp_server(subject.rtp_port)
|
105
|
-
server.should be_a UDPSocket
|
106
|
-
end
|
107
|
-
|
108
|
-
it "retries MAX_PORT_NUMBER_RETRIES to get a port" do
|
109
|
-
@sockets = use_udp_ports 9000...(9000 + RTSP::Capturer::MAX_PORT_NUMBER_RETRIES)
|
110
|
-
subject.init_udp_server(subject.rtp_port)
|
111
|
-
|
112
|
-
subject.rtp_port.should == 9000 + RTSP::Capturer::MAX_PORT_NUMBER_RETRIES
|
113
|
-
end
|
114
|
-
|
115
|
-
context "when no available ports, it retries MAX_PORT_NUMBER_RETRIES times, then" do
|
116
|
-
before do
|
117
|
-
@sockets = use_udp_ports 9000..(9000 + RTSP::Capturer::MAX_PORT_NUMBER_RETRIES)
|
118
|
-
end
|
119
|
-
|
120
|
-
it "retries MAX_PORT_NUMBER_RETRIES times then raises" do
|
121
|
-
expect { subject.init_udp_server(subject.rtp_port) }.to raise_error Errno::EADDRINUSE
|
122
|
-
end
|
123
|
-
|
124
|
-
it "sets @rtp_port back to 9000 after trying all" do
|
125
|
-
expect { subject.init_udp_server(subject.rtp_port) }.to raise_error Errno::EADDRINUSE
|
126
|
-
subject.rtp_port.should == 9000
|
127
|
-
end
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
describe "#init_tcp_server" do
|
132
|
-
it "returns a TCPSocket" do
|
133
|
-
subject.init_tcp_server(3456).should be_a TCPSocket
|
134
|
-
end
|
135
|
-
|
136
|
-
it "uses port a port between 9000 and 9000 + MAX_PORT_NUMBER_RETRIES" do
|
137
|
-
subject.init_tcp_server(9000)
|
138
|
-
subject.rtp_port.should >= 9000
|
139
|
-
subject.rtp_port.should <= 9000 + RTSP::Capturer::MAX_PORT_NUMBER_RETRIES
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
describe "#run" do
|
144
|
-
after(:each) { subject.stop }
|
145
|
-
|
146
|
-
it "calls #start_file_builder and #start_listener" do
|
147
|
-
subject.should_receive(:start_listener)
|
148
|
-
subject.should_receive(:start_file_builder)
|
149
|
-
subject.run
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
describe "#running?" do
|
154
|
-
after(:each) { subject.stop }
|
155
|
-
|
156
|
-
it "returns false before issuing #run" do
|
157
|
-
subject.running?.should be_false
|
158
|
-
end
|
159
|
-
|
160
|
-
it "returns true after running" do
|
161
|
-
subject.run
|
162
|
-
subject.running?.should be_true
|
163
|
-
end
|
164
|
-
|
165
|
-
it "returns false after running then stopping" do
|
166
|
-
subject.run
|
167
|
-
subject.running?.should be_true
|
168
|
-
subject.stop
|
169
|
-
subject.running?.should be_false
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
describe "#stop" do
|
174
|
-
it "calls #stop_listener" do
|
175
|
-
subject.should_receive(:stop_listener)
|
176
|
-
subject.stop
|
177
|
-
end
|
178
|
-
|
179
|
-
it "calls #stop_file_builder" do
|
180
|
-
subject.should_receive(:stop_file_builder)
|
181
|
-
subject.stop
|
182
|
-
end
|
183
|
-
|
184
|
-
it "sets @queue back to a new Queue" do
|
185
|
-
queue = subject.instance_variable_get(:@queue)
|
186
|
-
subject.stop
|
187
|
-
subject.instance_variable_get(:@queue).should_not equal queue
|
188
|
-
subject.instance_variable_get(:@queue).should_not be_nil
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
|
-
[
|
193
|
-
{
|
194
|
-
start_method: "start_file_builder",
|
195
|
-
stop_method: "stop_file_builder",
|
196
|
-
ivar: "@file_builder"
|
197
|
-
},
|
198
|
-
{
|
199
|
-
start_method: "start_listener",
|
200
|
-
stop_method: "stop_listener",
|
201
|
-
ivar: "@listener"
|
202
|
-
}
|
203
|
-
].each do |method_set|
|
204
|
-
describe "##{method_set[:start_method]}" do
|
205
|
-
before(:each) do
|
206
|
-
rtp_file = double "rtp_file"
|
207
|
-
rtp_file.stub(:write)
|
208
|
-
subject.rtp_file = rtp_file
|
209
|
-
|
210
|
-
server = double "A Server"
|
211
|
-
server.stub_chain(:recvfrom, :first).and_return("not nil")
|
212
|
-
subject.stub(:init_server).and_return(server)
|
213
|
-
end
|
214
|
-
|
215
|
-
after(:each) { subject.send(method_set[:stop_method].to_sym) }
|
216
|
-
|
217
|
-
it "starts the #{method_set[:ivar]} thread" do
|
218
|
-
subject.send(method_set[:start_method])
|
219
|
-
subject.instance_variable_get(method_set[:ivar].to_sym).should be_a Thread
|
220
|
-
end
|
221
|
-
|
222
|
-
it "returns the same #{method_set[:ivar]} if already started" do
|
223
|
-
subject.send(method_set[:start_method])
|
224
|
-
original_ivar = subject.instance_variable_get(method_set[:ivar].to_sym)
|
225
|
-
new_ivar = subject.send method_set[:start_method].to_sym
|
226
|
-
original_ivar.should equal new_ivar
|
227
|
-
end
|
228
|
-
|
229
|
-
if method_set[:start_method] == "start_listener"
|
230
|
-
it "pushes data on to the @queue" do
|
231
|
-
subject.start_listener
|
232
|
-
subject.instance_variable_get(:@queue).pop.should == "not nil"
|
233
|
-
end
|
234
|
-
end
|
235
|
-
end
|
236
|
-
|
237
|
-
describe "##{method_set[:stop_method]}" do
|
238
|
-
context "#{method_set[:ivar]} thread is running" do
|
239
|
-
before { subject.send(method_set[:start_method]) }
|
240
|
-
|
241
|
-
it "kills the thread" do
|
242
|
-
original_ivar = subject.instance_variable_get(method_set[:ivar].to_sym)
|
243
|
-
original_ivar.should_receive(:kill)
|
244
|
-
subject.send(method_set[:stop_method])
|
245
|
-
end
|
246
|
-
end
|
247
|
-
|
248
|
-
context "#{method_set[:ivar]} thread isn't running" do
|
249
|
-
it "doesn't try to kill the thread" do
|
250
|
-
allow_message_expectations_on_nil
|
251
|
-
original_ivar = subject.instance_variable_get(method_set[:ivar].to_sym)
|
252
|
-
original_ivar.should_not_receive(:kill)
|
253
|
-
subject.send(method_set[:stop_method])
|
254
|
-
end
|
255
|
-
end
|
256
|
-
end
|
257
|
-
end
|
258
|
-
end
|
data/tasks/metrics.rake
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
require 'metric_fu'
|
2
|
-
|
3
|
-
MetricFu::Configuration.run do |config|
|
4
|
-
#define which metrics you want to use
|
5
|
-
#config.metrics = [:churn, :flog, :flay, :reek, :roodi, :rcov, :stats]
|
6
|
-
config.metrics = [:churn, :flay, :reek, :roodi, :rcov, :stats]
|
7
|
-
#config.graphs = [:flog, :flay, :reek, :roodi, :rcov, :stats]
|
8
|
-
config.graphs = [:flay, :reek, :roodi, :rcov, :stats]
|
9
|
-
config.churn = { :start_date => "1 year ago", :minimum_churn_count => 10 }
|
10
|
-
config.flay = { :dirs_to_flay => ['lib'],
|
11
|
-
:minimum_score => 10,
|
12
|
-
:filetypes => ['rb', 'erb'] }
|
13
|
-
config.flog = { :dirs_to_flog => ['lib'] }
|
14
|
-
config.rcov = { :environment => 'test',
|
15
|
-
:test_files => ["spec/**/*_spec.rb"],
|
16
|
-
:rcov_opts => ["--sort coverage",
|
17
|
-
"--no-html",
|
18
|
-
"--text-coverage",
|
19
|
-
"--spec-only",
|
20
|
-
"--no-color",
|
21
|
-
"--profile",
|
22
|
-
"--exclude /gems/,/Library/"]
|
23
|
-
}
|
24
|
-
config.reek = { :dirs_to_reek => ['lib'] }
|
25
|
-
config.roodi = { :dirs_to_roodi => ['lib'], :roodi_config => "tasks/roodi_config.yml" }
|
26
|
-
config.graph_engine = :bluff
|
27
|
-
end
|