|
|
@ -271,16 +271,35 @@ func get_private_key(path string, generate bool) ed25519.PrivateKey {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func main_loop(client *pnyx.Client, audio_data chan []int16, window ncurses.Window, packet_chan chan pnyx.Payload, user_chan chan rune) {
|
|
|
|
func print_decoration(window, channels, body ncurses.Window, top_left string) {
|
|
|
|
max_y := ncurses.GetMaxY(window)
|
|
|
|
max_y := ncurses.GetMaxY(*ncurses.CurScr)
|
|
|
|
max_x := ncurses.GetMaxX(window)
|
|
|
|
max_x := ncurses.GetMaxX(*ncurses.CurScr)
|
|
|
|
titlebar := ncurses.NewWin(1, max_x, 0, 0)
|
|
|
|
|
|
|
|
channels := ncurses.NewWin(max_y - 1, max_x / 3, 1, 0)
|
|
|
|
|
|
|
|
body := ncurses.NewWin(max_y - 1, max_x * 2 / 3, 1, max_x / 3)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ncurses.MvWAddStr(titlebar, 0, 0, fmt.Sprintf("pnyx client %X:%X", client.Key.Public().(ed25519.PublicKey)[:2], client.Session.ID[:2]))
|
|
|
|
ncurses.WResize(channels, max_y - 2, (max_x / 4) - 1)
|
|
|
|
ncurses.MvWAddStr(body, 0, max_x-len(client.Remote()), client.Remote())
|
|
|
|
ncurses.WResize(body, max_y - 2, max_x - (max_x / 4) - 1)
|
|
|
|
ncurses.WRefresh(titlebar)
|
|
|
|
ncurses.MvWin(body, 2, (max_x / 4) + 1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ncurses.MvWAddStr(window, 0, 0, top_left)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for i := 0; i < max_x; i++ {
|
|
|
|
|
|
|
|
ncurses.MvWAddStr(window, 1, i, "═")
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ncurses.MvWAddStr(window, 1, max_x/4, "╦")
|
|
|
|
|
|
|
|
for i := 2; i < max_y; i++ {
|
|
|
|
|
|
|
|
ncurses.MvWAddStr(window, i, max_x/4, "║")
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ncurses.WRefresh(window)
|
|
|
|
|
|
|
|
ncurses.WRefresh(channels)
|
|
|
|
|
|
|
|
ncurses.WRefresh(body)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func main_loop(client *pnyx.Client, audio_data chan []int16, window ncurses.Window, packet_chan chan pnyx.Payload, user_chan chan []byte) {
|
|
|
|
|
|
|
|
channels := ncurses.NewWin(0, 0, 2, 0)
|
|
|
|
|
|
|
|
body := ncurses.NewWin(0, 0, 2, 0)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
print_decoration(window, channels, body, fmt.Sprintf("pnyx client %X:%X", client.Key.Public().(ed25519.PublicKey)[:2], client.Session.ID[:2]))
|
|
|
|
|
|
|
|
|
|
|
|
for client.Active() {
|
|
|
|
for client.Active() {
|
|
|
|
select {
|
|
|
|
select {
|
|
|
@ -325,30 +344,12 @@ func main_loop(client *pnyx.Client, audio_data chan []int16, window ncurses.Wind
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case char := <-user_chan:
|
|
|
|
case char := <-user_chan:
|
|
|
|
ncurses.MvWAddStr(body, 0, 0, string(char))
|
|
|
|
ncurses.WAddStr(body, string(char))
|
|
|
|
ncurses.WRefresh(body)
|
|
|
|
ncurses.WRefresh(body)
|
|
|
|
|
|
|
|
|
|
|
|
ncurses.MvWAddStr(channels, 0, 0, string(char))
|
|
|
|
|
|
|
|
ncurses.WRefresh(channels)
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func bitmatch(b byte, pattern byte, length int) bool {
|
|
|
|
|
|
|
|
mask := ^(byte(1 << (8 - length)) - 1)
|
|
|
|
|
|
|
|
return (b ^ pattern) & mask == 0
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func ch_listen(client *pnyx.Client, user_chan chan rune) {
|
|
|
|
|
|
|
|
b := [4]byte{}
|
|
|
|
|
|
|
|
for client.Active() {
|
|
|
|
|
|
|
|
os.Stdin.Read(b[0:1])
|
|
|
|
|
|
|
|
if bitmatch(b[0], 0b00000000, 1) {
|
|
|
|
|
|
|
|
user_chan <- rune(b[0])
|
|
|
|
|
|
|
|
} // TODO: further utf-8 support
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func process_mic(client *pnyx.Client, mic chan []byte) {
|
|
|
|
func process_mic(client *pnyx.Client, mic chan []byte) {
|
|
|
|
for true {
|
|
|
|
for true {
|
|
|
|
data := <- mic
|
|
|
|
data := <- mic
|
|
|
@ -380,7 +381,7 @@ func main() {
|
|
|
|
defer inDevice.Stop()
|
|
|
|
defer inDevice.Stop()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
user_chan := make(chan rune, 1024)
|
|
|
|
user_chan := make(chan []byte, 1024)
|
|
|
|
packet_chan := make(chan pnyx.Payload, 1024)
|
|
|
|
packet_chan := make(chan pnyx.Payload, 1024)
|
|
|
|
|
|
|
|
|
|
|
|
key := get_private_key(os.ExpandEnv(*key_file_arg), *generate_key_arg)
|
|
|
|
key := get_private_key(os.ExpandEnv(*key_file_arg), *generate_key_arg)
|
|
|
@ -409,15 +410,24 @@ func main() {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
go process_mic(client, mic)
|
|
|
|
go process_mic(client, mic)
|
|
|
|
go ch_listen(client, user_chan)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
locale := ncurses.SetLocale(0, "")
|
|
|
|
|
|
|
|
fmt.Printf("locale: %s\n", locale)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
user_chan, stdin_active := ncurses.UTF8Listener(100, os.Stdin)
|
|
|
|
window := ncurses.InitScr()
|
|
|
|
window := ncurses.InitScr()
|
|
|
|
|
|
|
|
ret := ncurses.StartColor()
|
|
|
|
|
|
|
|
if ret != 0 {
|
|
|
|
|
|
|
|
panic(ret)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
go main_loop(client, audio_data, window, packet_chan, user_chan)
|
|
|
|
go main_loop(client, audio_data, window, packet_chan, user_chan)
|
|
|
|
|
|
|
|
|
|
|
|
os_sigs := make(chan os.Signal, 1)
|
|
|
|
os_sigs := make(chan os.Signal, 1)
|
|
|
|
signal.Notify(os_sigs, syscall.SIGINT, syscall.SIGABRT)
|
|
|
|
signal.Notify(os_sigs, syscall.SIGINT, syscall.SIGABRT)
|
|
|
|
|
|
|
|
|
|
|
|
<-os_sigs
|
|
|
|
<-os_sigs
|
|
|
|
|
|
|
|
stdin_active.Store(false)
|
|
|
|
client.Close()
|
|
|
|
client.Close()
|
|
|
|
ncurses.EndWin()
|
|
|
|
ncurses.EndWin()
|
|
|
|
}
|
|
|
|
}
|
|
|
|