1 # application-replayproxy.tcl --
2 #
3 # Created to talk to MARS to provide replay. Also provides replay UI to
4 # DC video window
5 #
6 # Copyright (c) 2000-2002 The Regents of the University of California.
7 # All rights reserved.
8 #
9 # Redistribution and use in source and binary forms, with or without
10 # modification, are permitted provided that the following conditions are met:
11 #
12 # A. Redistributions of source code must retain the above copyright notice,
13 # this list of conditions and the following disclaimer.
14 # B. Redistributions in binary form must reproduce the above copyright notice,
15 # this list of conditions and the following disclaimer in the documentation
16 # and/or other materials provided with the distribution.
17 # C. Neither the names of the copyright holders nor the names of its
18 # contributors may be used to endorse or promote products derived from this
19 # software without specific prior written permission.
20 #
21 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
22 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
25 # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
32 import Application
33 import SSAC_Client
34 import CServiceManager
35 import CService
36
37
38 Class CReplayProxyApplication -superclass { Application Observer }
39
40 ##############################################################################
41 #
42 # CReplayProxyApplication instproc InitArgs { options } {
43 #
44 # Input:
45 # options - the options object
46 #
47 # Output:
48 # none
49 #
50 # Description:
51 # Registers all options before the command line argument is parsed
52 #
53 ##############################################################################
54 CReplayProxyApplication instproc InitArgs { options } {
55
56 # for the active services
57 $options register_option -sas optSpecAS
58 $options register_option -ComPort optComPort
59 }
60
61 ##############################################################################
62 #
63 # CReplayProxyApplication instproc InitResources { options } {
64 #
65 # Input:
66 # options - the options object
67 #
68 # Output:
69 # none
70 #
71 # Description:
72 # Gives defaults for options
73 #
74 ##############################################################################
75 CReplayProxyApplication instproc InitResources { options } {
76 # for the active services
77 $options add_default optSpecAS 224.4.5.24/50000/31
78 $options add_default optComPort 0
79 }
80
81
82 ##############################################################################
83 #
84 # CReplayProxyApplication instproc init { argv } {
85 #
86 # Input:
87 # argv - command line input
88 #
89 # Output:
90 # none
91 #
92 # Description:
93 # Constructor for the object.
94 #
95 ##############################################################################
96 CReplayProxyApplication instproc init { argv } {
97 $self next ReplayProxy
98
99 # initialize some variables
100 $self instvar m_inetClientAddress
101 $self instvar m_iClientPort
102 $self instvar m_liSourceId
103 $self instvar m_szPlayPauseState
104 $self instvar m_iOffset
105 $self instvar m_iPreviousOffset
106 $self instvar m_timer
107 $self instvar m_tmStart
108 $self instvar m_tmEnd
109
110 set m_inetClientAddress ""
111 set m_iClientPort ""
112 set m_liSourceId ""
113 set m_szPlayPauseState "PLAY"
114 set m_iOffset 0
115 set m_iPreviousOffset 600000
116 set m_timer ""
117 set m_tmStart 0
118 set m_tmEnd 0
119
120
121 # Initiailization of options
122 set options [$self options]
123 $self InitArgs $options
124 $self InitResources $options
125 $options load_preferences "archival ReplayProxy"
126 set argv [$options parse_args $argv]
127
128
129 # setup the service manager stuff
130 $self instvar m_serviceManager
131 $self instvar m_lService
132
133 set iPort [$options get_option optComPort]
134 set m_serviceManager [new CServiceManager "ServiceApp" "Replay" $iPort]
135 $m_serviceManager Attach $self
136
137 set m_lService ""
138
139 # setup the ssac client
140 $self instvar m_ssacClient
141 $self instvar m_specSsacAS
142
143 set m_specSsacAS [$options get_option optSpecAS]
144 set m_ssacClient [new SSAC_Client $m_specSsacAS -]
145 $m_ssacClient attach_observer $self
146
147 $self StartReplay $argv
148 }
149
150
151 ##############################################################################
152 #
153 # CReplayProxyApplication instproc destroy { }
154 #
155 # Input:
156 # none
157 #
158 # Output:
159 # none
160 #
161 # Description:
162 # destructor
163 #
164 ##############################################################################
165 CReplayProxyApplication instproc destroy { } {
166 $self instvar m_timer
167
168 if { m_timer != "" } {
169 after cancel $m_timer
170 }
171 }
172
173
174
175 ##############################################################################
176 #
177 # CReplayProxyApplication instproc NewConnection { service }
178 #
179 # Input:
180 # service - the new service that got connected
181 #
182 # Output:
183 # 1 - if handling this service
184 # 0 - otherwise
185 #
186 # Description:
187 # A call back function for the service manager. This function will be called
188 # when a new connection has just been noticed by the service manager
189 #
190 ##############################################################################
191 CReplayProxyApplication instproc NewConnection { service } {
192 # this member should never be called.
193 puts "Replay Proxy got a new connection: exiting"
194 exit
195
196 return 0
197 }
198
199
200 ##############################################################################
201 #
202 # CReplayProxyApplication public StartReplay { arguments } {
203 #
204 # Input:
205 # arguments - the arguments that are sent by the client. It should hold
206 # the address and port of the remote client as well as all the information
207 # to start a new replay
208 #
209 # Output:
210 # none
211 #
212 # Description:
213 #
214 ##############################################################################
215 CReplayProxyApplication public StartReplay { arguments } {
216 $self instvar m_ssacClient
217 $self instvar m_specSsacAS
218 $self instvar m_inetClientAddr
219 $self instvar m_iClientPort
220
221 # parse out the arguments
222 set inetMStudioAddr [lindex $arguments 0]
223 set iMStudioPort [lindex $arguments 1]
224 set specVideo "$inetMStudioAddr/$iMStudioPort"
225 set m_inetClientAddr [lindex $arguments 2]
226 set m_iClientPort [lindex $arguments 3]
227 set szCatalogName [lindex $arguments 4]
228 set specAudio [lindex $arguments 5]
229
230 # Start filling out the description fields
231 set description ""
232 append description "START_DESCR\n"
233 append description "file: $szCatalogName\n"
234 append description "server: $m_specSsacAS\n"
235 append description "inetBroadcastAddr: video:$specVideo\n"
236 append description "inetBroadcastAddr: audio:$specAudio\n"
237 append description "END_DESCR\n"
238
239 # now get the information from the catalog file and append it to the end
240 if [catch "open $szCatalogName r" fileId] {
241 puts stderr " Can't open $szCatalogName: $fileId"
242 exit
243 }
244
245 append description [read $fileId]
246
247 # tell the server to start the video
248 $m_ssacClient open $description 0
249 }
250
251
252 ##############################################################################
253 #
254 # CReplayProxyApplication public activate { tmStart tmEnd }
255 #
256 # Input:
257 # tmStart - the start time of the replay
258 # tmEnd - the end time of the replay
259 #
260 # Output:
261 # none
262 #
263 # Description:
264 # This is a callback from the client-ssac object which tells you the start
265 # and end time for the replay archive. The main function is to change the
266 # slider to have the correct start and end times
267 #
268 ##############################################################################
269 CReplayProxyApplication public activate { tmStart tmEnd } {
270 $self instvar m_tmStart
271 $self instvar m_tmEnd
272
273 set m_tmStart $tmStart
274 set m_tmEnd $tmEnd
275 }
276
277
278 ##############################################################################
279 #
280 # CReplayProxyApplication public play_update { state }
281 #
282 # Input:
283 # state - the state of the replay either play or pause
284 #
285 # Output:
286 # none
287 #
288 # Description:
289 # if the state is pause, then it's actually playing and vice-versa.
290 #
291 ##############################################################################
292 CReplayProxyApplication public play_update { state } {
293 $self instvar m_lService
294 $self instvar m_szPlayPauseState
295
296 if { $m_szPlayPauseState != $state } {
297 set m_szPlayPauseState $state
298
299 $self UpdateAllClients
300 }
301 }
302
303 ##############################################################################
304 #
305 # CReplayProxyApplication public update_title { szSessionInfo1 \
306 # szSessionInfo2 iDuration }
307 #
308 # Input:
309 # szSessionInfo1 - session info
310 # szSessionInfo2 - session info
311 # iDuration - the duration of the video
312 #
313 # Output:
314 # none
315 #
316 # Description:
317 # if the state is pause, then it's actually playing and vice-versa.
318 #
319 ##############################################################################
320 CReplayProxyApplication public update_title { szSessionInfo1 \
321 szSessionInfo2 iDuration } {
322 }
323
324
325 ##############################################################################
326 #
327 # CReplayProxyApplication public set_offset { iOffset }
328 #
329 # Input:
330 # iOffset - the new offset that the replay is on
331 #
332 # Output:
333 # none
334 #
335 # Description:
336 # if the state is pause, then it's actually playing and vice-versa.
337 #
338 ##############################################################################
339 CReplayProxyApplication public set_offset { iOffset } {
340 $self instvar m_iPreviousOffset
341 $self instvar m_iOffset
342 $self instvar m_tmStart
343 $self instvar m_tmEnd
344
345 set m_iOffset $iOffset
346
347 set duration [expr $m_tmEnd - $m_tmStart]
348 if { [expr abs($iOffset - $m_iPreviousOffset) > int($duration/20)] } {
349 set m_iPreviousOffset $iOffset
350 $self UpdateAllClients
351 }
352 }
353
354 ##############################################################################
355 #
356 # CReplayProxyApplication public ssac_reset { szMedia szAddress }
357 #
358 # Input:
359 # szMedia - the type of media that the this address is broadcasting
360 # szAddress - the address of the broadcast
361 #
362 # Output:
363 # none
364 #
365 # Description:
366 # This function will use the inputted information to start the video service
367 # connection back to the client. However, the source id's area also needed.
368 # The source id's are all in the ssac client object but we don't have a good
369 # interface to get them. Changing this callback function would adversely
370 # affect other programs using this object. So a hack will be made.
371 #
372 ##############################################################################
373 CReplayProxyApplication public ssac_reset { szMedia szAddress } {
374 $self instvar m_ssacClient
375 $self instvar m_liSourceId
376 $self instvar m_lService
377 $self instvar m_inetClientAddr
378 $self instvar m_iClientPort
379 $self instvar m_serviceManager
380 $self instvar m_lService
381
382 # I'm only interested in video streams right now
383 if { $szMedia != "video" } {
384 return
385 }
386
387 # I'm breaking the abstraction layer for the ssac. I'm going to dig deep
388 # into it's data structure to get to the source id's for the archive
389 # stream being sent.
390 set lSessionList [$m_ssacClient set sesslist_]
391
392 foreach sess $lSessionList {
393 if { [$m_ssacClient set session_($sess,Address)] == $szAddress && \
394 [$m_ssacClient set session_($sess,Media)] == $szMedia } {
395 set liSourceId [$m_ssacClient set session_($sess,SourceId)]
396 break
397 }
398 }
399
400 foreach iSourceId $liSourceId {
401 # see if we've already dealt with this source id
402 if { [lsearch -exact $m_liSourceId $iSourceId] == -1 } {
403 lappend m_liSourceId $iSourceId
404
405 set service [$m_serviceManager NewService $m_inetClientAddr \
406 $m_iClientPort "VideoService" $iSourceId]
407
408 $service MapMessage "GET_UI_CONTROL" $self "GetUIControl"
409 $service MapMessage "UPDATE_CONTROL_UI" $self "UpdateControlUI"
410 $service MapMessage "PLAY_PAUSE" $self "PlayPauseCmd"
411 $service MapMessage "MOVE_SLIDER" $self "MoveSliderCmd"
412 $service MapMessage "CLOSE_LINK" $self "CloseService"
413 $service MapMessage "GET_INFO" $self GetInfo
414
415 lappend m_lService $service
416
417 }
418 }
419 }
420
421 ##############################################################################
422 #
423 # CReplayProxyApplication private GetUIControl { service arguments }
424 #
425 # Input:
426 # service - the service that called this function
427 # arguments - the ui commands that will be evaluated to update the ui
428 #
429 # Output:
430 # none
431 #
432 # Description:
433 # send the control ui commands back to the client
434 #
435 ##############################################################################
436 CReplayProxyApplication private GetUIControl { service arguments } {
437 $self instvar m_szPlayPauseState
438 $self instvar m_iOffset
439 $self instvar m_tmStart
440 $self instvar m_tmEnd
441
442 set cmd ""
443
444 # for unique variable names
445 append cmd "regsub -all -- {\\\.} \$winFrame {_} __name \n"
446
447 # the play/pause button
448 append cmd "global playPause\$__name \n"
449 append cmd "set playPause\$__name $m_szPlayPauseState \n"
450 append cmd "button \$winFrame.playPauseButton \
451 -textvariable playPause\$__name \
452 -command \"\$service Send PLAY_PAUSE \\\"\\\" \" \n"
453
454 append cmd "pack \$winFrame.playPauseButton -fill y -side right \n"
455
456 # the progress slider
457 append cmd "global slider\$__name \n"
458 append cmd "set slider\$__name [expr int($m_iOffset)] \n"
459 append cmd "scale \$winFrame.slider -orient horizontal \
460 -from 0 -to [expr int($m_tmEnd - $m_tmStart)] \
461 -tickinterval [expr int(0.49 * ($m_tmEnd - $m_tmStart))] \
462 -showvalue true \
463 -variable slider\$__name \
464 -length 200 \
465 -command \"\$service Send MOVE_SLIDER\" \n"
466 append cmd "pack \$winFrame.slider -side left -fill x -expand 1 \n"
467
468
469 $service Send CONTROL_UI $cmd
470 }
471
472 ##############################################################################
473 #
474 # CReplayProxyApplication private UpdateControlUI { service arguments }
475 #
476 # Input:
477 # service - the service that called this function
478 # arguments - the ui commands that will be evaluated to update the ui
479 #
480 # Output:
481 # none
482 #
483 # Description:
484 #
485 ##############################################################################
486 CReplayProxyApplication private UpdateControlUI { service arguments } {
487 $self instvar m_szPlayPauseState
488 $self instvar m_iOffset
489
490 set cmd ""
491
492 # for unique variable names
493 append cmd "regsub -all -- {\\\.} \$winFrame {_} __name \n"
494
495 append cmd "global playPause\$__name \n"
496 append cmd "set playPause\$__name $m_szPlayPauseState \n"
497
498 append cmd "global slider\$__name \n"
499 append cmd "set slider\$__name [expr int($m_iOffset)] \n"
500
501 $service Send UPDATE_CONTROL_UI $cmd
502 }
503
504
505 ##############################################################################
506 #
507 # CReplayProxyApplication private UpdateAllClients { }
508 #
509 # Input:
510 # none
511 #
512 # Output:
513 # none
514 #
515 # Description:
516 # this will update all the clients' ui.
517 #
518 ##############################################################################
519 CReplayProxyApplication private UpdateAllClients { } {
520 $self instvar m_lService
521
522 foreach service $m_lService {
523 $self UpdateControlUI $service ""
524 }
525 }
526
527
528 ##############################################################################
529 #
530 # CReplayProxyApplication private UpdateOffset { }
531 #
532 # Input:
533 # none
534 #
535 # Output:
536 # none
537 #
538 # Description:
539 # update the offset
540 #
541 ##############################################################################
542 CReplayProxyApplication private UpdateOffset { } {
543 $self instvar m_timer
544 $self instvar m_iOffset
545 $self instvar m_szPlayPauseState
546
547 if { $m_szPlayPauseState == "PAUSE" } {
548 incr m_iOffset 2
549 $self UpdateAllClients
550 }
551
552 set m_timer [after 2000 "$self UpdateOffset"]
553 }
554
555
556 ##############################################################################
557 #
558 # CReplayProxyApplication private PlayPauseCmd { service arguments }
559 #
560 # Input:
561 # service - the service that called this function
562 # arguments - the ui commands that will be evaluated to update the ui
563 #
564 # Output:
565 # none
566 #
567 # Description:
568 # called by the client when the user presses the play/pause button
569 #
570 ##############################################################################
571 CReplayProxyApplication private PlayPauseCmd { service arguments } {
572 $self instvar m_ssacClient
573 $self instvar m_szPlayPauseState
574 $self instvar m_iOffset
575
576 if { $m_szPlayPauseState == "PLAY" } {
577 $m_ssacClient play $m_iOffset
578 } else {
579 $m_ssacClient pause
580 }
581
582
583 }
584
585
586 ##############################################################################
587 #
588 # CReplayProxyApplication private MoveSliderCmd { service arguments } {
589 #
590 # Input:
591 # service - the service that called this function
592 # arguments - the new offset to move to
593 #
594 # Output:
595 # none
596 #
597 # Description:
598 # called by the client when the user moves the slider
599 #
600 ##############################################################################
601 CReplayProxyApplication private MoveSliderCmd { service arguments } {
602 $self instvar m_ssacClient
603 $self instvar m_szPlayPauseState
604 $self instvar m_iOffset
605
606 # set the new offset
607 set m_iOffset [expr int($arguments)]
608
609 # move position in the archive only if we're playing - ie. with pause
610 # showing. This is cause once we move, we'll be in the play mode.
611 if { $m_szPlayPauseState == "PAUSE" } {
612 $m_ssacClient send PLAY [expr int($arguments)] 1
613 }
614 }
615
616
617 ##############################################################################
618 #
619 # CReplayProxyApplication public CloseService { service arguments } {
620 #
621 # Input:
622 # service - the service that called this function
623 # arguments - the arguments associated with this call
624 #
625 # Output:
626 # none
627 #
628 # Description:
629 # This is called by the remote service client closes the service link.
630 #
631 ##############################################################################
632 CReplayProxyApplication public CloseService { service arguments } {
633 exit
634 }
635
636 # the string argument to UPDATE_INFO is put in the DC display
637 CReplayProxyApplication public GetInfo { service } {
638 $service Send UPDATE_INFO ""
639 }
640
641
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.