1
0
mirror of https://github.com/stryan/mumble-discord-bridge.git synced 2024-11-26 22:45:43 -05:00
mumble-discord-bridge/internal/bridge/mumble.go

144 lines
3.3 KiB
Go
Raw Normal View History

package bridge
2020-10-29 02:21:07 -04:00
import (
2021-02-01 16:03:38 -05:00
"context"
2020-10-29 02:21:07 -04:00
"log"
"strconv"
2020-10-29 02:21:07 -04:00
"sync"
"time"
"github.com/stieneee/gumble/gumble"
_ "github.com/stieneee/gumble/opus"
"github.com/stieneee/mumble-discord-bridge/pkg/sleepct"
2020-10-29 02:21:07 -04:00
)
// MumbleDuplex - listener and outgoing
type MumbleDuplex struct {
mutex sync.Mutex
fromMumbleArr []chan gumble.AudioBuffer
mumbleStreamingArr []bool
mumbleSleepTick sleepct.SleepCT
}
func NewMumbleDuplex() *MumbleDuplex {
return &MumbleDuplex{
fromMumbleArr: make([]chan gumble.AudioBuffer, 0),
mumbleStreamingArr: make([]bool, 0),
mumbleSleepTick: sleepct.SleepCT{},
}
}
2021-09-13 00:50:23 -04:00
2020-10-29 02:21:07 -04:00
// OnAudioStream - Spawn routines to handle incoming packets
func (m *MumbleDuplex) OnAudioStream(e *gumble.AudioStreamEvent) {
2020-10-29 02:21:07 -04:00
// hold a reference ot the channel in the closure
streamChan := make(chan gumble.AudioBuffer, 100)
2020-10-29 02:21:07 -04:00
m.mutex.Lock()
m.fromMumbleArr = append(m.fromMumbleArr, streamChan)
m.mumbleStreamingArr = append(m.mumbleStreamingArr, false)
m.mutex.Unlock()
2020-10-29 02:21:07 -04:00
promMumbleArraySize.Set(float64(len(m.fromMumbleArr)))
go func() {
2021-04-06 22:34:38 -04:00
name := e.User.Name
log.Println("New mumble audio stream", name)
2021-04-06 22:34:38 -04:00
for p := range e.C {
// log.Println("audio packet", p.Sender.Name, len(p.AudioBuffer))
// 480 per 10ms
for i := 0; i < len(p.AudioBuffer)/480; i++ {
streamChan <- p.AudioBuffer[480*i : 480*(i+1)]
2020-10-29 02:21:07 -04:00
}
promReceivedMumblePackets.Inc()
m.mumbleSleepTick.Notify()
2020-10-29 02:21:07 -04:00
}
log.Println("Mumble audio stream ended", name)
}()
2020-10-29 02:21:07 -04:00
}
func (m *MumbleDuplex) fromMumbleMixer(ctx context.Context, cancel context.CancelFunc, toDiscord chan []int16) {
m.mumbleSleepTick.Start(10 * time.Millisecond)
2020-10-29 02:21:07 -04:00
sendAudio := false
2021-04-15 00:43:12 -04:00
droppingPackets := false
droppingPacketCount := 0
2020-10-29 02:21:07 -04:00
for {
select {
2021-02-01 16:03:38 -05:00
case <-ctx.Done():
log.Println("Stopping From Mumble Mixer")
return
default:
}
2021-02-01 16:03:38 -05:00
promTimerMumbleMixer.Observe(float64(m.mumbleSleepTick.SleepNextTarget(ctx, false)))
2020-10-29 02:21:07 -04:00
m.mutex.Lock()
2020-10-29 02:21:07 -04:00
sendAudio = false
internalMixerArr := make([]gumble.AudioBuffer, 0)
streamingCount := 0
2020-10-29 02:21:07 -04:00
// Work through each channel
for i := 0; i < len(m.fromMumbleArr); i++ {
if len(m.fromMumbleArr[i]) > 0 {
2020-10-29 02:21:07 -04:00
sendAudio = true
if !m.mumbleStreamingArr[i] {
m.mumbleStreamingArr[i] = true
streamingCount++
// log.Println("Mumble starting", i)
2020-10-29 02:21:07 -04:00
}
x1 := (<-m.fromMumbleArr[i])
2020-10-29 02:21:07 -04:00
internalMixerArr = append(internalMixerArr, x1)
} else {
if m.mumbleStreamingArr[i] {
m.mumbleStreamingArr[i] = false
// log.Println("Mumble stopping", i)
2020-10-29 02:21:07 -04:00
}
}
}
m.mutex.Unlock()
2020-10-29 02:21:07 -04:00
promMumbleStreaming.Set(float64(streamingCount))
2021-04-18 00:30:27 -04:00
if sendAudio {
2020-10-29 02:21:07 -04:00
2021-04-18 00:30:27 -04:00
outBuf := make([]int16, 480)
2020-10-29 02:21:07 -04:00
2021-04-18 00:30:27 -04:00
for i := 0; i < len(outBuf); i++ {
for j := 0; j < len(internalMixerArr); j++ {
outBuf[i] += (internalMixerArr[j])[i]
}
2021-04-15 00:43:12 -04:00
}
2021-04-18 00:30:27 -04:00
promToDiscordBufferSize.Set(float64(len(toDiscord)))
select {
case toDiscord <- outBuf:
{
if droppingPackets {
log.Println("Discord buffer ok, total packets dropped " + strconv.Itoa(droppingPacketCount))
droppingPackets = false
}
}
default:
if !droppingPackets {
log.Println("Error: toDiscord buffer full. Dropping packets")
droppingPackets = true
droppingPacketCount = 0
}
droppingPacketCount++
promToDiscordDropped.Inc()
if droppingPacketCount > 250 {
log.Println("Discord Timeout")
cancel()
}
}
2020-10-29 02:21:07 -04:00
}
}
}