1
0

Implemented lastPlayedSong() function that retrieves one song from a playlist.log file that doesn't run external commands for it.

And now we start with an empty list.
This commit is contained in:
Alexander Andreev 2022-08-29 08:58:35 +04:00
parent 23f246857e
commit c935db8ce7
Signed by: Arav
GPG Key ID: 0388CC8FAA51063F

View File

@ -1,11 +1,12 @@
package radio package radio
import ( import (
"bytes"
"dwelling-radio/pkg/watcher" "dwelling-radio/pkg/watcher"
"encoding/json" "encoding/json"
"fmt" "io"
"net/http" "net/http"
"os/exec" "os"
"strings" "strings"
"sync" "sync"
"syscall" "syscall"
@ -17,6 +18,8 @@ import (
const ( const (
IcecastPlaylistDateFormat = "02/Jan/2006:15:04:05 -0700" IcecastPlaylistDateFormat = "02/Jan/2006:15:04:05 -0700"
SongTimeFormat = "2006 15:04-0700" SongTimeFormat = "2006 15:04-0700"
bufferSize = 8192
) )
type IcecastStatusDTO struct { type IcecastStatusDTO struct {
@ -85,7 +88,7 @@ func IcecastLastPlayedSongs(lastNSongs int, playlistPath string) ([]Song, error)
} }
} }
return lastPlayedSongs(lastNSongs, playlistPath) return make([]Song, 0), nil
} }
func IcecastLastSong(playlistPath string) (Song, error) { func IcecastLastSong(playlistPath string) (Song, error) {
@ -97,45 +100,65 @@ func IcecastLastSong(playlistPath string) (Song, error) {
} }
} }
songs, err := lastPlayedSongs(1, playlistPath) song, err := lastPlayedSong(playlistPath)
if len(songs) == 0 { if err != nil {
return Song{}, nil return Song{}, err
} }
return songs[0], err return *song, nil
} }
func lastPlayedSongs(lastNSongs int, playlistPath string) ([]Song, error) { func lastPlayedSong(playlistPath string) (*Song, error) {
songs := make([]Song, 0) buf := make([]byte, bufferSize)
var last_song_line string
cmd := fmt.Sprintf("tail -n%d %s | head -n-1 | cut -d'|' -f1,3,4", lastNSongs+1, playlistPath) playlist, err := os.Open(playlistPath)
out, err := exec.Command("bash", "-c", cmd).CombinedOutput()
if err != nil { if err != nil {
return songs, err return nil, err
} }
if len(out) == 0 { playlist_stat, _ := playlist.Stat()
return songs, nil
if playlist_stat.Size() == 0 {
return nil, nil
} }
for _, song := range strings.Split(string(out), "\n") { playlist.Seek(-bufferSize, os.SEEK_END)
ts := strings.Split(song, "|")
if len(ts) <= 1 { _, err = playlist.Read(buf)
continue if err != nil && err != io.EOF {
} return nil, err
tim, _ := time.Parse(IcecastPlaylistDateFormat, ts[0])
songs = append(songs, Song{
Time: tim.Format(SongTimeFormat),
Listeners: ts[1],
Song: ts[2]})
} }
return songs, nil newline_end_pos := bytes.LastIndexByte(buf, '\n')
if newline_end_pos == -1 && !bytes.ContainsRune(buf, '|') {
return nil, nil
} else if newline_end_pos == -1 {
newline_end_pos = len(buf)
}
newline_start_pos := bytes.LastIndexByte(buf[:newline_end_pos-1], '\n')
last_song_line = string(buf[newline_start_pos+1 : newline_end_pos-1])
if strings.Count(last_song_line, "|") != 3 {
return nil, nil
}
fields := strings.Split(last_song_line, "|")
tim, _ := time.Parse(IcecastPlaylistDateFormat, fields[0])
return &Song{
Time: tim.Format(SongTimeFormat),
Listeners: fields[2],
Song: fields[3]}, nil
} }
var playlistWatcher watcher.InotifyWatcher var playlistWatcher watcher.InotifyWatcher
var playlistFired chan uint32 = make(chan uint32) var playlistFired chan uint32 = make(chan uint32)
var lastPlayedCache []Song var lastPlayedCache []Song = make([]Song, 10)
var lastPlayedCacheMutex sync.Mutex var lastPlayedCacheMutex sync.Mutex
func IcecastWatchPlaylist(playlistPath string, lastNSongs int) error { func IcecastWatchPlaylist(playlistPath string, lastNSongs int) error {
@ -157,9 +180,11 @@ func IcecastWatchPlaylist(playlistPath string, lastNSongs int) error {
case mask := <-playlistFired: case mask := <-playlistFired:
if mask&syscall.IN_MODIFY > 0 { if mask&syscall.IN_MODIFY > 0 {
lastPlayedCacheMutex.Lock() lastPlayedCacheMutex.Lock()
songs, err := lastPlayedSongs(lastNSongs, playlistPath) if song, err := lastPlayedSong(playlistPath); err == nil {
if err == nil && len(songs) > 0 { lastPlayedCache = append(lastPlayedCache, *song)
lastPlayedCache = songs if len(lastPlayedCache) > lastNSongs {
lastPlayedCache = lastPlayedCache[1:]
}
} }
lastPlayedCacheMutex.Unlock() lastPlayedCacheMutex.Unlock()
} else if mask&syscall.IN_IGNORED > 0 { } else if mask&syscall.IN_IGNORED > 0 {
@ -171,13 +196,6 @@ func IcecastWatchPlaylist(playlistPath string, lastNSongs int) error {
} }
}() }()
lastPlayedCacheMutex.Lock()
songs, err := lastPlayedSongs(lastNSongs, playlistPath)
if err == nil && len(songs) > 0 {
lastPlayedCache = songs
}
lastPlayedCacheMutex.Unlock()
return nil return nil
} }