#!/usr/bin/env python # imports import threading from threading import Timer from threading import Thread import sys, pygame from pygame.locals import * import re import urllib import os import getopt import pygame.font import pygame.surface # globals start_id = str(47) # 15 # 47 width = 800 height = 600 delay = 5000 fullscreen = False cache_path = './cache/' base_url = 'http://www.explosm.net/comics/' next_id = start_id def help(): print """Cyanide and Happiness aka Explosm Viewing Script v0.1 http://apoc.sixserv.org/ Syntax: %s [OPTIONS] -s, --start=ID the start id(default=15) -w, --width=W Fullscreen Width -h, --height=H Fullscreen Height -d, --delay=SECONDS Slideshow Delay """ % sys.argv[0] # # Parsing command line arguments # try: opts, args = getopt.getopt(sys.argv[1:], "s:w:h:d:", ["start=", "width=", "height=", "delay="]) except getopt.GetoptError, err: print str(err) help() sys.exit(2) try: for o, a in opts: if o in ("-s", "--start"): start_id = a elif o in ("-w", "--width"): width = int(a) elif o in ("-h", "--height"): height = int(a) elif o in ("-d", "--delay"): height = int(a) else: assert False, "unhandled option" except ValueError: print "Error in parsing parameter types." sys.exit(2) # # initialize sdl/pygame, screen backbuffer as surScreen surface # pygame.init() def init_video(): global fullscreen, width, height size = (width, height) if fullscreen: modes = DOUBLEBUF | FULLSCREEN else: modes = DOUBLEBUF return pygame.display.set_mode(size, modes) surScreen = init_video() comic_surfaces = {} # # # class ComicImage(object): # class attribute saves id => ComicImage objects images = {} def __init__(self, image_id): self.image_id = image_id self.next_id = None self.prev_id = None self.image_surface = None def get_surface(self): global cache_path, comic_surfaces if not comic_surfaces.has_key(self.image_id): print 'get surface not exists!' comic_surfaces[self.image_id] = pygame.image.load('%s/%s' % (cache_path, self.image_filename)).convert() return comic_surfaces[self.image_id] def clear_surface(self): self.image_surface = None def clear_images(self): pass # load id page, parses next, prev and image url. def load(self): global base_url, cache_path if not self.image_id: print "Error: No ID!" print self.image_id sys.exit() try: fetch_url = "%s%s/" % (base_url, self.image_id) print "Fetching URL: %s" % fetch_url site = urllib.urlopen(fetch_url) print 123 contents = site.read() print 124 except: print "Error in retriving id(%s)" % self.image_id sys.exit(2) print "128" # parse Next id: match_next_id = re.findall('href="/comics/([^/]+)/">Next >', contents) if not match_next_id: print "Error: No next id!" self.next_id = None else: self.next_id = match_next_id[0] print "Found NextID: %s" % self.next_id # parse Prev. id: match_prev_id = re.findall('href="/comics/([^/]+)/">< Previous', contents) if not match_prev_id: print "Error: No prev id!" self.prev_id = None else: self.prev_id = match_prev_id[0] print "Found PrevID: %s" % self.prev_id # parse image url: match_image_url = re.findall('\[IMG\]([^\]]+)\[/IMG\]', contents) if not match_image_url: print "Error: No img tag found!" self.image_url = None return None else: self.image_url = match_image_url[0] print "Found Image URL: %s" % self.image_url image_filename_match = re.findall("/([^/]+)$", self.image_url) self.image_filename = image_filename_match[0] os.system('wget -O "%s/%s" -c "%s"' % (cache_path, self.image_filename, self.image_url)) #comic_surfaces[self.image_id] = pygame.image.load('%s/%s' % (cache_path, self.image_filename)).convert() # creates next object and return: def get_next(self): if ComicImage.images.has_key(self.next_id): return ComicImage.images[self.next_id] else: image = ComicImage(self.next_id) image.load() ComicImage.images[self.next_id] = image return image # creates prev object and return: def get_prev(self): if ComicImage.images.has_key(self.prev_id): return ComicImage.images[self.prev_id] else: image = ComicImage(self.prev_id) image.load() ComicImage.images[self.prev_id] = image return image #testing... """ comic = ComicImage(start_id) comic.load() comic = comic.get_next() comic = comic.get_prev() sys.exit(2) """ def save_comic_cache(): global comic, cache_path import pickle pickle.dump(ComicImage.images, open('%s/comic.dump' % cache_path, 'w')) def load_comic_cache(): global comic, cache_path import pickle ComicImage.images = pickle.load(open('%s/comic.dump' % cache_path, 'r')) #load_comic_cache() load = True if load: load_comic_cache() if not ComicImage.images.has_key(start_id): comic = ComicImage(start_id) comic.load() else: comic = ComicImage.images[start_id] else: comic = ComicImage(start_id) comic.load() # # Thread function # def image_update_next(): global surImage, comic print 'Next Image...' comic = comic.get_next() def image_update_prev(): global surImage, comic print 'Prev Image...' comic = comic.get_prev() # # initial setup timer event # NEXT_IMAGE = USEREVENT + 1 pygame.time.set_timer(NEXT_IMAGE, delay) slideshow_thread = Thread(target=image_update_next) slideshow_thread.start() slideshow = True # # main event/draw loop # #font = pygame.font.SysFont("Monaco", 18) font = pygame.font.SysFont("Verdana", 18) while True: for event in pygame.event.get(): if event.type == QUIT: sys.exit() elif event.type == KEYDOWN: if event.key == K_ESCAPE or event.key == K_q: save_comic_cache() sys.exit() elif event.key == K_f: # toggle and re-initialize if fullscreen: fullscreen = False else: fullscreen = True surScreen = init_video() elif event.key == K_SPACE: # toggle status of event timer if slideshow: # deactivate! print "Stop Timer!" slideshow = False pygame.time.set_timer(NEXT_IMAGE, 0) else: print "Start Timer!" slideshow = True pygame.time.set_timer(NEXT_IMAGE, delay) elif event.key == K_LEFT: if not slideshow_thread.is_alive(): slideshow_thread = Thread(target=image_update_prev) slideshow_thread.start() elif event.key == K_RIGHT: if not slideshow_thread.is_alive(): slideshow_thread = Thread(target=image_update_next) slideshow_thread.start() elif event.type == NEXT_IMAGE: print "event!" if not slideshow_thread.is_alive(): slideshow_thread = Thread(target=image_update_next) slideshow_thread.start() #next_image(next_id) surScreen.fill((0x00,0x0,0x0)) if comic.get_surface(): surface = comic.get_surface() surScreen.blit(surface, (50, 40)) #if dst_w > width - 100: # pygame.time.delay(2000) """ glob_off_y = height - comic_surface.get_height() - 150 glob_off_x = (width / 2.0) - (comic_surface.get_width() / 2) #print glob_off_y surScreen.blit(comic_surface, (glob_off_x, 40 + glob_off_y)) surface = comic_surface.copy() surface = pygame.transform.flip(surface, False, True) for off_y in range(1,150): bc = int( 255.0 / 150.0 * off_y ) surface.fill((bc, bc, bc), (0, off_y, surface.get_width(), 1), BLEND_SUB) #surface.fill((0,0,0), (0, 10 + glob_off_y, surface.get_width(), surface.get_height() - 10)) surScreen.blit(surface, (glob_off_x, 40 + surface.get_height() + glob_off_y)) """ if slideshow: slideshow_str = 'True' else: slideshow_str = 'False' ren = font.render("Slideshow: %s ID: %s Filename: '%s'" % (slideshow_str, comic.image_id, comic.image_filename) , 1, (255,255,255)) surScreen.blit(ren, (20, 10)) pygame.display.update() pygame.time.delay(100) py.font.exit()