Let the operator edit the station config in the window instead of hand-editing the file and relaunching.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+62
-8
@@ -36,17 +36,37 @@ func (s *Station) Run(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
s.mu.Lock()
|
||||
if s.fatal != "" {
|
||||
if s.fatal != "" || !s.loaded {
|
||||
s.mu.Unlock()
|
||||
<-ctx.Done()
|
||||
return nil
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil
|
||||
case <-s.wake:
|
||||
}
|
||||
continue
|
||||
}
|
||||
s.kick = false
|
||||
s.state.Connection = "Connecting"
|
||||
s.publish()
|
||||
host, port := s.cfg.host, s.cfg.port
|
||||
epoch := s.epoch
|
||||
dialCtx, dialCancel := context.WithCancel(ctx)
|
||||
s.cancelDial = dialCancel
|
||||
s.mu.Unlock()
|
||||
|
||||
conn, err := dialStation(ctx, host, port)
|
||||
conn, err := dialStation(dialCtx, host, port)
|
||||
dialCancel()
|
||||
s.mu.Lock()
|
||||
s.cancelDial = nil
|
||||
stale := s.epoch != epoch
|
||||
s.mu.Unlock()
|
||||
if stale {
|
||||
if conn != nil {
|
||||
conn.Close()
|
||||
}
|
||||
s.drainApply()
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
if ctx.Err() != nil {
|
||||
return nil
|
||||
@@ -61,17 +81,28 @@ func (s *Station) Run(ctx context.Context) error {
|
||||
continue
|
||||
}
|
||||
|
||||
err = s.session(ctx, conn, major)
|
||||
err = s.session(ctx, conn, major, epoch)
|
||||
conn.Close()
|
||||
fallback := errors.Is(err, errFallback)
|
||||
reconnect := errors.Is(err, errReconnect)
|
||||
s.mu.Lock()
|
||||
s.closeUDP()
|
||||
if s.conn == conn {
|
||||
s.conn = nil
|
||||
}
|
||||
s.mic = nil
|
||||
s.play = nil
|
||||
s.audioHeard = false
|
||||
s.flushWaiting = false
|
||||
if fallback || reconnect {
|
||||
kicked := s.kick
|
||||
if kicked {
|
||||
s.kick = false
|
||||
s.drainApply()
|
||||
if s.up {
|
||||
s.noteDownLocked(s.clock.Now(), false)
|
||||
}
|
||||
}
|
||||
if fallback || reconnect || kicked {
|
||||
s.roomBusy = false
|
||||
s.remoteTalker = ""
|
||||
s.mu.Unlock()
|
||||
@@ -120,6 +151,8 @@ func (s *Station) wait(ctx context.Context, d time.Duration) bool {
|
||||
return false
|
||||
case <-timer.C():
|
||||
return true
|
||||
case <-s.apply:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,7 +296,21 @@ const (
|
||||
phChallenge
|
||||
)
|
||||
|
||||
func (s *Station) session(ctx context.Context, conn net.Conn, major uint16) error {
|
||||
func (s *Station) session(ctx context.Context, conn net.Conn, major uint16, epoch uint64) error {
|
||||
s.mu.Lock()
|
||||
s.conn = conn
|
||||
stale := s.epoch != epoch
|
||||
s.mu.Unlock()
|
||||
if stale {
|
||||
return errReconnect
|
||||
}
|
||||
defer func() {
|
||||
s.mu.Lock()
|
||||
if s.conn == conn {
|
||||
s.conn = nil
|
||||
}
|
||||
s.mu.Unlock()
|
||||
}()
|
||||
done := make(chan struct{})
|
||||
var closeOnce sync.Once
|
||||
closeConn := func() { closeOnce.Do(func() { conn.Close() }) }
|
||||
@@ -721,7 +768,7 @@ func (s *Station) closeUDP() {
|
||||
}
|
||||
|
||||
func (s *Station) transmitting() bool {
|
||||
if s.fatal != "" || s.state.Connection != "Connected" || s.roomBusy {
|
||||
if s.configOpen || s.fatal != "" || s.state.Connection != "Connected" || s.roomBusy {
|
||||
return false
|
||||
}
|
||||
return s.buttonHeld || s.spaceHeld
|
||||
@@ -731,6 +778,8 @@ func (s *Station) publish() {
|
||||
s.noteTransmitLocked()
|
||||
s.state.Callsign = s.cfg.callsign
|
||||
s.state.TalkGroup = s.cfg.talkGroup
|
||||
s.state.NeedsConfig = !s.loaded
|
||||
s.state.ConfigOpen = s.configOpen
|
||||
if s.fatal != "" {
|
||||
s.state.Connection = "Disconnected"
|
||||
s.state.Detail = s.fatal
|
||||
@@ -764,6 +813,11 @@ func (s *Station) publish() {
|
||||
}
|
||||
}
|
||||
}
|
||||
if s.configOpen && s.configErr != "" {
|
||||
s.state.Detail = s.configErr
|
||||
} else if s.openBlocked != "" {
|
||||
s.state.Detail = s.openBlocked
|
||||
}
|
||||
select {
|
||||
case s.wake <- struct{}{}:
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user