Skip to content

Instantly share code, notes, and snippets.

@danhigham
Last active June 9, 2017 20:27
Show Gist options
  • Save danhigham/9f66800b8a655a2fcd25184a48b86a43 to your computer and use it in GitHub Desktop.
Save danhigham/9f66800b8a655a2fcd25184a48b86a43 to your computer and use it in GitHub Desktop.
Go app to display images on a Pi based photo frame
package main
import (
"encoding/json"
"os"
"os/exec"
"io"
"io/ioutil"
"log"
"net/http"
"time"
"github.com/tgulacsi/picago"
)
type Configuration struct {
Key string
Secret string
Album string
Delay time.Duration
}
type ImageSize struct {
Width int
Height int
}
func findAlbum(albums []picago.Album, test func(picago.Album) bool) picago.Album {
for _, a := range albums {
if test(a) {
return a
}
}
return picago.Album{}
}
func getPhotoSample(albumID string, userID string, client *http.Client, sampleSize int, offset int, c chan string) bool {
photos, err := picago.GetPhotos(client, userID, albumID)
if err != nil {
log.Fatalf("error listing albums: %v", err)
}
for i := offset; i < offset + sampleSize; i++ {
if i >= len(photos) {
return true
}
tmpfile, _ := ioutil.TempFile("", "photoframe")
log.Printf("Downloading %s", photos[i].URL)
image, _ := picago.DownloadPhoto(client, photos[i].URL)
io.Copy(tmpfile, image)
c <- tmpfile.Name()
}
return false
}
func getImageSize(filename string) ImageSize {
imageSize := ImageSize{}
cmd := exec.Command("identify", "-format", "{\"Width\": %w, \"Height\": %h}", filename)
stdout, err := cmd.StdoutPipe()
if err != nil {
log.Fatal(err)
}
if err != nil {
log.Fatal(err)
}
if err := cmd.Start(); err != nil {
log.Fatal(err)
}
if err := json.NewDecoder(stdout).Decode(&imageSize); err != nil {
log.Println("FAIL")
log.Fatal(err)
}
if err := cmd.Wait(); err != nil {
log.Fatal(err)
}
return imageSize
}
func showImages(c chan string, delay time.Duration) {
previousPid := 0
for {
image := <-c
imageSize := getImageSize(image)
log.Printf("Displaying %s", image)
var cmd *exec.Cmd
if imageSize.Width > imageSize.Height {
cmd = exec.Command("feh", "-g", "800x480", "-Z", "-F", "--zoom", "fill", image)
} else {
cmd = exec.Command("feh", "-g", "800x480", "-B", "black", image)
}
env := os.Environ()
env = append(env, "DISPLAY=:0")
cmd.Env = env
err := cmd.Start()
if err != nil {
log.Fatal(err)
}
go func(pid int) {
time.Sleep(2 * time.Second)
if pid > 0 {
oldProc, err := os.FindProcess(pid)
if err == nil {
oldProc.Kill()
}
}
}(previousPid)
previousPid = cmd.Process.Pid
time.Sleep(delay * time.Second)
os.Remove(image)
}
}
func main() {
file, _ := os.Open("config.json")
decoder := json.NewDecoder(file)
config := Configuration{}
err := decoder.Decode(&config)
if err != nil {
log.Println("error:", err)
}
client, err := picago.NewClient(config.Key, config.Secret, "", "token-cache.json")
if err != nil {
log.Fatalf("error with authorization: %v", err)
}
user, err := picago.GetUser(client, "")
userid := user.ID
albums, err := picago.GetAlbums(client, userid)
if err != nil {
log.Fatalf("error listing albums: %v", err)
}
c := make(chan string, 10)
go showImages(c, config.Delay)
photoFrameAlbum := findAlbum(albums, func(album picago.Album) bool { return album.Title == config.Album })
offset := 0
for {
ret := getPhotoSample(photoFrameAlbum.ID, userid, client, 10, offset, c)
if ret {
offset = 0
} else {
offset = offset + 10
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment