~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Open Mash Cross Reference
mash/tcl/vat/ui-audio.tcl

Component: ~ [ mash ] ~ [ apps ] ~ [ gsm ] ~ [ lib ] ~ [ otcl ] ~ [ srm ] ~ [ tcl8.3 ] ~ [ tclcl ] ~ [ tk8.3 ] ~ [ tutorials ] ~

  1 # ui-audio.tcl --
  2 #
  3 #       FIXME: This file needs a description here.
  4 #
  5 # Copyright (c) 1993-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/src/mash/repository/mash/mash-1/tcl/vat/ui-audio.tcl,v 1.13 1997/12/23 05:31:51 mccanne Exp $
 32 
 33 
 34 import Observable Configuration CoordinationBus
 35 
 36 #
 37 # The AudioArbiter is used to negotiate with other processes for control
 38 # over the host's audio device.  Multiple applications might want to
 39 # simultaneously access the underlying audio hardware, but many such
 40 # devices cannot be shared because of the operating system's contraints
 41 # on the API.  Thus, we have explicit methods for obtaining and
 42 # releasing the underlying hardware resources.
 43 # <p>
 44 #
 45 # The AudioArbiter is also an Observable so an Observer, e.g. a UI, can watch
 46 # its status (i.e. Do we have the device? Did we just get it so we
 47 # should raise the window?, etc.)
 48 #
 49 Class AudioArbiter -superclass {CoordinationBus Observable} -configuration {
 50         idleDropTime 20
 51         defaultPriority 100
 52 }
 53 
 54 #
 55 # Create an arbiter to represent the given AudioAgent, <i>agent</i>.
 56 # Register CoordinationBus messages to suit the following device bus API: <br>
 57 # <dd> $cb send audio-demand $pid
 58 # <dd> $cb send audio-request $pid $pri
 59 # <dd> $cb send audio-release $pid
 60 #
 61 AudioArbiter public init agent {
 62         # the default coordbus channel is 0
 63         # so, we get the base channel for the global stuff
 64         $self next
 65         $self instvar agent_ activity_ id_ priority_ hold_
 66         set agent_ $agent
 67         set hold_ 0
 68 
 69         $self register audio-demand someone_demands
 70         $self register audio-request someone_requests
 71         $self register audio-release someone_released
 72 
 73         set activity_ 0
 74         set priority_ [$self get_option defaultPriority]
 75         set id_ [after 5000 "$self timeout"]
 76 }
 77 
 78 #
 79 # Cancel the "timeout".
 80 #
 81 AudioArbiter instproc destroy {} {
 82         $self instvar id_
 83         after cancel $id_
 84         $self next
 85 }
 86 
 87 #
 88 # Set the priority, <i>p</i>, that this arbiter has over the control of the audio device.
 89 #
 90 AudioArbiter instproc set-pri p {
 91         $self instvar priority_
 92         set priority_ $p
 93 }
 94 
 95 #
 96 # Close the audio device.
 97 #
 98 AudioArbiter public release {} {
 99         $self instvar agent_
100         $agent_ release
101         $self indicator_update
102 }
103 
104 #
105 # Callback when someone requests the audio.  If we have the audio, it's
106 # not pinned, and it's unmuted, we must relinquish it to anyone with higher
107 # priority.  #
108 #
109 AudioArbiter public someone_requests { pid pri } {
110         $self instvar agent_ priority_ hold_
111         global unmuted outputMutebutton
112         if { [$agent_ have_audio] && !$hold_ && ($pri > $priority_) } {
113 
114 #FIXME FIX unmuted ref
115 #               || !$unmuted($outputMutebutton))} {
116                 #
117                 # we have the audio, it's not pinned, and someone
118                 # with a high priority wants it or we have it muted.
119                 # give it up to them.
120                 #
121                 $self give_it_up $pid
122         }
123 }
124 
125 #
126 # Close the audio device, and advertise that it's
127 # been released to the conference bus.
128 #
129 AudioArbiter private give_it_up pid {
130         $self release
131         $self send audio-release $pid
132 }
133 
134 #
135 # Callback when someone demands the audio
136 # If we have it, honor request.
137 #
138 AudioArbiter public someone_demands pid {
139         $self instvar agent_
140         if { [$agent_ have_audio] } {
141                 #
142                 # we have the audio and someone demanded it.
143                 # give it up.
144                 #
145                 $self give_it_up $pid
146         }
147 }
148 
149 #
150 # Callback when someone releases the audio to process <i>pid</i>.  If
151 # the audio was released to us, i.e. if the pid matches, try to grab it.
152 #
153 AudioArbiter public someone_released pid {
154         if { $pid == [pid] } {
155                 #
156                 # someone released the audio to us.
157                 # try to grab it -- if we fail, somebody else
158                 # got it and give up (shouldn't happen because
159                 # pids are unique).
160                 #
161                 $self grab
162                 $self notify_observers arbiter_snatch
163         }
164 }
165 
166 #
167 # Update the title bar indicator to show whether or
168 # not we have the device open.
169 #
170 AudioArbiter instproc indicator_update { } {
171         $self instvar agent_ activity_ hold_
172         if [$agent_ have_audio] {
173                 $self notify_observers arbiter_have 1
174                 #
175                 # when we're not running off the audio clock, our time base
176                 # can shift pretty badly (especially on PC's where gettimeofday
177                 # accuracy is low).  so we reset all our clock offsets whenever
178                 # we recover the audio device.
179                 #
180                 $agent_ reset_source_offsets
181         } else {
182                 $self notify_observers arbiter_have 0
183                 set hold_ 0
184         }
185         set activity_ [$agent_ unix_time]
186 }
187 
188 #
189 # Attempt to open and intialize the underlying audio hardware.  After
190 # <i>grab</i> is called, the AudioAgent <i>haveaudio</i> method can be
191 # queried to see if the device was successfully opened.  Once obtained,
192 # the device can be released with the AudioAgent <i>release</i> method.
193 #
194 AudioArbiter public grab {} {
195         $self instvar agent_
196         $agent_ obtain
197         $self indicator_update
198 }
199 
200 #
201 # Ask for the audio, but don't demand it, because it
202 # might be in use for more important things.  First,
203 # just try to open the device directly.  If that fails,
204 # ask the vat that has it to give it up via the conference bus.
205 #
206 AudioArbiter public request {} {
207         # first just try to see if we can get it
208         $self instvar agent_ priority_
209         $agent_ obtain
210         if [$agent_ have_audio] {
211                 $self indicator_update
212         } else {
213                 $self send audio-request [pid] $priority_
214         }
215 }
216 
217 #
218 # Demand the audio.  Whoever has it will hear us, close the
219 # device, and eventually notify us back over the conference bus.
220 #
221 AudioArbiter public demand {} {
222         $self instvar agent_
223         $agent_ obtain
224         if [$agent_ have_audio] {
225                 $self indicator_update
226         } else {
227                 $self send audio-demand [pid]
228         }
229 }
230 
231 #
232 # Demand the audio device if <i>v</i> is true and the AudioAgent does not have_audio.
233 #
234 AudioArbiter public hold v {
235         $self instvar hold_ agent_
236         set hold_ $v
237         if { $hold_ && ![$agent_ have_audio] } {
238                 $self demand
239         }
240 }
241 
242 #
243 # Periodically check the status of the AudioAgent, releasing the audio
244 # device if the AudioAgent has been inactive for given amount of time.
245 #
246 AudioArbiter private timeout {} {
247         $self instvar activity_ agent_ id_ hold_
248 
249         if { [$agent_ have_audio] && !$hold_ } {
250                 if [$agent_ is_active] {
251                         $agent_ clear_active
252                         set activity_ [$agent_ unix_time]
253                 } else {
254                         set r [$self get_option idleDropTime]
255                         if { $r && [$agent_ unix_time] - $activity_ > \
256                             $r } {
257                                 $self give_it_up 0
258                         }
259                 }
260         }
261         set id_ [after 5000 "$self timeout"]
262 }
263 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.