chore: release v0.26.0

This commit is contained in:
2026-08-20 17:53:55 +02:00
parent 47992b5f03
commit 1e507225dd
44 changed files with 3197 additions and 240 deletions
+73
View File
@@ -0,0 +1,73 @@
package udp
import (
"bytes"
"encoding/binary"
"fmt"
"strings"
"hamlog/internal/applog"
)
// WSJT-X Halt Tx (message type 8) — "stop transmitting".
//
// The same two things the Halt Tx button and the Enable Tx toggle do in the
// application's own window:
//
// Halt Tx type 8
// id utf8 the target application's own id
// auto_tx_only bool false = stop the transmission NOW
// true = let this over finish, then stop auto-Tx
//
// Both are useful and they are not the same operation. Stopping mid-over is what
// you want when you have called the wrong station or realised the frequency is
// occupied; finishing the over first is what you want when the QSO is complete
// and cutting the transmission would leave the other end waiting for a report
// that never lands.
const wsjtMsgHaltTx = 8
// EncodeHaltTx builds the datagram. autoTxOnly false halts immediately.
func EncodeHaltTx(programID string, autoTxOnly bool) []byte {
var b bytes.Buffer
_ = binary.Write(&b, binary.BigEndian, uint32(wsjtMagic))
_ = binary.Write(&b, binary.BigEndian, uint32(2)) // schema 2 — what every current sender speaks
_ = binary.Write(&b, binary.BigEndian, uint32(wsjtMsgHaltTx))
writeQString(&b, programID)
var auto uint8
if autoTxOnly {
auto = 1
}
_ = binary.Write(&b, binary.BigEndian, auto)
return b.Bytes()
}
// SendHaltTx tells one decoding application to stop transmitting.
//
// Routed by PROGRAM ID and answered back to the address that instance's packets
// arrive from, exactly like SendReply: two receivers can share one multicast
// group, and halting the 20 m instance because the 6 m one is transmitting would
// be worse than doing nothing.
func (m *Manager) SendHaltTx(programID string, autoTxOnly bool) error {
if strings.TrimSpace(programID) == "" {
return fmt.Errorf("no application id — cannot tell which receiver to halt")
}
m.mu.Lock()
servers := make([]*Server, 0, len(m.inbound))
for _, s := range m.inbound {
servers = append(servers, s)
}
m.mu.Unlock()
for _, s := range servers {
conn, addr := s.replyTarget(programID)
if conn == nil || addr == nil {
continue
}
if _, err := conn.WriteToUDP(EncodeHaltTx(programID, autoTxOnly), addr); err != nil {
return fmt.Errorf("send halt to %s at %s: %w", programID, addr, err)
}
applog.Printf("udp: halt tx sent to %s at %s (auto_tx_only=%v)", programID, addr, autoTxOnly)
return nil
}
return fmt.Errorf("no packet has arrived from %q yet — nothing to halt", programID)
}