rtsp 0.4.1 → 0.4.2

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.
Files changed (105) hide show
  1. data/ChangeLog.rdoc +10 -0
  2. data/Gemfile +1 -1
  3. data/README.rdoc +52 -38
  4. data/Rakefile +2 -8
  5. data/bin/rtsp_client +3 -3
  6. data/lib/rtsp/client.rb +69 -85
  7. data/lib/rtsp/message.rb +4 -5
  8. data/lib/rtsp/presentation.rb +1 -1
  9. data/lib/rtsp/session.rb +1 -1
  10. data/lib/rtsp/version.rb +1 -1
  11. data/rtsp.gemspec +13 -14
  12. data/spec/integration/client_use_spec.rb +206 -0
  13. data/spec/integration/coverage/index.html +1 -1
  14. data/spec/spec_helper.rb +2 -1
  15. data/spec/support/fake_rtsp_server.rb +1 -1
  16. data/spec/unit/rtsp/client_spec.rb +407 -0
  17. data/spec/{rtsp → unit/rtsp}/helpers_spec.rb +1 -1
  18. data/spec/{rtsp → unit/rtsp}/message_spec.rb +1 -1
  19. data/spec/{rtsp → unit/rtsp}/response_spec.rb +1 -1
  20. data/spec/{rtsp → unit/rtsp}/transport_parser_spec.rb +1 -1
  21. data/spec/{rtsp_spec.rb → unit/rtsp_spec.rb} +3 -3
  22. metadata +22 -185
  23. data/spec/rtsp/client_spec.rb +0 -326
  24. data/spec/rtsp/coverage/assets/0.7.1/application.css +0 -1110
  25. data/spec/rtsp/coverage/assets/0.7.1/application.js +0 -626
  26. data/spec/rtsp/coverage/assets/0.7.1/fancybox/blank.gif +0 -0
  27. data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_close.png +0 -0
  28. data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_loading.png +0 -0
  29. data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_nav_left.png +0 -0
  30. data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_nav_right.png +0 -0
  31. data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_e.png +0 -0
  32. data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_n.png +0 -0
  33. data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_ne.png +0 -0
  34. data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_nw.png +0 -0
  35. data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_s.png +0 -0
  36. data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_se.png +0 -0
  37. data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_sw.png +0 -0
  38. data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_w.png +0 -0
  39. data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_title_left.png +0 -0
  40. data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_title_main.png +0 -0
  41. data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_title_over.png +0 -0
  42. data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancy_title_right.png +0 -0
  43. data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancybox-x.png +0 -0
  44. data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancybox-y.png +0 -0
  45. data/spec/rtsp/coverage/assets/0.7.1/fancybox/fancybox.png +0 -0
  46. data/spec/rtsp/coverage/assets/0.7.1/favicon_green.png +0 -0
  47. data/spec/rtsp/coverage/assets/0.7.1/favicon_red.png +0 -0
  48. data/spec/rtsp/coverage/assets/0.7.1/favicon_yellow.png +0 -0
  49. data/spec/rtsp/coverage/assets/0.7.1/loading.gif +0 -0
  50. data/spec/rtsp/coverage/assets/0.7.1/magnify.png +0 -0
  51. data/spec/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  52. data/spec/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  53. data/spec/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  54. data/spec/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  55. data/spec/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  56. data/spec/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  57. data/spec/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  58. data/spec/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  59. data/spec/rtsp/coverage/assets/0.7.1/smoothness/images/ui-icons_222222_256x240.png +0 -0
  60. data/spec/rtsp/coverage/assets/0.7.1/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  61. data/spec/rtsp/coverage/assets/0.7.1/smoothness/images/ui-icons_454545_256x240.png +0 -0
  62. data/spec/rtsp/coverage/assets/0.7.1/smoothness/images/ui-icons_888888_256x240.png +0 -0
  63. data/spec/rtsp/coverage/assets/0.7.1/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  64. data/spec/rtsp/coverage/index.html +0 -72
  65. data/spec/unit/rtsp/coverage/assets/0.7.1/application.css +0 -1110
  66. data/spec/unit/rtsp/coverage/assets/0.7.1/application.js +0 -626
  67. data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/blank.gif +0 -0
  68. data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_close.png +0 -0
  69. data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_loading.png +0 -0
  70. data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_nav_left.png +0 -0
  71. data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_nav_right.png +0 -0
  72. data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_e.png +0 -0
  73. data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_n.png +0 -0
  74. data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_ne.png +0 -0
  75. data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_nw.png +0 -0
  76. data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_s.png +0 -0
  77. data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_se.png +0 -0
  78. data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_sw.png +0 -0
  79. data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_shadow_w.png +0 -0
  80. data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_title_left.png +0 -0
  81. data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_title_main.png +0 -0
  82. data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_title_over.png +0 -0
  83. data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancy_title_right.png +0 -0
  84. data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancybox-x.png +0 -0
  85. data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancybox-y.png +0 -0
  86. data/spec/unit/rtsp/coverage/assets/0.7.1/fancybox/fancybox.png +0 -0
  87. data/spec/unit/rtsp/coverage/assets/0.7.1/favicon_green.png +0 -0
  88. data/spec/unit/rtsp/coverage/assets/0.7.1/favicon_red.png +0 -0
  89. data/spec/unit/rtsp/coverage/assets/0.7.1/favicon_yellow.png +0 -0
  90. data/spec/unit/rtsp/coverage/assets/0.7.1/loading.gif +0 -0
  91. data/spec/unit/rtsp/coverage/assets/0.7.1/magnify.png +0 -0
  92. data/spec/unit/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  93. data/spec/unit/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  94. data/spec/unit/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  95. data/spec/unit/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  96. data/spec/unit/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  97. data/spec/unit/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  98. data/spec/unit/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  99. data/spec/unit/rtsp/coverage/assets/0.7.1/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  100. data/spec/unit/rtsp/coverage/assets/0.7.1/smoothness/images/ui-icons_222222_256x240.png +0 -0
  101. data/spec/unit/rtsp/coverage/assets/0.7.1/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  102. data/spec/unit/rtsp/coverage/assets/0.7.1/smoothness/images/ui-icons_454545_256x240.png +0 -0
  103. data/spec/unit/rtsp/coverage/assets/0.7.1/smoothness/images/ui-icons_888888_256x240.png +0 -0
  104. data/spec/unit/rtsp/coverage/assets/0.7.1/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  105. data/spec/unit/rtsp/coverage/index.html +0 -72
@@ -1,3 +1,13 @@
1
+ === 0.4.2 / 2012-11-14
2
+
3
+ * Bug fixes
4
+ * {gh-17}[https://github.com/turboladen/rtsp/issues/17] Can now parse HTTP
5
+ responses (some servers may send HTTP responses to RTSP requests).
6
+ * Other
7
+ * Turned logging off by default. To enable, simply do <tt>RTSP::Client.log = true</tt>
8
+ * Updated to work with RTP 0.1.0.
9
+ * Can now inspect RTP packets during #play.
10
+
1
11
  === 0.4.1 / 2012-11-14
2
12
 
3
13
  * gh-16: Can now parse Session IDs to be alpha characters. Thanks @greywolf-colorado!
data/Gemfile CHANGED
@@ -1,5 +1,5 @@
1
1
  source :rubygems
2
2
 
3
- #gem 'rtp', path: '../rtp'
4
3
  gemspec
4
+ gem 'thor'
5
5
 
@@ -2,48 +2,47 @@
2
2
 
3
3
  * https://github.com/turboladen/rtsp
4
4
 
5
+ {<img src="https://secure.travis-ci.org/turboladen/rtsp.png" alt="Build Status" />}[https://travis-ci.org/turboladen/rtsp]
6
+
5
7
  == DESCRIPTION:
6
8
 
7
9
  This library intends to follow the RTSP RFC document (2326) to allow for working
8
- with RTSP servers. At this point, it's up to you to parse the data from a play
9
- call, but we'll get there. ...eventually.
10
-
11
- For more information
10
+ with RTSP servers. By way of {rtp}[https://github.com/turboladen/rtp], you can
11
+ either inspect the RTP packets as they come across the wire or use the file
12
+ that the data got saved to.
12
13
 
13
- RTSP: http://tools.ietf.org/html/rfc2326
14
+ For more information:
14
15
 
15
- SDP: http://tools.ietf.org/html/rfc4566
16
+ * RTSP: {http://tools.ietf.org/html/rfc2326}[http://tools.ietf.org/html/rfc2326]
17
+ * RTP: {http://tools.ietf.org/html/rfc3550}[http://tools.ietf.org/html/rfc3550]
18
+ * SDP: {http://tools.ietf.org/html/rfc4566}[http://tools.ietf.org/html/rfc4566]
16
19
 
17
20
  == FEATURES/PROBLEMS:
18
21
 
19
22
  * All standard RTSP methods supported except REDIRECT.
20
- * Captures RTP data to a file, but doesn't ensure RTP sequencing before putting to file.
21
- * One client object can only handle 1 stream; use a client per stream until this functionality
22
- gets implemented.
23
- * Only handles unicast, UDP streams.
24
- * RTSP exceptions are all +RTSP::Error+s; this will change.
23
+ * Captures RTP data to a file, or yields if a block is passed to #play.
24
+ * One client object can only handle 1 stream; use a client per stream until this
25
+ functionality gets implemented.
26
+ * Only handles unicast, TCP RTSP communication.
27
+ * RTSP exceptions are all {RTSP::Error}s.
25
28
 
26
29
  == SYNOPSIS:
27
30
 
28
31
  === Basic Usage
29
32
 
30
- RTSP::Client.log? # => true
31
- RTSP::Client.log = false
32
- client = RTSP::Client.new "rtsp://64.202.98.91/sa.sdp" do |connection, capturer|
33
- connection.timeout = 5
34
- capturer.rtp_port = 8554
35
- capturer.rtp_file = File.open("captured_stuff.rtp", "wb")
36
- end
37
-
33
+ RTSP::Client.log? # => false
34
+ RTSP::Client.log = true
35
+ client = RTSP::Client.new "rtsp://64.202.98.91/sa.sdp"
36
+
38
37
  client.server_uri # => #<URI::Generic:0x00000100ba4db0 URL:rtsp://64.202.98.91:554/sa.sdp>
39
38
  client.session_state # => :init
40
39
  client.cseq # => 1
41
40
  client.connection.do_capture # => true
42
41
  client.connection.interleave # => false
43
- client.connection.timeout # => 5
44
- client.capturer.broadcast_type # => :unicast
45
- client.capturer.rtp_port # => 8554
46
- client.capturer.rtp_file # => #<File:captured_stuff.rtp>
42
+ client.connection.timeout # => 30
43
+ client.capturer.ip_addressing_type # => :unicast
44
+ client.capturer.rtp_port # => 6970
45
+ client.capturer.capture_file # => #<File:/var/folders/tg/j9jxvvfs4qn9cg4vztzyy2gc0000gp/T/rtp_capture.raw-59901-1l8dgv2>
47
46
  client.capturer.transport_protocol # => :UDP
48
47
 
49
48
  response = client.options
@@ -66,7 +65,6 @@ gets implemented.
66
65
  client.cseq # => 4
67
66
  client.session_state # => :ready
68
67
 
69
-
70
68
  response = client.play(client.aggregate_control_track)
71
69
  response.range # => "npt=now="
72
70
  resposne.rtp_info # => "url=rtsp://64.202.98.91:554/sa.sdp/trackID=1"
@@ -86,7 +84,31 @@ gets implemented.
86
84
  client.session_state # => :init
87
85
 
88
86
  # Check the streamed file's contents
89
- puts client.capturer.rtp_file # => (Lots of data)
87
+ puts client.capturer.capture_file # => (Lots of data)
88
+
89
+ === RTP packet inspection
90
+
91
+ As of RTP 0.1.0, you can now inspect and use packets as they come across the
92
+ wire:
93
+
94
+ client = RTSP::Client.new "rtsp://64.202.98.91/sa.sdp"
95
+ client.describe
96
+ client.setup(client.media_control_tracks.first)
97
+ payload_file = File.new('rtp.data', 'wb')
98
+
99
+ client.play(client.aggregate_control_track) do |packet|
100
+ puts "packet is a #{packet.class}"
101
+ puts "RTP seqence: #{packet.sequence_number}"
102
+ puts "RTP payload type: #{packet.payload_type}"
103
+
104
+ # Let's save the payload data while we're at it...
105
+ payload_file.write(packet.rtp_payload)
106
+ end
107
+
108
+ payload_file.close
109
+
110
+ Take a look at the {RTP::Packet docs}[http://rdoc.info/gems/rtp/RTP/Packet] for
111
+ more information.
90
112
 
91
113
  === CLI App
92
114
 
@@ -116,20 +138,12 @@ As usual, get help by:
116
138
  == REQUIREMENTS:
117
139
 
118
140
  * (Tested) Rubies
119
- * 1.9.2-p180
141
+ * 1.9.2
142
+ * 1.9.3
120
143
  * RubyGems
121
- * sdp, '~> 0.2.2'
122
- * RubyGems (development)
123
- * bundler, '~> 1.0.0'
124
- * code_statistics, '~> 0.2.13'
125
- * metric_fu, '>= 2.0.0'
126
- * ore, '~> 0.7.2'
127
- * ore-core, '~> 0.1.0'
128
- * ore-tasks, '~> 0.3.0'
129
- * rake, '~> 0.8.7'
130
- * rspec, '~> 2.5.0'
131
- * simplecov, '>= 0.4.0'
132
- * yard, '~> 0.6.0'
144
+ * sdp
145
+ * rtp
146
+ * parslet
133
147
 
134
148
  == INSTALL:
135
149
 
data/Rakefile CHANGED
@@ -2,22 +2,16 @@ require 'bundler/gem_tasks'
2
2
  require 'rspec/core/rake_task'
3
3
  require 'yard'
4
4
 
5
- RSpec::Core::RakeTask.new(:spec) do |t|
6
- t.rspec_opts = ['--format', 'documentation', '--color']
7
- end
5
+ RSpec::Core::RakeTask.new
8
6
 
9
7
  namespace :spec do
10
8
  RSpec::Core::RakeTask.new(:warnings) do |t|
11
9
  t.ruby_opts = "-w"
12
- t.rspec_opts = ['--format', 'documentation', '--color']
13
10
  end
14
11
  end
15
12
  task :default => :spec
16
13
  task :test => :spec # for `gem test`
17
14
 
18
15
  YARD::Rake::YardocTask.new do |t|
19
- t.options = ['--verbose']
16
+ t.options = %w[--verbose]
20
17
  end
21
-
22
- # Load all extra rake tasks
23
- Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].each { |ext| load ext }
@@ -11,7 +11,7 @@ optparse = OptionParser.new do |opts|
11
11
  # Turn on logging
12
12
  RTSP::Client.configure { |c| c.log = false }
13
13
  opts.on('-d', '--debug', "Turn on RTSP::Client logging.") do
14
- RTSP::Client.configure { |c| c.log = true }
14
+ RTSP::Client.log = true
15
15
  end
16
16
 
17
17
  #----------------------------------------------------------------------------
@@ -50,8 +50,8 @@ optparse = OptionParser.new do |opts|
50
50
  exit
51
51
  end
52
52
 
53
- rtsp_client = RTSP::Client.new(url) do |connection, capturer|
54
- capturer.rtp_file = File.open("#{Dir.pwd}/rtsp_client_stream.rtp", "wb")
53
+ rtsp_client = RTSP::Client.new(url) do |_, capturer|
54
+ capturer.capture_file = File.open("#{Dir.pwd}/rtsp_client_stream.rtp", "wb")
55
55
  end
56
56
 
57
57
  begin
@@ -79,7 +79,7 @@ module RTSP
79
79
  attr_accessor :connection
80
80
 
81
81
  # Use to get/set an object for capturing received data.
82
- # @param [RTP::Receiver]
82
+ #
83
83
  # @return [RTP::Receiver]
84
84
  attr_accessor :capturer
85
85
 
@@ -112,21 +112,16 @@ module RTSP
112
112
  @connection = Struct::Connection.new
113
113
  @capturer = RTP::Receiver.new
114
114
 
115
- yield(connection, capturer) if block_given?
116
-
117
- @connection.server_url = server_url || @connection.server_url
118
- @server_uri = build_resource_uri_from(@connection.server_url)
119
- @connection.timeout ||= 30
120
- @connection.socket ||= TCPSocket.new(@server_uri.host, @server_uri.port)
121
- @connection.do_capture ||= true
122
- @connection.interleave ||= false
123
- @capturer.rtp_port ||= 9000
124
- @capturer.transport_protocol ||= :UDP
125
- @capturer.broadcast_type ||= :unicast
126
- @capturer.rtp_file ||= Tempfile.new(RTP::Receiver::DEFAULT_CAPFILE_NAME)
127
-
128
- @play_thread = nil
129
- @cseq = 1
115
+ yield(@connection, @capturer) if block_given?
116
+
117
+ @connection.server_url = server_url || @connection.server_url
118
+ @server_uri = build_resource_uri_from(@connection.server_url)
119
+ @connection.timeout ||= 30
120
+ @connection.socket ||= TCPSocket.new(@server_uri.host, @server_uri.port)
121
+ @connection.do_capture ||= true
122
+ @connection.interleave ||= false
123
+
124
+ @cseq = 1
130
125
  reset_state
131
126
  end
132
127
 
@@ -153,18 +148,16 @@ module RTSP
153
148
  response = Timeout::timeout(@connection.timeout) do
154
149
  @connection.socket.send(message.to_s, 0)
155
150
  socket_data = @connection.socket.recvfrom MAX_BYTES_TO_RECEIVE
151
+
152
+ RTSP::Client.log "Received response:"
153
+ socket_data.first.each_line { |line| RTSP::Client.log line.strip }
154
+
156
155
  RTSP::Response.new socket_data.first
157
156
  end
158
157
  rescue Timeout::Error
159
158
  raise RTSP::Error, "Request took more than #{@connection.timeout} seconds to send."
160
159
  end
161
160
 
162
- RTSP::Client.log "Received response:"
163
-
164
- if response
165
- response.to_s.each_line { |line| RTSP::Client.log line.strip }
166
- end
167
-
168
161
  response
169
162
  end
170
163
 
@@ -235,8 +228,8 @@ module RTSP
235
228
  # @return [String] The String to use with the Transport header.
236
229
  # @see http://tools.ietf.org/html/rfc2326#page-58 RFC 2326, Section 12.39.
237
230
  def request_transport
238
- value = "RTP/AVP;#{@capturer.broadcast_type};client_port="
239
- value << "#{@capturer.rtp_port}-#{@capturer.rtp_port + 1}\r\n"
231
+ value = "RTP/AVP;#{@capturer.ip_addressing_type};client_port="
232
+ value << "#{@capturer.rtp_port}-#{@capturer.rtcp_port}\r\n"
240
233
  end
241
234
 
242
235
  # Sends the SETUP request, then sets +@session+ to the value returned in the
@@ -260,14 +253,14 @@ module RTSP
260
253
 
261
254
  @session = response.session
262
255
  parser = RTSP::TransportParser.new
263
- @transport = parser.parse response.transport
256
+ @transport = parser.parse(response.transport)
264
257
 
265
258
  unless @transport[:transport_protocol].nil?
266
259
  @capturer.transport_protocol = @transport[:transport_protocol]
267
260
  end
268
261
 
269
- @capturer.rtp_port = @transport[:client_port][:rtp].to_i
270
- @capturer.broadcast_type = @transport[:broadcast_type]
262
+ @capturer.rtp_port = @transport[:client_port][:rtp].to_i
263
+ @capturer.ip_address = @transport[:destination].to_s
271
264
  end
272
265
  end
273
266
 
@@ -281,7 +274,7 @@ module RTSP
281
274
  # @raise [RTSP::Error] If +#play+ is called but the session hasn't yet been
282
275
  # set up via +#setup+.
283
276
  # @see http://tools.ietf.org/html/rfc2326#page-34 RFC 2326, Section 10.5.
284
- def play(track, additional_headers={})
277
+ def play(track, additional_headers={}, &block)
285
278
  message = RTSP::Message.play(track).with_headers({
286
279
  cseq: @cseq, session: @session[:session_id] })
287
280
  message.add_headers additional_headers
@@ -291,16 +284,8 @@ module RTSP
291
284
  raise RTSP::Error, "Session not set up yet. Run #setup first."
292
285
  end
293
286
 
294
- if @play_thread.nil?
295
- RTSP::Client.log "Capturing RTP data on port #{@transport[:client_port][:rtp]}"
296
-
297
- unless @capturer.running?
298
- @play_thread = Thread.new do
299
- @capturer.run
300
- end
301
- end
302
- end
303
-
287
+ RTSP::Client.log "Capturing RTP data on port #{@transport[:client_port][:rtp]}"
288
+ @capturer.start(&block)
304
289
  @session_state = :playing
305
290
  end
306
291
  end
@@ -313,7 +298,7 @@ module RTSP
313
298
  # @see http://tools.ietf.org/html/rfc2326#page-36 RFC 2326, Section 10.6.
314
299
  def pause(track, additional_headers={})
315
300
  message = RTSP::Message.pause(track).with_headers({
316
- cseq: @cseq, session: @session[:session_id] })
301
+ cseq: @cseq, session: @session[:session_id] })
317
302
  message.add_headers additional_headers
318
303
 
319
304
  request(message) do
@@ -336,23 +321,11 @@ module RTSP
336
321
  message.add_headers additional_headers
337
322
 
338
323
  request(message) do
324
+ @capturer.stop
339
325
  reset_state
340
-
341
- if @play_thread
342
- @capturer.stop
343
- @capturer.rtp_file.close
344
- @play_thread.exit
345
- end
346
326
  end
347
327
  end
348
328
 
349
- # Sets state related variables back to their starting values;
350
- # +@session_state+ is set to +:init+; +@session+ is set to 0.
351
- def reset_state
352
- @session_state = :init
353
- @session = {}
354
- end
355
-
356
329
  # Sends the GET_PARAMETERS request.
357
330
  #
358
331
  # @param [String] track The presentation or media track to ping.
@@ -361,8 +334,7 @@ module RTSP
361
334
  # @return [RTSP::Response]
362
335
  # @see http://tools.ietf.org/html/rfc2326#page-37 RFC 2326, Section 10.8.
363
336
  def get_parameter(track, body="", additional_headers={})
364
- message = RTSP::Message.get_parameter(track).with_headers({
365
- cseq: @cseq })
337
+ message = RTSP::Message.get_parameter(track).with_headers({ cseq: @cseq })
366
338
  message.add_headers additional_headers
367
339
  message.body = body
368
340
 
@@ -377,8 +349,7 @@ module RTSP
377
349
  # @return [RTSP::Response]
378
350
  # @see http://tools.ietf.org/html/rfc2326#page-38 RFC 2326, Section 10.9.
379
351
  def set_parameter(track, parameters, additional_headers={})
380
- message = RTSP::Message.set_parameter(track).with_headers({
381
- cseq: @cseq })
352
+ message = RTSP::Message.set_parameter(track).with_headers({ cseq: @cseq })
382
353
  message.add_headers additional_headers
383
354
  message.body = parameters
384
355
 
@@ -404,7 +375,7 @@ module RTSP
404
375
  # then increments +@cseq+ by 1. Handles any exceptions raised during the
405
376
  # Request.
406
377
  #
407
- # @param [Hash] new_args
378
+ # @param [RTSP::Message] message
408
379
  # @yield [RTSP::Response]
409
380
  # @return [RTSP::Response]
410
381
  # @raise [RTSP::Error] All 4xx & 5xx response codes & their messages.
@@ -434,15 +405,6 @@ module RTSP
434
405
  response
435
406
  end
436
407
 
437
- # Ensures that +@session+ is set before continuing on.
438
- #
439
- # @raise [RTSP::Error] Raises if @session isn't set.
440
- def ensure_session
441
- if @session.empty?
442
- raise RTSP::Error, "Session number not retrieved from server yet. Run SETUP first."
443
- end
444
- end
445
-
446
408
  # Extracts the URL associated with the "control" attribute from the main
447
409
  # section of the session description.
448
410
  #
@@ -478,24 +440,31 @@ module RTSP
478
440
  tracks
479
441
  end
480
442
 
481
- # Compares the sequence number passed in to the current client sequence
482
- # number ( +@cseq+ ) and raises if they're not equal. If that's the case, the
483
- # server responded to a different request.
443
+ private
444
+
445
+ # Sets state related variables back to their starting values;
446
+ # +@session_state+ is set to +:init+; +@session+ is set to 0.
447
+ def reset_state
448
+ @session_state = :init
449
+ @session = {}
450
+ end
451
+
452
+ # Takes the methods returned from the Public header from an OPTIONS response
453
+ # and puts them to an Array.
484
454
  #
485
- # @param [Fixnum] server_cseq Sequence number returned by the server.
486
- # @raise [RTSP::Error] If the server returns a CSeq value that's different
487
- # from what the client sent.
488
- def compare_sequence_number server_cseq
489
- if @cseq != server_cseq
490
- message = "Sequence number mismatch. Client: #{@cseq}, Server: #{server_cseq}"
491
- raise RTSP::Error, message
492
- end
455
+ # @param [String] method_list The string returned from the server containing
456
+ # the list of methods it supports.
457
+ # @return [Array<Symbol>] The list of methods as symbols.
458
+ # @see #options
459
+ def extract_supported_methods_from method_list
460
+ method_list.downcase.split(', ').map { |m| m.to_sym }
493
461
  end
494
462
 
495
463
  # Compares the session number passed in to the current client session
496
464
  # number ( +@session+ ) and raises if they're not equal. If that's the case,
497
465
  # the server responded to a different request.
498
466
  #
467
+ # @todo Remove this--it's not used.
499
468
  # @param [Fixnum] server_session Session number returned by the server.
500
469
  # @raise [RTSP::Error] If the server returns a Session value that's different
501
470
  # from what the client sent.
@@ -506,15 +475,30 @@ module RTSP
506
475
  end
507
476
  end
508
477
 
509
- # Takes the methods returned from the Public header from an OPTIONS response
510
- # and puts them to an Array.
478
+ # Compares the sequence number passed in to the current client sequence
479
+ # number ( +@cseq+ ) and raises if they're not equal. If that's the case, the
480
+ # server responded to a different request.
511
481
  #
512
- # @param [String] method_list The string returned from the server containing
513
- # the list of methods it supports.
514
- # @return [Array<Symbol>] The list of methods as symbols.
515
- # @see #options
516
- def extract_supported_methods_from method_list
517
- method_list.downcase.split(', ').map { |m| m.to_sym }
482
+ # @param [Fixnum] server_cseq Sequence number returned by the server.
483
+ # @raise [RTSP::Error] If the server returns a CSeq value that's different
484
+ # from what the client sent.
485
+ def compare_sequence_number server_cseq
486
+ if @cseq != server_cseq
487
+ message = "Sequence number mismatch. Client: #{@cseq}, Server: #{server_cseq}"
488
+ raise RTSP::Error, message
489
+ end
518
490
  end
491
+
492
+ # Ensures that +@session+ is set before continuing on.
493
+ #
494
+ # @raise [RTSP::Error] Raises if @session isn't set.
495
+ def ensure_session
496
+ if @session.empty?
497
+ raise RTSP::Error, "Session number not retrieved from server yet. Run SETUP first."
498
+ end
499
+ end
500
+
519
501
  end
520
502
  end
503
+
504
+ RTSP::Client.log = false