diff --git a/main.go b/main.go index 0b10af0..08c34d4 100644 --- a/main.go +++ b/main.go @@ -11,6 +11,7 @@ import ( "os/exec" "regexp" "strings" + "time" "golang.org/x/net/html" ) @@ -19,7 +20,7 @@ type MPVRequest struct { Command []string `json:"command"` } type MPVResponsePlayback struct { - Data float32 `json:"data"` + Data float64 `json:"data"` } type MPV struct { @@ -72,7 +73,7 @@ func (mpv *MPV) ExecuteIPC(req *MPVRequest) ([]byte, error) { return resBytes[:n], nil } -func (mpv *MPV) InquirePlayback() (float32, error) { +func (mpv *MPV) InquirePlayback() (float64, error) { resBytes, err := mpv.ExecuteIPC(&MPVRequest{ Command: []string{"get_property", "playback-time"}, }) @@ -131,31 +132,111 @@ func ParseWebMedia(url string) (string, error) { re := regexp.MustCompile(`url:.*'(.*)'`) if match := re.FindAllStringSubmatch(streamChannels, 1); match != nil { - fmt.Println(match) - return match[0][1], nil } else { return "", fmt.Errorf("regex failed") } } -var testUrl string +const MPTV_SPAWN_GRACE = 5 * time.Second +const MPTV_INQUIRE_INTERVAL = time.Second +const MPTV_MAX_ATTEMPTS = 1 + +var web string +var socketPath string func main() { - flag.StringVar(&testUrl, "test-url", "", "test url") + flag.StringVar(&web, "web", "", "web media") + flag.StringVar(&socketPath, "sock", "", "where to place socket") flag.Parse() - // mpv := NewMPV(testUrl, "/tmp/mptv3.sock") - // mpv.Spawn() - // defer mpv.Stop() + streamUrl, err := ParseWebMedia(web) + if err != nil { + fmt.Fprintf(os.Stderr, "failed to get stream: %s\n", err) + return + } - // for { - // time.Sleep(time.Second * 2) - // _, err := mpv.InquirePlayback() + mpv := NewMPV(streamUrl, socketPath) + if err = mpv.Spawn(); err != nil { + fmt.Fprintln(os.Stderr, err) + return + } + time.Sleep(MPTV_SPAWN_GRACE) - // fmt.Println(err) - // } + playback := 0.0 + lastPlayback := 0.0 + attempt := 0 - stream, err := ParseWebMedia(testUrl) - fmt.Println(stream, err) + for { + fmt.Printf("playback %f lastPlayback %f attempt %d\n", playback, lastPlayback, attempt) + + // inquire + playback, err = mpv.InquirePlayback() + if err != nil { + // dead mpv, restart + streamUrl, err = ParseWebMedia(web) + if err != nil { + fmt.Fprintf(os.Stderr, "failed to get stream: %s\n", err) + // dont exit loop here since web request may fail due internet outage + } + + mpv = NewMPV(streamUrl, socketPath) + if err = mpv.Spawn(); err != nil { + // failed to spawn mpv this time? fatal + fmt.Fprintln(os.Stderr, err) + return + } + + // reset values + playback = 0.0 + lastPlayback = 0.0 + attempt = 0 + + // skip this cycle + time.Sleep(MPTV_SPAWN_GRACE) + continue + } + + if lastPlayback == 0.0 { + // first init of last playback, dont count as attempt + lastPlayback = playback + } else if playback == lastPlayback { + // playback stuck, increment attempt + attempt += 1 + if attempt > MPTV_MAX_ATTEMPTS { + // attempts exceeded, shoot in the head old mpv + mpv.Stop() + + // respawn mpv + streamUrl, err = ParseWebMedia(web) + if err != nil { + fmt.Fprintf(os.Stderr, "failed to get stream: %s\n", err) + // dont exit loop here since web request may fail due internet outage + } + + mpv = NewMPV(streamUrl, socketPath) + if err = mpv.Spawn(); err != nil { + // failed to spawn mpv this time? fatal + fmt.Fprintln(os.Stderr, err) + return + } + + // reset values + playback = 0.0 + lastPlayback = 0.0 + attempt = 0 + + // skip this cycle + time.Sleep(MPTV_SPAWN_GRACE) + continue + } + } else { + // playback doesnt match last playback that was already initalized - we're good + lastPlayback = playback + attempt = 0 + } + + // new cycle + time.Sleep(MPTV_INQUIRE_INTERVAL) + } }