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
import (
"bytes"
"dwelling-radio/pkg/watcher"
"encoding/json"
"fmt"
"io"
"net/http"
"os/exec"
"os"
"strings"
"sync"
"syscall"
@ -17,6 +18,8 @@ import (
const (
IcecastPlaylistDateFormat = "02/Jan/2006:15:04:05 -0700"
SongTimeFormat = "2006 15:04-0700"
bufferSize = 8192
)
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) {
@ -97,45 +100,65 @@ func IcecastLastSong(playlistPath string) (Song, error) {
}
}
songs, err := lastPlayedSongs(1, playlistPath)
if len(songs) == 0 {
return Song{}, nil
song, err := lastPlayedSong(playlistPath)
if err != nil {
return Song{}, err
}
return songs[0], err
return *song, nil
}
func lastPlayedSongs(lastNSongs int, playlistPath string) ([]Song, error) {
songs := make([]Song, 0)
func lastPlayedSong(playlistPath string) (*Song, error) {
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)
out, err := exec.Command("bash", "-c", cmd).CombinedOutput()
playlist, err := os.Open(playlistPath)
if err != nil {
return songs, err
return nil, err
}
if len(out) == 0 {
return songs, nil
playlist_stat, _ := playlist.Stat()
if playlist_stat.Size() == 0 {
return nil, nil
}
for _, song := range strings.Split(string(out), "\n") {
ts := strings.Split(song, "|")
if len(ts) <= 1 {
continue
}
tim, _ := time.Parse(IcecastPlaylistDateFormat, ts[0])
songs = append(songs, Song{
Time: tim.Format(SongTimeFormat),
Listeners: ts[1],
Song: ts[2]})
playlist.Seek(-bufferSize, os.SEEK_END)
_, err = playlist.Read(buf)
if err != nil && err != io.EOF {
return nil, err
}
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 playlistFired chan uint32 = make(chan uint32)
var lastPlayedCache []Song
var lastPlayedCache []Song = make([]Song, 10)
var lastPlayedCacheMutex sync.Mutex
func IcecastWatchPlaylist(playlistPath string, lastNSongs int) error {
@ -157,9 +180,11 @@ func IcecastWatchPlaylist(playlistPath string, lastNSongs int) error {
case mask := <-playlistFired:
if mask&syscall.IN_MODIFY > 0 {
lastPlayedCacheMutex.Lock()
songs, err := lastPlayedSongs(lastNSongs, playlistPath)
if err == nil && len(songs) > 0 {
lastPlayedCache = songs
if song, err := lastPlayedSong(playlistPath); err == nil {
lastPlayedCache = append(lastPlayedCache, *song)
if len(lastPlayedCache) > lastNSongs {
lastPlayedCache = lastPlayedCache[1:]
}
}
lastPlayedCacheMutex.Unlock()
} 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
}