Skip to content

Commit f78131b

Browse files
author
Datanoise
committed
fix: implement truly graceful and rapid shutdown by signaling long-polling handlers
1 parent 349e1ff commit f78131b

6 files changed

Lines changed: 418 additions & 330 deletions

File tree

go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ require (
1111
require (
1212
github.com/braheezy/shine-mp3 v0.1.0 // indirect
1313
github.com/dhowden/tag v0.0.0-20240417053706-3d75831295e8 // indirect
14+
github.com/djimenez/iconv-go v0.0.0-20160305225143-8960e66bd3da // indirect
1415
github.com/dustin/go-humanize v1.0.1 // indirect
1516
github.com/go-audio/audio v1.0.0 // indirect
1617
github.com/go-audio/riff v1.0.0 // indirect
@@ -20,6 +21,7 @@ require (
2021
github.com/hajimehoshi/go-mp3 v0.3.4 // indirect
2122
github.com/kazzmir/opus-go v1.2.1 // indirect
2223
github.com/mattn/go-isatty v0.0.20 // indirect
24+
github.com/mikkyang/id3-go v0.0.0-20191012064224-2c6ab3bb1fbd // indirect
2325
github.com/pion/datachannel v1.6.0 // indirect
2426
github.com/pion/dtls/v3 v3.1.2 // indirect
2527
github.com/pion/ice/v4 v4.2.1 // indirect

go.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
44
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
55
github.com/dhowden/tag v0.0.0-20240417053706-3d75831295e8 h1:OtSeLS5y0Uy01jaKK4mA/WVIYtpzVm63vLVAPzJXigg=
66
github.com/dhowden/tag v0.0.0-20240417053706-3d75831295e8/go.mod h1:apkPC/CR3s48O2D7Y++n1XWEpgPNNCjXYga3PPbJe2E=
7+
github.com/djimenez/iconv-go v0.0.0-20160305225143-8960e66bd3da h1:0qwwqQCLOOXPl58ljnq3sTJR7yRuMolM02vjxDh4ZVE=
8+
github.com/djimenez/iconv-go v0.0.0-20160305225143-8960e66bd3da/go.mod h1:ns+zIWBBchgfRdxNgIJWn2x6U95LQchxeqiN5Cgdgts=
79
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
810
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
911
github.com/glebarez/go-sqlite v1.22.0 h1:uAcMJhaA6r3LHMTFgP0SifzgXg46yJkgxqyuyec+ruQ=
@@ -29,6 +31,8 @@ github.com/kazzmir/opus-go v1.2.1 h1:uKHJgA4zlZv60eatfwGBhLdrovlPdRVBVco22MQQvmU
2931
github.com/kazzmir/opus-go v1.2.1/go.mod h1:oKDlLYxYVpknE4zKDmJyiLPB9RyhKw0n/l7EoPr6000=
3032
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
3133
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
34+
github.com/mikkyang/id3-go v0.0.0-20191012064224-2c6ab3bb1fbd h1:Cqivkwpk34qJJsi0xbZp2TOhpMsG381iaum8mb+6T/s=
35+
github.com/mikkyang/id3-go v0.0.0-20191012064224-2c6ab3bb1fbd/go.mod h1:6ReX25kzt2D67Dt9vH3kTm8R4luFEfW9W3RDuytp0IA=
3236
github.com/pion/datachannel v1.6.0 h1:XecBlj+cvsxhAMZWFfFcPyUaDZtd7IJvrXqlXD/53i0=
3337
github.com/pion/datachannel v1.6.0/go.mod h1:ur+wzYF8mWdC+Mkis5Thosk+u/VOL287apDNEbFpsIk=
3438
github.com/pion/dtls/v3 v3.1.2 h1:gqEdOUXLtCGW+afsBLO0LtDD8GnuBBjEy6HRtyofZTc=

playlists/foo.pls

439 Bytes
Binary file not shown.

relay/streamer.go

Lines changed: 55 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/DatanoiseTV/tinyice/config"
1515
"github.com/dhowden/tag"
1616
"github.com/hajimehoshi/go-mp3"
17+
"github.com/mikkyang/id3-go"
1718
"github.com/sirupsen/logrus"
1819
)
1920

@@ -48,6 +49,7 @@ type Streamer struct {
4849

4950
fileCancel context.CancelFunc
5051
titleCache map[string]string
52+
titleFetchWg sync.WaitGroup
5153

5254
// Stats
5355
BytesStreamed int64
@@ -114,6 +116,12 @@ func (s *Streamer) ToggleInjectMetadata() {
114116
s.InjectMetadata = !s.InjectMetadata
115117
}
116118

119+
func (s *Streamer) ClearQueue() {
120+
s.mu.Lock()
121+
defer s.mu.Unlock()
122+
s.Queue = []string{}
123+
}
124+
117125
func (s *Streamer) Stop() {
118126
s.mu.Lock()
119127
defer s.mu.Unlock()
@@ -149,8 +157,18 @@ func (s *Streamer) RemoveFromQueue(index int) {
149157
s.Queue = append(s.Queue[:index], s.Queue[index+1:]...)
150158
}
151159

152-
type PlaylistItem struct {
153-
Title string
160+
func (s *Streamer) MoveQueueItem(from, to int) {
161+
s.mu.Lock()
162+
defer s.mu.Unlock()
163+
if from < 0 || from >= len(s.Queue) || to < 0 || to >= len(s.Queue) {
164+
return
165+
}
166+
item := s.Queue[from]
167+
s.Queue = append(s.Queue[:from], s.Queue[from+1:]...)
168+
s.Queue = append(s.Queue[:to], append([]string{item}, s.Queue[to:]...)...)
169+
}
170+
171+
type PlaylistItem struct { Title string
154172
Path string
155173
}
156174

@@ -172,31 +190,50 @@ func (s *Streamer) GetPlaylistInfo() []PlaylistItem {
172190

173191
func (s *Streamer) GetSongTitle(path string) string {
174192
s.mu.RLock()
175-
defer s.mu.RUnlock()
176193
if title, ok := s.titleCache[path]; ok {
194+
s.mu.RUnlock()
177195
return title
178196
}
197+
s.mu.RUnlock()
198+
199+
// Trigger background fetch if not already in progress
200+
go s.fetchTitleAndCache(path)
201+
202+
// Fallback to filename if no title found (yet)
179203
return filepath.Base(path)
180204
}
181205

182-
func (s *Streamer) fetchTitleAndCache(path string) string {
183-
title := filepath.Base(path)
184-
f, err := os.Open(path)
185-
if err == nil {
186-
if m, err := tag.ReadFrom(f); err == nil {
187-
if m.Artist() != "" && m.Title() != "" {
188-
title = fmt.Sprintf("%s - %s", m.Artist(), m.Title())
189-
} else if m.Title() != "" {
190-
title = m.Title()
206+
func (s *Streamer) fetchTitleAndCache(path string) {
207+
s.titleFetchWg.Add(1)
208+
go func() {
209+
defer s.titleFetchWg.Done()
210+
211+
s.mu.Lock()
212+
if _, ok := s.titleCache[path]; ok {
213+
s.mu.Unlock()
214+
return // Already fetched by another concurrent call
215+
}
216+
s.mu.Unlock()
217+
218+
title := filepath.Base(path)
219+
220+
// Use id3-go for extraction
221+
if file, err := id3.Open(path); err == nil {
222+
defer file.Close()
223+
artist := strings.TrimSpace(file.Artist())
224+
song := strings.TrimSpace(file.Title())
225+
226+
if artist != "" && song != "" {
227+
title = fmt.Sprintf("%s - %s", artist, song)
228+
} else if song != "" {
229+
title = song
191230
}
192231
}
193-
f.Close()
194-
}
195232

196-
s.mu.Lock()
197-
s.titleCache[path] = title
198-
s.mu.Unlock()
199-
return title
233+
s.mu.Lock()
234+
s.titleCache[path] = title
235+
s.mu.Unlock()
236+
}()
200237
}
201238

202239
func (s *Streamer) GetQueueInfo() []PlaylistItem {

0 commit comments

Comments
 (0)