#
# Copyright (c) 1993-1995 Regents of the University of California.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
#    must display the following acknowledgement:
#	This product includes software developed by the Network Research
#	Group at Lawrence Berkeley National Laboratory.
# 4. Neither the name of the University nor of the Laboratory may be used
#    to endorse or promote products derived from this software without
#    specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# @(#) $Header: ui-audio.tcl,v 1.10 96/01/08 19:48:07 van Exp $ (LBL)
#
#

#
# device bus API
# $cb send "audio-demand $pid"
# $cb send "audio-request $pid $pri"
# $cb send "audio-release $pid"
#
set cb_dispatch(audio-demand) audio_someone_demands
set cb_dispatch(audio-request) audio_someone_requests
set cb_dispatch(audio-release) audio_someone_released

set audio_activity 0

proc audio_someone_requests { pid pri } {
	global audioHeld V unmuted outputMutebutton
	if { [audio have] && !$audioHeld && ($pri > $V(priority) \
		|| !$unmuted($outputMutebutton))} {
		#
		# we have the audio, it's not pinned, and someone
		# with a high priority wants it or we have it muted.
		# give it up to them.
		#
		audio_give_it_up $pid
	}
}

proc audio_release {} {
	audio release 
	audio_indicator_update
}

#
# close the audio device and advertise that it's
# been released to the conference bus
#
proc audio_give_it_up pid {
	global V
	audio_release 
	$V(devbus) send "audio-release $pid"
}

#
# callback when someone demands the audio
# if we have it, honor request
#
proc audio_someone_demands pid {
	if { [audio have] } {
		#
		# we have the audio and someone demanded it.
		# give it up.
		#
		audio_give_it_up $pid
	}
}

#
# callback when someone requests the audio.
# honor request only if it makes sense.
#
proc audio_someone_released pid {
	global V autoRaise
	if { $pid == [pid] } {
		#
		# someone released the audio to us.
		# try to grab it -- if we fail, somebody else
		# got it and give up (shouldn't happen because
		# pids are unique).
		#
		audio_grab
		if $autoRaise {
			raise .
		}
	}
}

#
# when we're not running off the audio clock, our time base
# can shift pretty badly (especially on PC's where gettimeofday
# accuracy is low).  so we reset all our clock offsets whenever
# we recover the audio device.
#
proc reset_source_offsets {} {
	foreach src [session active] {
		[$src handler] reset-offset
	}
}

#
# update the title bar indicator to show whether or
# not we have the device open
#
proc audio_indicator_update { } {
	global audioHeld title_bar audio_activity
	if [audio have] {
		$title_bar configure -font [ctrlfont]
		reset_source_offsets
	} else {
		$title_bar configure -font [option get . noAudioFont Vat]
		set audioHeld 0
	}
	set audio_activity [controller unix-time]
}

proc audio_grab {} {
	global V
	audio obtain
	audio_indicator_update
}

#
# ask for the audio, but don't demand it because it
# might be in use for more important things.  first,
# just try to open the device directly.  if that fails
# ask the vat who has it to give it up via the conference bus.
#
proc audio_request {} {
	# first just try to see if we can get it
	audio obtain
	if [audio have] {
		audio_indicator_update
	} else {
		global V
		$V(devbus) send "audio-request [pid] $V(priority)"
	}
}

#
# demand the audio.  whoever has it will hear us, close the
# device, and eventually notify us back over the conference bus.
# 
proc audio_demand {} {
	audio obtain
	if [audio have] {
		audio_indicator_update
	} else {
		global V
		$V(devbus) send "audio-demand [pid]"
	}
}

proc audio_timeout {} {
	global audioHeld audio_activity
	if { [audio have] && !$audioHeld } {
		if [controller active] {
			controller active 0
			set audio_activity [controller unix-time]
		} else {
			set r [resource idleDropTime]
			if { $r && [controller unix-time] - $audio_activity > \
			    $r } {
				audio_give_it_up 0
			}
		}
	}
	after 5000 audio_timeout
}
