Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 16 additions & 12 deletions pkg/sip/inbound.go
Original file line number Diff line number Diff line change
Expand Up @@ -737,7 +737,6 @@ type inboundCall struct {
sigTs SignalingTimestamps
jitterBuf bool
projectID string
audioOut *msdk.WriteCloserSwitch[msdk.PCM16Sample] // inner writer owned by MediaPort
}

func (s *Server) newInboundCall(
Expand Down Expand Up @@ -767,7 +766,6 @@ func (s *Server) newInboundCall(
endCall: make(chan EndCall, 1),
jitterBuf: SelectValueBool(s.conf.EnableJitterBuffer, s.conf.EnableJitterBufferProb),
projectID: "", // Will be set in handleInvite when available
audioOut: msdk.NewWriteCloserSwitch[msdk.PCM16Sample](RoomSampleRate),
}
c.stats.Update()
c.setLog(log.WithValues("jitterBuf", c.jitterBuf))
Expand Down Expand Up @@ -955,6 +953,8 @@ func (c *inboundCall) handleInvite(ctx context.Context, tid traceid.ID, req *sip
ackTimeout <-chan time.Time
)

roomAudioOut := msdk.NewWriteCloserSwitch[msdk.PCM16Sample](RoomSampleRate)

acceptCall := func(answerData []byte) (bool, error) {
defer c.mon.StageDurTimer("call-accept")()
headers := disp.Headers
Expand Down Expand Up @@ -985,7 +985,7 @@ func (c *inboundCall) handleInvite(ctx context.Context, tid traceid.ID, req *sip
// Start this timer right after the Accept.
ackTimeout = time.After(inviteOkAckLateTimeout)
}
if old := c.audioOut.Swap(c.media.GetOutboundAudioWriter()); old != nil {
if old := roomAudioOut.Swap(c.media.GetOutboundAudioWriter()); old != nil {
c.log().Warnw("unexpected audio out writer", nil)
old.Close()
}
Expand All @@ -996,7 +996,7 @@ func (c *inboundCall) handleInvite(ctx context.Context, tid traceid.ID, req *sip
return true, nil
}

if err := c.createMediaPort(mconf, conf, disp.FeatureFlags); err != nil {
if err := c.createMediaPort(mconf, conf, roomAudioOut, disp.FeatureFlags); err != nil {
return rejectMedia(err)
}

Expand Down Expand Up @@ -1160,7 +1160,7 @@ func (w *pinDTMFWriter) WriteSample(msg *livekit.SipDTMF) error {
return nil
}

func (c *inboundCall) createMediaPort(mconf *sipMediaConfig, conf *config.Config, featureFlags map[string]string) error {
func (c *inboundCall) createMediaPort(mconf *sipMediaConfig, conf *config.Config, roomAudioOut *msdk.WriteCloserSwitch[msdk.PCM16Sample], featureFlags map[string]string) error {
c.mmu.Lock()
defer c.mmu.Unlock()
if c.media != nil {
Expand Down Expand Up @@ -1191,7 +1191,7 @@ func (c *inboundCall) createMediaPort(mconf *sipMediaConfig, conf *config.Config
c.mediaCodecs = mconf.Codecs

// Mixer is created with the room; attach it now so pin prompts can play.
if old := c.lkRoom.WriteOutboundAudioTo(c.audioOut); old != nil {
if old := c.lkRoom.WriteOutboundAudioTo(roomAudioOut); old != nil {
c.log().Warnw("room has unexpected outbound audio writer", nil)
old.Close()
}
Expand Down Expand Up @@ -1736,21 +1736,25 @@ func (c *inboundCall) transferCall(ctx context.Context, transferTo string, heade

if dialtone && c.started.IsBroken() && !c.done.Load() {
const ringVolume = math.MaxInt16 / 2
rctx, rcancel := context.WithCancel(ctx)
defer rcancel()

// Mute the room audio to the SIP participant.
// Skip closing the existing writer, which is c.audioOut.
_ = c.lkRoom.WriteOutboundAudioTo(nil)
oldRoomAudioOut := c.lkRoom.WriteOutboundAudioTo(nil)

defer func() {
if retErr != nil && !c.done.Load() {
c.lkRoom.WriteOutboundAudioTo(c.audioOut)
c.lkRoom.WriteOutboundAudioTo(oldRoomAudioOut)
} else {
if err := oldRoomAudioOut.Close(); err != nil {
c.log().Warnw("failed to close old audio output", err)
}
}
}()
Comment thread
devin-ai-integration[bot] marked this conversation as resolved.

rctx, rcancel := context.WithCancel(ctx)
defer rcancel()

go func() {
err := tones.Play(rctx, c.audioOut, ringVolume, tones.ETSIRinging)
err := tones.Play(rctx, oldRoomAudioOut, ringVolume, tones.ETSIRinging)
Comment thread
alexfish8 marked this conversation as resolved.
if err != nil && !errors.Is(err, context.Canceled) && !errors.Is(err, context.DeadlineExceeded) {
c.log().Infow("cannot play dial tone", "error", err)
}
Expand Down