1 # client-ssac.tcl --
2 #
3 # FIXME: This file needs a description here.
4 #
5 # Copyright (c) 1998-2002 The Regents of the University of California.
6 # All rights reserved.
7 #
8 # Redistribution and use in source and binary forms, with or without
9 # modification, are permitted provided that the following conditions are met:
10 #
11 # A. Redistributions of source code must retain the above copyright notice,
12 # this list of conditions and the following disclaimer.
13 # B. Redistributions in binary form must reproduce the above copyright notice,
14 # this list of conditions and the following disclaimer in the documentation
15 # and/or other materials provided with the distribution.
16 # C. Neither the names of the copyright holders nor the names of its
17 # contributors may be used to endorse or promote products derived from this
18 # software without specific prior written permission.
19 #
20 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
21 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
24 # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #
31 # @(#) $Header: /usr/mash/src/repository/mash/mash-1/tcl/ssac/client-ssac.tcl,v 1.26 2002/02/03 04:30:10 lim Exp $
32
33
34 import mashutils SDPParser AnnounceListenManager/AS/Client/SSAC \
35 SessionCatalog SDPParser Observable
36
37 # Client side SSAC parsing
38 # Status: pre-alpha
39 # Author: Angela Schuett
40
41 Class SSAC_Client -superclass Observable -configuration {
42 megaforPort 60000
43 }
44
45
46 # megactrl can be an empty string; in that case, the object will try to
47 # read the server's location from the catalog file
48 # ssg_port will be used by SSAC_Client *only* if the megactrl address
49 # that it ends up using is unicast; otherwise this gets reset to "-"
50 SSAC_Client public init { megactrl ssg_port {data_multicast 0} } {
51 $self instvar session_
52 $self instvar broadcast_
53
54 set session_(state) IDLE
55 #set session_(uri) ""
56 set session_(first) 0
57
58 set session_(server_name) $megactrl
59 set session_(ssg_port) $ssg_port
60 set session_(data_multicast) $data_multicast
61 }
62
63
64 SSAC_Client public send {method args} {
65 $self instvar session_ AS_ broadcast_
66
67 if {$session_(first) == 0} {
68 # this is the first time! we should create an
69 # AnnounceListenManager for this guy
70 set AS_ [new AnnounceListenManager/AS/Client/SSAC $self \
71 $session_(server_name) $session_(ssg_port)]
72 $AS_ data_multicast $session_(data_multicast)
73 $AS_ set_broadcast "[array get broadcast_]"
74 }
75 switch -exact -- $method {
76 "PLAY" {
77 set seqno [$AS_ seqno]
78 incr seqno 2
79 #puts "client upped seqno for PLAY"
80 $AS_ set_seqno $seqno
81 $AS_ set_offset [lindex $args 0]
82 $AS_ set_filename $session_(session_name)
83
84 set dont_send_now [lindex $args 1]
85 }
86 "PAUSE" {
87 set seqno [$AS_ seqno]
88 incr seqno
89 #puts "client upped seqno for PAUSE"
90 $AS_ set_seqno $seqno
91 $AS_ set_offset "PAUSE"
92
93 set dont_send_now [lindex $args 0]
94 }
95
96 "CLOSE" {
97 # FIXME FIX THIS
98
99 #set seqno [$AS_ seqno]
100 #incr seqno
101 #$AS_ set_seqno $seqno
102 #$AS_ set_offset "End"
103
104 #set dont_send_now [lindex $args 0]
105 }
106 }
107
108 #send the message
109
110 if {$session_(first) == 0} {
111 $AS_ start
112 set session_(first) 1
113 } elseif { $dont_send_now == {} } {
114 #$AS_ change_state $msg
115 $AS_ send_announcement
116 # Seek, pause, close are sent immediately, without waiting
117 # for timer to fire. Keep-alive msgs are sent on timer
118 }
119
120 }
121
122 SSAC_Client public notify {msg} {
123 #puts "Notify: $msg"
124 # set timescales
125
126 $self parse_server_msg $msg
127 }
128
129 SSAC_Client public open {desc offset} {
130 $self instvar session_
131
132 #set session_(uri) $url
133 set media_list [$self parse_pd $desc]
134
135 # for now, we assume that the start time is now + 15 seconds
136 #set session_(startwall) [expr [clock seconds] + 15]
137 #puts "OPEN $session_(startwall)"
138 $self send "PLAY" $offset
139 return $media_list
140 }
141
142 SSAC_Client public play_or_pause { {offset {}} } {
143 $self instvar session_
144
145 if {$session_(state) == "PLAY"} {
146 $self pause
147 } else {
148 $self play $offset
149 }
150 }
151
152
153 SSAC_Client public stop { } {
154 $self pause
155 }
156
157
158 SSAC_Client public duration { } {
159 $self instvar session_
160 return [expr $session_(endtime) - $session_(starttime)]
161 }
162
163
164 SSAC_Client public elapsed { time } {
165 $self instvar session_
166 return [duration_readable $time]
167 }
168
169
170 # This procedure parses the server SSAC announcement
171 SSAC_Client private parse_server_msg {msg} {
172 $self instvar session_ sesslist_ first_
173 $self instvar rtsp_ AS_ old_offset_
174
175 set o [split $msg "\n"]
176
177
178 #puts "msg = $msg"
179
180 set seqno [lindex [split [lindex $o 0]] 1]
181 if {$seqno >= [$AS_ seqno]} {
182 $AS_ set_seqno $seqno
183 #puts "server upped seqno"
184
185 set duration [lindex [split [lindex $o 2]] 1]
186
187 set session_(starttime) 0
188 set session_(endtime) $duration
189
190 set systemt [lindex [split [lindex $o 3]] 1]
191 set offsett [lindex [split [lindex $o 3]] 2]
192 #puts "system time=$systemt logical time=$offsett"
193 set system_offset [expr [clock seconds] - $systemt]
194 set new_offset [expr $offsett + $system_offset]
195
196 set len [llength $o]
197 for {set n 4} {$n < $len} {incr n 2} {
198 set sess [lindex [split [lindex $o $n]] 1]
199 if {![lsearch sesslist_ $sess]} {
200 puts "Error"
201 }
202 ##
203 set tmpsession($sess) [lrange [split [lindex $o \
204 [expr $n + 1]]] 1 end]
205 }
206
207 if {$session_(first) == 1} {
208 $self notify_observers activate \
209 $session_(starttime) $session_(endtime)
210 set session_(state) "PLAY"
211 $self notify_observers play_update "PAUSE"
212
213 set session_(duration) [expr $session_(endtime) - \
214 $session_(starttime)]
215 $self notify_observers update_title \
216 $session_(session_info1) \
217 $session_(session_info2) \
218 $session_(duration)
219
220 # puts "sesslist_ - $sesslist_"
221 # puts "session_ - [array get session_]"
222 # puts "tmpsession_ - [array get tmpsession]"
223
224 foreach sess $sesslist_ {
225 set session_($sess,Address) [lindex $tmpsession($sess) 0]
226 set session_($sess,SourceId) [lrange $tmpsession($sess) 1 end]
227
228 #puts "sess - $sess"
229 $self notify_observers ssac_reset \
230 $session_($sess,Media) \
231 $session_($sess,Address)
232 }
233 set session_(first) 2
234 } else {
235 # Fix this
236 #puts "offset changed to $new_offset"
237 $self notify_observers set_offset $new_offset
238 $AS_ set_offset $new_offset
239
240 foreach sess $sesslist_ {
241 if {$tmpsession($sess) != \
242 $session_($sess,Address)} {
243 set session_($sess,Address) \
244 $tmpsession($sess)
245 $self notify_observers ssac_reset \
246 $session_($sess,Media)\
247 $session_($sess,Address)
248 }
249 }
250 }
251 set old_offset_ $new_offset
252 } else {
253 #puts "OLD SEQNO $seqno $session_(seqno)"
254 }
255 }
256
257
258
259
260 # This procedure parses the presentation description, which contains the
261 # server mcast address, catalog file location, and catalog file. The pd is
262 # passed through the -server flag, and is intended to be downloaded from
263 # the web. Shouldn't be in this class, move to application.
264
265 SSAC_Client private parse_pd {pd} {
266 $self instvar session_ sesslist_ broadcast_
267
268 set ctg [new SessionCatalog]
269 $ctg parse $pd
270 set sdp [$ctg get_sdp]
271 #puts $sdp
272
273 set p [new SDPParser]
274 set message [$p parse $sdp]
275
276 if {$message != ""} {
277 if {[$message have_field s]} {
278 set session_(session_info1) [$message field_value s]
279 }
280 if {[$message have_field i]} {
281 set session_(session_info2) [$message field_value i]
282 }
283
284 delete $message
285 } else {
286 set session_(session_info1) ""
287 set session_(session_info2) ""
288 }
289 delete $p
290
291 $self notify_observers update_title $session_(session_info1) \
292 $session_(session_info2) 0
293
294 set desc [$ctg get_desc]
295 if {$desc==""} {
296 error "Catalog file is missing server contact info"
297 }
298 set desclines [split $desc "\n"]
299
300 if { $session_(server_name) == "" } {
301 set server_name [lindex [split [lindex $desclines 1]] 1]
302 regsub -all ":" $server_name "/" session_(server_name)
303 }
304
305 set s [split $session_(server_name) /]
306 set addr [lindex $s 0]
307 if ![regexp {^[0-9.]+$} $addr] {
308 # this looks like a hostname
309 set addr [gethostbyname $addr]
310 }
311 if { [in_multicast $addr] } {
312 set session_(ssg_port) -
313 } else {
314 # this is unicast; append port numbers
315 set port [lindex $s 1]
316 if { $port == {} } { set port [$self get_option megaforPort] }
317 set session_(server_name) "$addr/$port:$session_(ssg_port)/1"
318 }
319
320 set session_(session_name) [lindex [split [lindex $desclines 0]] 1]
321
322
323 # ok now get the broadcast addresses for each media type and
324 # put them into the table
325 foreach desc $desclines {
326 if {[lindex $desc 0] != "inetBroadcastAddr:"} {
327 continue
328 }
329
330 set info [split [lindex $desc 1] :]
331 set broadcast_([lindex $info 0]) [lindex $info 1]
332 }
333
334 foreach id [$ctg info streams] {
335 lappend sessions([$ctg info session $id]) $id
336
337 }
338 set sesslist_ [array names sessions]
339
340 foreach sess $sesslist_ {
341 # FIXME hack
342 set session_($sess,Media) [string trimright $sess "0123456789"]
343 # puts "********* $sess $session_($sess,Media) **********"
344 set media($session_($sess,Media)) 1
345 }
346
347 delete $ctg
348
349 # FIXME: assumes there is only one session of each mediatype
350 # Yatin: I'm not sure if collaborator can handle multiple sessions
351 # of the same media type. don't want to add the code to enable
352 # that and test it right now
353 return [array names media]
354 }
355
356
357 SSAC_Client public server_name { } {
358 $self instvar session_
359 return $session_(server_name)
360 }
361
362
363
364 SSAC_Client private play { offset } {
365 $self instvar session_
366 if { $session_(state) != "PLAY" } {
367 set session_(state) PLAY
368 $self notify_observers play_update "PAUSE"
369 $self send PLAY $offset
370 }
371 }
372
373
374 SSAC_Client private pause { } {
375 $self instvar session_
376 if { $session_(state) != "PAUSE" } {
377 set session_(state) PAUSE
378 $self notify_observers play_update "PLAY"
379 $self send PAUSE
380 }
381 }
382
383
384 # Called when the data addresses change, for example when the MARS
385 # server crashes and restarts. Since mediaboard is currently started as
386 # an outside app, we'd have to just start a new one.
387 SSAC_Client private reset_tools {} {
388 $self instvar session_ sesslist_ rtsp_
389
390 foreach sess $sesslist_ {
391 switch -- $session_($sess,Media) {
392 video {
393
394 $rtsp_(application) reset_vic $session_($sess,Address)
395
396 }
397 audio {
398 $rtsp_(application) reset_vat $session_($sess,Address)
399 }
400 mediaboard {
401 puts "Not resetting Mediaboard**"
402 }
403
404 }
405 }
406 }
407
408
409
410
411 SSAC_Client private start_tools {} {
412 $self instvar session_ sesslist_ rtsp_
413 foreach sess $sesslist_ {
414 switch -- $session_($sess,Media) {
415 video {
416 #puts "Starting VIC..."
417 $rtsp_(application) start_vic $session_($sess,Address)
418
419 }
420 audio {
421 #puts "Starting VAT..."
422
423 $rtsp_(application) start_vat $session_($sess,Address)
424 }
425 mediaboard {
426 global env
427 set mpid_ [eval exec mb -sa $session_($sess,Address) &]
428 }
429
430 }
431 }
432 }
433
434 # Start the tools standalone
435 SSAC_Client private start_tools2 {} {
436 $self instvar session_ sesslist_ rtsp_
437
438 foreach sess $sesslist_ {
439 switch -- $session_($sess,Media) {
440 video {
441 puts "Starting VIC $session_($sess,Address)"
442 #$rtsp_(application) start_vic $session_($sess,Address)
443
444 set vpid_ [eval exec vic -X loopback=1 $session_($sess,Address) &]
445
446 }
447 audio {
448 puts "Starting VAT $session_($sess,Address)"
449 #$rtsp_(application) start_vat $session_($sess,Address)
450 set apid_ [eval exec vat -X loopback=1 $session_($sess,Address) &]
451
452 }
453
454 mediaboard {
455 puts "Starting MB $session_($sess,Address)"
456 set mpid_ [eval exec mb -sa $session_($sess,Address) &]
457 }
458
459 }
460 }
461 }
462
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.