2024-04-03 18:52:04 -06:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2024-04-06 16:38:14 -06:00
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
|
|
|
|
"git.metznet.ca/MetzNet/pnyx"
|
2024-04-08 11:28:52 -06:00
|
|
|
"github.com/gen2brain/malgo"
|
2024-04-03 18:52:04 -06:00
|
|
|
)
|
|
|
|
|
|
|
|
func main() {
|
2024-04-08 11:28:52 -06:00
|
|
|
ctx, err := malgo.InitContext(nil, malgo.ContextConfig{}, nil)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
defer ctx.Free()
|
|
|
|
defer ctx.Uninit()
|
|
|
|
|
2024-04-08 11:32:39 -06:00
|
|
|
// Playback devices.
|
|
|
|
infos, err := ctx.Devices(malgo.Playback)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
2024-04-08 11:56:34 -06:00
|
|
|
var playback_device *malgo.DeviceInfo = nil
|
2024-04-08 11:46:43 -06:00
|
|
|
for _, info := range infos {
|
|
|
|
if info.IsDefault != 0 {
|
2024-04-08 11:56:34 -06:00
|
|
|
full, err := ctx.DeviceInfo(malgo.Playback, info.ID, malgo.Shared)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
playback_device = &full
|
2024-04-08 11:46:43 -06:00
|
|
|
}
|
2024-04-08 11:32:39 -06:00
|
|
|
}
|
|
|
|
|
2024-04-08 11:56:34 -06:00
|
|
|
if playback_device == nil {
|
|
|
|
panic("No default playback device")
|
|
|
|
}
|
|
|
|
|
2024-04-08 11:32:39 -06:00
|
|
|
infos, err = ctx.Devices(malgo.Capture)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
2024-04-08 11:56:34 -06:00
|
|
|
var capture_device *malgo.DeviceInfo = nil
|
2024-04-08 11:46:43 -06:00
|
|
|
for _, info := range infos {
|
|
|
|
if info.IsDefault != 0 {
|
2024-04-08 11:56:34 -06:00
|
|
|
full, err := ctx.DeviceInfo(malgo.Capture, info.ID, malgo.Shared)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
capture_device = &full
|
2024-04-08 11:46:43 -06:00
|
|
|
}
|
2024-04-08 11:32:39 -06:00
|
|
|
}
|
|
|
|
|
2024-04-08 11:56:34 -06:00
|
|
|
if capture_device == nil {
|
|
|
|
panic("No default capture device")
|
|
|
|
}
|
|
|
|
|
2024-04-08 11:28:52 -06:00
|
|
|
inDeviceConfig := malgo.DefaultDeviceConfig(malgo.Capture)
|
2024-04-08 11:56:34 -06:00
|
|
|
inDeviceConfig.Capture.Format = capture_device.Formats[0].Format
|
2024-04-08 11:58:32 -06:00
|
|
|
inDeviceConfig.Capture.Channels = capture_device.Formats[0].Channels
|
2024-04-08 11:47:56 -06:00
|
|
|
inDeviceConfig.Capture.DeviceID = capture_device.ID.Pointer()
|
2024-04-08 11:56:34 -06:00
|
|
|
inDeviceConfig.SampleRate = capture_device.Formats[0].SampleRate
|
2024-04-08 11:28:52 -06:00
|
|
|
inDeviceConfig.PeriodSizeInFrames = 100
|
|
|
|
inDeviceConfig.Alsa.NoMMap = 1
|
|
|
|
inDeviceConfig.Capture.ShareMode = malgo.Shared
|
|
|
|
|
|
|
|
outDeviceConfig := malgo.DefaultDeviceConfig(malgo.Playback)
|
2024-04-08 11:56:34 -06:00
|
|
|
outDeviceConfig.Playback.Format = playback_device.Formats[0].Format
|
2024-04-08 11:58:32 -06:00
|
|
|
outDeviceConfig.Playback.Channels = playback_device.Formats[0].Channels
|
2024-04-08 11:47:56 -06:00
|
|
|
outDeviceConfig.Playback.DeviceID = playback_device.ID.Pointer()
|
2024-04-08 11:56:34 -06:00
|
|
|
outDeviceConfig.SampleRate = playback_device.Formats[0].SampleRate
|
2024-04-08 11:28:52 -06:00
|
|
|
outDeviceConfig.PeriodSizeInFrames = 100
|
|
|
|
outDeviceConfig.Alsa.NoMMap = 1
|
|
|
|
outDeviceConfig.Playback.ShareMode = malgo.Shared
|
|
|
|
|
|
|
|
mic := make(chan []byte, 0)
|
|
|
|
speaker := make(chan []byte, 0)
|
|
|
|
|
|
|
|
onSendFrames := func(output_samples []byte, input_samples []byte, framecount uint32) {
|
|
|
|
select {
|
|
|
|
case data := <- speaker:
|
|
|
|
copy(output_samples, data)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
playbackCallbacks := malgo.DeviceCallbacks{
|
|
|
|
Data: onSendFrames,
|
|
|
|
}
|
|
|
|
|
2024-04-08 11:58:32 -06:00
|
|
|
fmt.Printf("Creating playback device %+v with format %+v\n", playback_device, playback_device.Formats[0])
|
2024-04-08 11:28:52 -06:00
|
|
|
outDevice, err := malgo.InitDevice(ctx.Context, outDeviceConfig, playbackCallbacks)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
2024-04-08 11:46:43 -06:00
|
|
|
fmt.Printf("Starting playback\n")
|
2024-04-08 11:28:52 -06:00
|
|
|
err = outDevice.Start()
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
defer outDevice.Uninit()
|
|
|
|
defer outDevice.Stop()
|
|
|
|
|
|
|
|
onRecvFrames := func(output_samples []byte, input_samples []byte, framecount uint32) {
|
|
|
|
data := make([]byte, len(input_samples))
|
|
|
|
copy(data, input_samples)
|
|
|
|
|
|
|
|
select {
|
|
|
|
case mic <- data:
|
|
|
|
default:
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
captureCallbacks := malgo.DeviceCallbacks{
|
|
|
|
Data: onRecvFrames,
|
|
|
|
}
|
|
|
|
|
2024-04-08 11:58:32 -06:00
|
|
|
fmt.Printf("Creating capture device %+v with format %+v\n", capture_device, capture_device.Formats[0])
|
2024-04-08 11:28:52 -06:00
|
|
|
inDevice, err := malgo.InitDevice(ctx.Context, inDeviceConfig, captureCallbacks)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
2024-04-08 11:35:38 -06:00
|
|
|
fmt.Printf("Starting capture device\n")
|
2024-04-08 11:28:52 -06:00
|
|
|
err = inDevice.Start()
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
defer inDevice.Uninit()
|
|
|
|
defer inDevice.Stop()
|
|
|
|
|
|
|
|
fmt.Printf("Starting pnyx client\n")
|
|
|
|
|
2024-04-06 17:03:31 -06:00
|
|
|
client, err := pnyx.NewClient(nil, os.Args[1])
|
2024-04-03 18:52:04 -06:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2024-04-08 11:28:52 -06:00
|
|
|
|
|
|
|
go func() {
|
|
|
|
var buf [1024]byte
|
|
|
|
for true {
|
|
|
|
read, _, err := client.Connection.ReadFromUDP(buf[:])
|
|
|
|
if err != nil {
|
|
|
|
fmt.Printf("Read Error %s\n", err)
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
data, err := pnyx.ParseSessionData(&client.Session, buf[pnyx.COMMAND_LENGTH + pnyx.ID_LENGTH:read])
|
|
|
|
if err != nil {
|
|
|
|
fmt.Printf("ParseSessionData Error %s\n", err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
packet, err := pnyx.ParsePacket(data)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Printf("ParsePacket Error %s - %x\n", err, data)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
_ = pnyx.PeerID(packet.Data[0:16])
|
|
|
|
speaker <- packet.Data[16:]
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
err = client.Send(pnyx.Packet{
|
|
|
|
Channel: pnyx.ChannelID(1),
|
|
|
|
Mode: pnyx.MODE_RAW,
|
|
|
|
Command: pnyx.MODE_COMMAND_JOIN,
|
|
|
|
Data: nil,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
for true {
|
|
|
|
data := <- mic
|
|
|
|
err = client.Send(pnyx.Packet{
|
|
|
|
Channel: pnyx.ChannelID(1),
|
|
|
|
Mode: pnyx.MODE_RAW,
|
|
|
|
Command: pnyx.MODE_COMMAND_DATA,
|
|
|
|
Data: data,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
err = client.Send(pnyx.Packet{
|
|
|
|
Channel: pnyx.ChannelID(1),
|
|
|
|
Mode: pnyx.MODE_RAW,
|
|
|
|
Command: pnyx.MODE_COMMAND_LEAVE,
|
|
|
|
Data: nil,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
err = client.Close()
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2024-04-03 18:52:04 -06:00
|
|
|
}
|