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 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 be_nil
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
@@ -3,6 +3,4 @@ require_relative 'rtsp/version'
3
3
 
4
4
  # This base module simply defines properties about the library. See child
5
5
  # classes/modules for the meat.
6
- module RTSP
7
-
8
- end
6
+ module RTSP; end
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 +RTSP::Capturer+ and a Connection Struct.
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 [RTSP::Capturer]
84
- # @return [RTSP::Capturer]
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, RTSP::Capturer]
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 = RTSP::Capturer.new
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
- # 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.
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 { |header| header.capitalize }.join('-')
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 values
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, "#{self.class} received nil string--this shouldn't happen."
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 response
81
- # code, response message, response version, and creates a snake-case
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 that's
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
@@ -1,4 +1,4 @@
1
1
  module RTSP
2
2
  # rtsp version
3
- VERSION = "0.2.2"
3
+ VERSION = "0.3.0"
4
4
  end
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.required_rubygems_version = Gem::Requirement.new(">= 1.3.6") if s.respond_to? :required_rubygems_version=
12
- s.authors = ["Steve Loveless, Mike Kirby"]
13
- s.date = %q{2011-04-14}
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 = ["steve.loveless@gmail.com, mkiby@gmail.com"]
19
- s.executables = ["rtsp_client"]
20
- s.extra_rdoc_files = [
21
- "ChangeLog.rdoc",
22
- "LICENSE.rdoc",
23
- "README.rdoc"
24
- ]
25
- s.files = Dir.glob("{lib,bin,tasks}/**/*") +
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>, ["~> 1.1.0"])
37
- s.add_runtime_dependency(%q<sdp>, ["~> 0.2.2"])
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>, ["~> 1.0.0"])
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<metric_fu>, [">= 2.0.0"])
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"])
@@ -1,7 +1,7 @@
1
1
  require 'sdp'
2
2
  require_relative '../spec_helper'
3
3
  require 'rtsp/client'
4
- require 'support/fake_rtsp_server'
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
- RTSP::Capturer.any_instance.stub(:run)
24
- RTSP::Capturer.any_instance.stub(:stop)
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
@@ -0,0 +1,9 @@
1
+ require 'rake/tasklib' # roodi_task fails without this.
2
+ require 'roodi'
3
+ require 'roodi_task'
4
+
5
+ RoodiTask.new do |t|
6
+ t.config = 'tasks/roodi_config.yaml'
7
+ t.patterns = Dir.glob("{features,lib,spec}/**/*.rb")
8
+ t.verbose = true
9
+ end
@@ -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.2.2
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: 2011-04-14 00:00:00.000000000 Z
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: &70200108735200 !ruby/object:Gem::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: *70200108735200
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: &70200108733900 !ruby/object:Gem::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.2
44
+ version: 0.2.6
33
45
  type: :runtime
34
46
  prerelease: false
35
- version_requirements: *70200108733900
47
+ version_requirements: *70350646950580
36
48
  - !ruby/object:Gem::Dependency
37
49
  name: bundler
38
- requirement: &70200108733140 !ruby/object:Gem::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: 1.0.0
55
+ version: '0'
44
56
  type: :development
45
57
  prerelease: false
46
- version_requirements: *70200108733140
58
+ version_requirements: *70350646949960
47
59
  - !ruby/object:Gem::Dependency
48
60
  name: code_statistics
49
- requirement: &70200108731600 !ruby/object:Gem::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: *70200108731600
69
+ version_requirements: *70350646948280
58
70
  - !ruby/object:Gem::Dependency
59
- name: metric_fu
60
- requirement: &70200108731040 !ruby/object:Gem::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: 2.0.0
77
+ version: 1.1.0
66
78
  type: :development
67
79
  prerelease: false
68
- version_requirements: *70200108731040
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: &70200108730460 !ruby/object:Gem::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: *70200108730460
113
+ version_requirements: *70350646943460
80
114
  - !ruby/object:Gem::Dependency
81
115
  name: simplecov
82
- requirement: &70200108729440 !ruby/object:Gem::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: *70200108729440
124
+ version_requirements: *70350646942580
91
125
  - !ruby/object:Gem::Dependency
92
126
  name: yard
93
- requirement: &70200108727820 !ruby/object:Gem::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: *70200108727820
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, mkiby@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: 1.3.6
208
+ version: '0'
177
209
  requirements: []
178
- rubyforge_project: rtsp
179
- rubygems_version: 1.8.10
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
@@ -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