Skip to content

Commit

Permalink
* Improve the handling of the buffer/stream by adding some params to …
Browse files Browse the repository at this point in the history
…the struct, adapt the appearance of the update notification

    * Use constants for error codes
    * Enhance the buffer again
    * Move frontend code to the web folder
    * Add german language (in dev mode)
    * Now autoreconnect can be used, update the web client

Signed-off-by: Marcel Goerentz <m.goerentz@t-online.de>
  • Loading branch information
marcelGoerentz committed Jan 9, 2025
1 parent 5b5a02b commit b36f16f
Show file tree
Hide file tree
Showing 46 changed files with 1,141 additions and 546 deletions.
86 changes: 36 additions & 50 deletions src/buffer.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,77 +8,60 @@ import (
"os"

"github.com/avfs/avfs"
"github.com/avfs/avfs/vfs/memfs"
"github.com/avfs/avfs/vfs/osfs"
)

/*
InitBufferVFS will set the bufferVFS variable
*/
func InitBufferVFS(virtual bool) {

if virtual {
bufferVFS = memfs.New()
} else {
bufferVFS = osfs.New()
func (b *Buffer) StartBuffer(stream *Stream, errorChan chan ErrorInfo) {
if stream.UseBackup {
UpdateStreamURLForBackup(stream)
}

}

func StartBuffer(stream *Stream, useBackup bool, backupNumber int, errorChan chan ErrorInfo) *Buffer {
if useBackup {
UpdateStreamURLForBackup(stream, backupNumber)
}

if err := PrepareBufferFolder(stream.Folder); err != nil {
var err error = nil
if err = PrepareBufferFolder(stream.Buffer.FileSystem, stream.Folder); err != nil {
ShowError(err, 4008)
HandleBufferError(err, backupNumber, useBackup, stream, errorChan)
return nil
handleBufferError(err, stream, errorChan)
return
}

switch Settings.Buffer {
case "ffmpeg", "vlc":
if buffer, err := StartThirdPartyBuffer(stream, useBackup, backupNumber, errorChan); err != nil {
return HandleBufferError(err, backupNumber, useBackup, stream, errorChan)
} else {
return buffer
}
err = StartThirdPartyBuffer(stream, errorChan)
case "threadfin":
if buffer, err := StartThreadfinBuffer(stream, useBackup, backupNumber, errorChan); err != nil {
return HandleBufferError(err, backupNumber, useBackup, stream, errorChan)
} else {
return buffer
}
err = StartThreadfinBuffer(stream, errorChan)
default:
return nil
return
}
if err != nil {
handleBufferError(err, stream, errorChan)
}
}

/*
HandleBufferError will retry running the Buffer function with the next backup number
*/
func HandleBufferError(err error, backupNumber int, useBackup bool, stream *Stream, errorChan chan ErrorInfo) *Buffer {
func handleBufferError(err error, stream *Stream, errorChan chan ErrorInfo) {
ShowError(err, 4011)
if !useBackup || (useBackup && backupNumber >= 0 && backupNumber <= 3) {
backupNumber++
if !stream.UseBackup || (stream.UseBackup && stream.BackupNumber >= 0 && stream.BackupNumber <= 3) {
stream.BackupNumber++
if stream.BackupChannel1URL != "" || stream.BackupChannel2URL != "" || stream.BackupChannel3URL != "" {
return StartBuffer(stream, true, backupNumber, errorChan)
stream.UseBackup = true
stream.Buffer.StartBuffer(stream, errorChan)
}
}
return nil
}

/*
HandleByteOutput save the byte ouptut of the command or http request as files
*/
func HandleByteOutput(stdOut io.ReadCloser, stream *Stream, errorChan chan ErrorInfo) {
bufferSize := Settings.BufferSize * 1024 // Puffergröße in Bytes
TS_PACKAGE_MIN_SIZE := 188
bufferSize := Settings.BufferSize * 1024 // in bytes
buffer := make([]byte, bufferSize)
var fileSize int
init := true
tmpFolder := stream.Folder + string(os.PathSeparator)
tmpSegment := 1
tmpSegment := stream.LatestSegment

var bufferVFS = stream.Buffer.FileSystem
var f avfs.File
var err error
var tmpFile string
Expand All @@ -89,7 +72,7 @@ func HandleByteOutput(stdOut io.ReadCloser, stream *Stream, errorChan chan Error
f, err = bufferVFS.Create(tmpFile)
if err != nil {
f.Close()
ShowError(err, 4010)
ShowError(err, CreateFileError)
errorChan <- ErrorInfo{CreateFileError, stream, ""}
return
}
Expand All @@ -106,30 +89,33 @@ func HandleByteOutput(stdOut io.ReadCloser, stream *Stream, errorChan chan Error
return
}
if err != nil {
if _, ok := err.(*net.OpError); !ok || stream.Buffer.isThirdPartyBuffer {
ShowError(err, 4012)
if _, ok := err.(*net.OpError); !ok || stream.Buffer.IsThirdPartyBuffer {
ShowError(err, ReadIntoBufferError)
}
f.Close()
bufferVFS.Remove(tmpFile)
errorChan <- ErrorInfo{ReadIntoBufferError, stream, ""}
return
}
if _, err := f.Write(buffer[:n]); err != nil {
ShowError(err, 4013)
ShowError(err, WriteToBufferError)
f.Close()
bufferVFS.Remove(tmpFile)
errorChan <- ErrorInfo{WriteToBufferError, stream, ""}
return
}
fileSize += n
// Prüfen, ob Dateigröße den Puffer überschreitet
if fileSize >= bufferSize {
// Check if the file size exceeds the threshold
if fileSize >= TS_PACKAGE_MIN_SIZE * 1024 {
tmpSegment++
tmpFile = fmt.Sprintf("%s%d.ts", tmpFolder, tmpSegment)
// Datei schließen und neue Datei öffnen
// Close the current file and create a new one
f.Close()
stream.LatestSegment = tmpSegment
f, err = bufferVFS.Create(tmpFile)
if err != nil {
f.Close()
ShowError(err, 4010)
ShowError(err, CreateFileError)
errorChan <- ErrorInfo{CreateFileError, stream, ""}
return
}
Expand All @@ -141,8 +127,8 @@ func HandleByteOutput(stdOut io.ReadCloser, stream *Stream, errorChan chan Error
/*
UpdateStreamURLForBackup will set the ther stream url when a backup will be used
*/
func UpdateStreamURLForBackup(stream *Stream, backupNumber int) {
switch backupNumber {
func UpdateStreamURLForBackup(stream *Stream) {
switch stream.BackupNumber {
case 1:
stream.URL = stream.BackupChannel1URL
ShowHighlight("START OF BACKUP 1 STREAM")
Expand All @@ -161,7 +147,7 @@ func UpdateStreamURLForBackup(stream *Stream, backupNumber int) {
/*
PrepareBufferFolder will clean the buffer folder and check if the folder exists
*/
func PrepareBufferFolder(folder string) error {
func PrepareBufferFolder(bufferVFS avfs.VFS, folder string) error {
if err := bufferVFS.RemoveAll(getPlatformPath(folder)); err != nil {
return fmt.Errorf("failed to remove buffer folder: %w", err)
}
Expand Down
12 changes: 3 additions & 9 deletions src/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"strings"
"sync"

"github.com/avfs/avfs"
//"github.com/avfs/avfs"
"golang.org/x/text/cases"
"golang.org/x/text/language"
)
Expand All @@ -27,14 +27,8 @@ var Data DataStruct
// SystemFiles : Alle Systemdateien
var SystemFiles = []string{"authentication.json", "pms.json", "settings.json", "xepg.json", "urls.json"}

// BufferInformation : Informationen über den Buffer (aktive Streams, maximale Streams)
var BufferInformation sync.Map

// bufferVFS : Filesystem to use for the Buffer
var bufferVFS avfs.VFS

// BufferClients : Anzahl der Clients die einen Stream über den Buffer abspielen
var BufferClients sync.Map
//var bufferVFS avfs.VFS

// Lock : Lock Map
var Lock = sync.RWMutex{}
Expand Down Expand Up @@ -201,7 +195,7 @@ func Init() (err error) {
// HTML Dateien erstellen, mit dev == true werden die lokalen HTML Dateien verwendet
if System.Dev {

HTMLInit("webUI", "src", "html"+string(os.PathSeparator), "src"+string(os.PathSeparator)+"webUI.go")
HTMLInit("webUI", "src", strings.Join([]string{"web", "public"}, string(os.PathSeparator)), "src"+string(os.PathSeparator)+"webUI.go")
err = BuildGoFile()
if err != nil {
return
Expand Down
31 changes: 13 additions & 18 deletions src/internal/imgcache/imagecache.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,21 +60,20 @@ func (ic *ImageCache) GetImageURL(url string) (string) {
ic.mutex.Unlock()

if ic.caching {
// Create the filename and path to the file
filename := createFileNameFromURL(url, key)
path_to_file := ic.basePath + filename
url_to_file := ic.baseURL + "/images/" + filename

// Enqueue the Image for the download
ic.EnqueueURL(url, path_to_file)

// Save file name in cache
ic.mutex.Lock()
ic.cache[key] = url_to_file
ic.cache[key] = url_to_file // Save url to file in cache
ic.mutex.Unlock()
return url_to_file
} else {
// Save original url in cache
return url
return url // Return original url if caching is disabled
}
}

Expand All @@ -90,8 +89,7 @@ func (ic *ImageCache) DownloadImage(url string, filename string) (error) {
// Download the image
resp, err := client.Get(url)
if err != nil {
ic.ErrorHandlingWhenDownloading(url)
return errors.New("error when downloading the image")
return ic.handleDownloadError(url, "error when downloading the image")
}
defer resp.Body.Close()

Expand All @@ -100,41 +98,38 @@ func (ic *ImageCache) DownloadImage(url string, filename string) (error) {
url = "https://" + strings.Split(url, "//")[1]
resp, err = client.Get(url)
if err != nil {
ic.ErrorHandlingWhenDownloading(url)
return errors.New("error when downloading the image")
return ic.handleDownloadError(url, "error when downloading the image")
}
if resp.StatusCode != http.StatusOK {
ic.ErrorHandlingWhenDownloading(url)
return errors.New("received bad status code")
return ic.handleDownloadError(url, "received bad status code")
}
} else {
ic.ErrorHandlingWhenDownloading(url)
return errors.New("received bad status code")
return ic.handleDownloadError(url, "received bad status code")
}
}

// Save the image to disk
file, err := os.Create(filename)
if err != nil {
ic.ErrorHandlingWhenDownloading(url)
return errors.New("unable to create the file")
return ic.handleDownloadError(url, "unable to create the file")
}
defer file.Close()

_, err = io.Copy(file, resp.Body)
if err != nil {
ic.ErrorHandlingWhenDownloading(url)
return errors.New("can't save the image to the file")
os.Remove(filename)
return ic.handleDownloadError(url, "can't save the image to the file")
}
return nil
}
return nil
}

func (ic *ImageCache) ErrorHandlingWhenDownloading(url string) {
func (ic *ImageCache) handleDownloadError(url, message string) error {
ic.mutex.Lock()
defer ic.mutex.Unlock()
ic.cache[url]=url
ic.cache[url]=url // Save original url in cache
return errors.New(message)
}

// Block until downloads have been completed
Expand Down
2 changes: 2 additions & 0 deletions src/screen.go
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,8 @@ func getErrMsg(errCode int) (errMsg string) {
errMsg = "Could not read buffered file before sending to clients"
case 4017:
errMsg = "Cannot stream from M3U file, please use ffmpeg or VLC"
case 4018:
errMsg = "Error while reading thirdparty stdErr"

// PID saving and deleting
case 4040:
Expand Down
Loading

0 comments on commit b36f16f

Please sign in to comment.