diff --git a/ui/slideshow.go b/ui/slideshow.go index 58494e9..00d8aca 100644 --- a/ui/slideshow.go +++ b/ui/slideshow.go @@ -3,7 +3,9 @@ package ui import ( "context" "io" + "io/ioutil" "log" + "os" "os/exec" "syscall" "time" @@ -11,19 +13,102 @@ import ( "github.com/eiannone/keyboard" "github.com/knadh/koanf" - pfconfig "git.kemonine.info/PiFrame/config" + "git.kemonine.info/PiFrame/config" ) const ( - CMD_FIM = "/usr/local/bin/pf-fim.sh" + PATH_TEMP_FOR_SLIDESHOW = "/run/piframe/fim" ) -func Slideshow(config *koanf.Koanf) { +func Slideshow(pfconfig *koanf.Koanf) { + // Prep folder setup needed for fim + // fim does NOT allow multiple folders passed on the CLI (as far as KemoNine can tell) + // We build a temp folder stup in /run/piframe/fim that has symlinks to selected albums + // After we build up this directory setup we'll kick off fim against the temp dir with recursive + // /run is a tmpfs so this won't wear on the sd card storage + + // Create temp folder + _, err := os.Stat(PATH_TEMP_FOR_SLIDESHOW) + if os.IsNotExist(err) { + errDir := os.MkdirAll(PATH_TEMP_FOR_SLIDESHOW, 0755) + if errDir != nil { + log.Fatalf("Error setting up slideshow : %s", err) + } + } + + // Cleanup temp folder if it already existed + dirRead, err := os.Open(PATH_TEMP_FOR_SLIDESHOW) + if err != nil { + log.Fatalf("Error setting up slideshow : %s", err) + } + dirFiles, err := dirRead.Readdir(0) + if err != nil { + log.Fatalf("Error setting up slideshow : %s", err) + } + // Loop over the directory's files. + for index := range(dirFiles) { + fileHere := dirFiles[index] + + // Get name of file and its full path. + nameHere := fileHere.Name() + fullPath := PATH_TEMP_FOR_SLIDESHOW + "/" + nameHere + + // Remove the file. + err = os.Remove(fullPath) + if err != nil { + log.Fatalf("Error setting up slideshow : %s", err) + } + } + + // Setup symlinks to selected albums to be used with slideshow + // Add albums full paths to command line args for fim + albumRootPath := pfconfig.String(config.CONFIG_KEY_ALBUMS_ROOT) + for _, album := range pfconfig.Strings(config.CONFIG_KEY_ALBUMS_SELECTED) { + source := albumRootPath + album + destination := PATH_TEMP_FOR_SLIDESHOW + album + if album == "/" { + files, err := ioutil.ReadDir(albumRootPath) + if err != nil { + log.Fatalf("Error setting up slideshow : %s", err) + } + + for _, file := range files { + filePath := albumRootPath + "/" + file.Name() + fileStat, err := os.Stat(filePath) + if err != nil { + log.Fatalf("Error setting up slideshow : %s", err) + } + mode := fileStat.Mode() + if mode.IsRegular() { + err = os.Symlink(filePath, PATH_TEMP_FOR_SLIDESHOW + "/" + file.Name()) + if err != nil { + log.Fatalf("Error setting up slideshow : %s", err) + } + } + } + continue + } + err = os.Symlink(source, destination) + if err != nil { + log.Fatalf("Error setting up slideshow : %s", err) + } + } + // fim placeholder so we can operate on it when a exit slideshow is received var fim *exec.Cmd = nil - // Run slideshow - fim = exec.Command(CMD_FIM) + // Prep slideshow command and arguments + // NOTE: The random flag is seeded with time() ; this is bad as we will be restarting the slideshow at about the same time per the configurd schedule + // We use the non-seeded form to ensure that it's a little more random (or at least hope it's a little more random) + CMD_FIM := "/usr/bin/fim" + ARGS_FIM := []string{"--no-commandline", "--no-history", "--etc-fimrc", "/usr/local/etc/fimrc", + "--device", "/dev/fb0", "--vt", "1", + "--execute-commands-early", "\"clear\"", "--final-commands", "\"clear\"", + "--autozoom", "--random-no-seed", "--recursive", "--cd-and-readdir", + PATH_TEMP_FOR_SLIDESHOW} + + // fim command that'll be executed + fim = exec.Command(CMD_FIM, ARGS_FIM...) // Put fim into a process group so ALL processes that may be executed are exited when main process exits fim.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} @@ -34,7 +119,7 @@ func Slideshow(config *koanf.Koanf) { } // Advance slideshow every interval as defined in const() - ticker := time.NewTicker(config.Duration(pfconfig.CONFIG_KEY_SLIDESHOW_INTERVAL)) + ticker := time.NewTicker(pfconfig.Duration(config.CONFIG_KEY_SLIDESHOW_INTERVAL)) stop_ticker := make(chan struct{}) go func() { for { @@ -101,7 +186,7 @@ func Slideshow(config *koanf.Koanf) { if err != nil { log.Fatalf("Error controlling fim : %s", err) } - ticker.Reset(config.Duration(pfconfig.CONFIG_KEY_SLIDESHOW_INTERVAL)) + ticker.Reset(pfconfig.Duration(config.CONFIG_KEY_SLIDESHOW_INTERVAL)) } } }