Created
February 3, 2019 05:16
-
-
Save jasongrout/2baf84e243f8cb6d822fbdfd17715d6c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# TODO: | |
# [X] initialize only the modules we are using | |
# [X] Display a single specific picture from the 2011 folder | |
# [X] Regenerate pics for 1080p | |
# Minimum Viable Product (MVP) | |
# [X] Pick a random pic from the 2011 folder | |
# [X] Pick a random pic from the Export1080p folder | |
# [X] Display a random pic over and over again, with 10 minutes in between. Maybe move the picture slightly every so often? | |
# [X] Clear the screen between pictures | |
# [X] set_allowed(None) -> None | |
# [X] Shift-escape exits | |
# [X] Press a key changes the picture | |
# [X] Use a pygame clock? - NO, use the events instead. | |
# [X] Make program event-driven | |
# [X]forwards arrow | |
# [X] Center the picture | |
# [X] Make *just* the space key change the picture. | |
# [X] Make left mouse/right mouse click be the same as left/right arrow, and middle mouse click same as space bar. | |
# [X] Hold down a mouse button for a set time should also exit the program (7 seconds?) | |
# [X] Replace key checks with .key = pygame.K_LEFT, pygame.K_ESCAPE, etc. See https://www.pygame.org/docs/ref/key.html for constants | |
# [X] Move all constants up to the top of the program, make the units easy for Dad to change (like minutes for new picture, not milliseconds) | |
# [X] Fix shift-escape to check modifier keys using a bitmask (get binary repr with `bin`) | |
# [X] Print file name (without the '.jpg') in the upper left. | |
# [X] Print a small shadow to help reading the numbers when on a light background. | |
# [X] Use pygame.freetype module to render nicer text directly to the screen | |
# [X] Move text to the bottom left, say 5 pixels up from the bottom? | |
# [X] Make a shortcut you can click on to start the program | |
# [X] Toggle text for different formats with a key | |
# [X] Uninstall screensaver | |
# [X] Make the date text format a bit nicer, like 27 Aug 2006 (be careful, not all filenames are dates) | |
# [X] Turn off screensaver: http://www.raspberry-projects.com/pi/pi-operating-systems/raspbian/screensaver | |
# [X] Pick a random day, then a picture from that day - probably good enough to group based on the first 8 characters of the filename. | |
# [X] Make the pictures directory a variable | |
# [X] Make the program automatically run on bootup. http://www.raspberry-projects.com/pi/pi-operating-systems/raspbian/auto-running-programs-gui | |
# [ ] Make program version controlled and clean up the TODOs | |
# [ ] Copy the sd disk and check in the old pi to make sure it works | |
# [ ] Wrap, package up, and ship | |
# If we have time: | |
# [ ] Turn off screen at night (see note below about `xset dpms force off`. Also see https://wiki.libsdl.org/FAQUsingSDL#Why_does_SDL_disable_my_screensaver_by_default.3F about allowing the screen to blank while running the program - we'll need to set an environment variable in this program using os.environ). | |
# [ ] Save the pic history to a file to easily pick it back up again | |
# [ ] bias against showing pics we've already shown. Perhaps if we generate a pic already in the history list, try at least once to pick a new random picture, or after we show a picture, take it out of the list. | |
# [ ] Be able to rate a picture from 1-5, show the rating next, maybe make it more likely to be picked. Be able to say "don't show this pic again". | |
# Later | |
# [ ] Make it easy to turn on or off LED lights. Ask about good default. | |
# [ ] Print the date on the picture (get date with stat call?) | |
# [ ] Picture selection logic - higher preference to pictures in similar season, pics with higher ratings, etc. | |
# [ ] Print info about the pic on the pic display (date, filename, keywords, caption, etc.) | |
# [ ] up/down keys go through the pictures chronologically? | |
# [ ] Handle pics with different sizes/orientations. Rotate? Put upright and blur the background? Center smaller pics | |
# [ ] Hook up hardware buttons and switch: buttons to go prev/next, switch to hold a pic, buttons to rate a pic up or down. | |
# autorun: http://www.raspberry-projects.com/pi/pi-operating-systems/raspbian/auto-running-programs-gui | |
# control LEDs: https://www.jeffgeerling.com/blogs/jeff-geerling/controlling-pwr-act-leds-raspberry-pi - set the trigger for each led (if 'none' doesn't work to turn them off, try 'gpio') | |
# Setup: | |
# - Edit /boot/config.txt and add `hdmi_blanking=1`. Then you can use `xset dpms force off` to blank the screen and turn off the monitor until another key is pressed. See https://www.raspberrypi.org/documentation/configuration/config-txt/video.md and https://github.com/raspberrypi/linux/issues/487. | |
########### | |
# import stuff we need | |
from random import SystemRandom | |
import pygame | |
import time | |
import os | |
import pygame.freetype | |
# Set the variables so we can easily change the program | |
FULLSCREEN = True | |
TIMER = 60 # in minutes | |
FONTSIZE = 110 | |
FORMAT = 1 | |
PIC_DIRECTORY = 'Export1080p/' | |
def date (filename): | |
if FORMAT == 0: | |
return '' | |
elif FORMAT == 1: | |
if filename[0] == '2': | |
return convert(filename) | |
else: | |
return '' | |
elif FORMAT == 2: | |
return filename[:-4] | |
months = { | |
'01': 'Jan', | |
'02': 'Feb', | |
'03': 'Mar', | |
'04': 'Apr', | |
'05': 'May', | |
'06': 'June', | |
'07': 'July', | |
'08': 'Aug', | |
'09': 'Sep', | |
'10': 'Oct', | |
'11': 'Nov', | |
'12': 'Dec' | |
} | |
def convert(date): | |
year = date[:4] | |
month = date[4:6] | |
day = date[6:8] | |
month = months[month] | |
return day+' '+month+' '+year | |
def group(data): | |
"organizing the list of strings in a dict, returns the dict" | |
dic = {} | |
for name in data: | |
start = name[:8] | |
if start not in dic: | |
dic[start] = [name] | |
else: | |
dic[start].append(name) | |
return dic | |
# Start pygame up, setting allowed events | |
pygame.freetype.init() | |
pygame.display.init() | |
pygame.event.set_allowed(None) | |
pygame.event.set_allowed([pygame.USEREVENT,pygame.KEYDOWN,pygame.QUIT, pygame.MOUSEBUTTONDOWN, pygame.MOUSEBUTTONUP]) | |
if FULLSCREEN: | |
pygame.mouse.set_visible(False) | |
screen = pygame.display.set_mode((0,0), pygame.FULLSCREEN) # fullscreen | |
else: | |
screen = pygame.display.set_mode((300, 200)) # development | |
PICTURE_CHANGE = pygame.USEREVENT | |
font = pygame.freetype.SysFont(None, FONTSIZE) | |
random = SystemRandom() | |
def show(filename): | |
screen.fill([0,0,0]) | |
image = pygame.image.load(PIC_DIRECTORY + filename) | |
cimage = image.convert() | |
if FULLSCREEN: | |
x = screen.get_width() | |
n = cimage.get_width() | |
offset = round((x-n)/2) | |
screen.blit(cimage, (offset,0)) | |
else: | |
pygame.transform.smoothscale(cimage, (300, 200), screen) # development | |
# Put the filename up on the screen, not .jpg . | |
words = font.render( date(filename), fgcolor=(255,255,255), bgcolor=(0,0,0,100)) | |
s = screen.get_height() | |
w = words[0].get_height() | |
screen.blit(words[0],(10,s-w-5)) | |
pygame.display.flip() | |
pygame.time.set_timer(PICTURE_CHANGE,TIMER*60*1000) | |
# Set up the picture history | |
position = -1 | |
history = [] # list of filenames tha you have veiwed | |
# Get all of the filenames in the picture directory | |
pic_files = os.listdir(path=PIC_DIRECTORY) | |
groups = group(pic_files) | |
days = list(groups.keys()) | |
# Show the first picture after a second | |
pygame.time.set_timer(PICTURE_CHANGE, 1000) | |
# Handle events | |
while True: | |
f=pygame.event.wait() | |
# Show a new random picture | |
if (f.type == PICTURE_CHANGE | |
or (f.type == pygame.KEYDOWN and (f.key == pygame.K_SPACE)) | |
or (f.type == pygame.MOUSEBUTTONDOWN and f.button == 2)): | |
#pick a day, then pick a random pic from that day | |
day = random.choice(days) | |
x = random.choice(groups[day]) | |
history.append(x) | |
position = -1 | |
show(history[position]) | |
# Change the date format | |
if (f.type == pygame.KEYDOWN and f.key == pygame.K_RETURN): | |
FORMAT = FORMAT+1 | |
if FORMAT == 3: | |
FORMAT = 0 | |
show(history[position]) | |
# Show the previous picture | |
if (f.type == pygame.KEYDOWN and f.key == pygame.K_LEFT) or (f.type == pygame.MOUSEBUTTONDOWN and f.button == 1): | |
if len(history) > -position: | |
position = position-1 | |
show(history[position]) | |
# Show the next picture | |
if (f.type == pygame.KEYDOWN and f.key == pygame.K_RIGHT) or (f.type == pygame.MOUSEBUTTONDOWN and f.button == 3): | |
if position < -1: | |
position = position+1 | |
show(history[position]) | |
# Quit the program | |
if f.type == pygame.QUIT: | |
break | |
# Quit if shift-escape | |
if (f.type == pygame.KEYDOWN | |
and f.key == pygame.K_ESCAPE | |
and (f.mod & pygame.KMOD_SHIFT != 0)): | |
break | |
# Quit if you hold down a mouse button for 5 seconds | |
if (f.type == pygame.MOUSEBUTTONDOWN and f.button in [1,2,3]): | |
pygame.time.set_timer(pygame.QUIT,1000*5) | |
if (f.type == pygame.MOUSEBUTTONUP and f.button in [1,2,3]): | |
# Cancel the quit event since we let up on the mouse button | |
pygame.time.set_timer(pygame.QUIT,0) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment