gyorgyf@37: #!/usr/bin/env python gyorgyf@37: # encoding: utf-8 gyorgyf@37: """ gyorgyf@37: visclient.py gyorgyf@37: gyorgyf@37: Created by George Fazekas on 2012-06-17. gyorgyf@37: Copyright (c) 2012 . All rights reserved. gyorgyf@37: """ gyorgyf@37: gyorgyf@37: import sys,os,math,time,copy gyorgyf@37: import pygame as pg gyorgyf@37: from pygame.locals import * gyorgyf@37: from pygame import gfxdraw as gd gyorgyf@37: import httplib as ht gyorgyf@37: gyorgyf@37: import gradients gyorgyf@37: from gradients import genericFxyGradient gyorgyf@37: gyorgyf@37: from threading import Thread gyorgyf@37: from random import random gyorgyf@37: gyorgyf@37: import colorsys as cs gyorgyf@37: gyorgyf@37: scol = (0,255,0,255) gyorgyf@37: ecol = (0,0,0,255) gyorgyf@37: gyorgyf@37: xavg=0 gyorgyf@37: yavg=0 gyorgyf@37: countavg=0 gyorgyf@37: moods = [] gyorgyf@37: gyorgyf@37: gyorgyf@37: # X,Y=1140,900 gyorgyf@37: # X,Y = 600,400 gyorgyf@37: X,Y = 800,600 gyorgyf@37: # X,Y = 1024,768 gyorgyf@37: gyorgyf@37: # Fullscreen resolution: gyorgyf@37: # XF,YF = 1280,900 gyorgyf@37: # XF,YF = 1440,900 gyorgyf@37: XF,YF = 1344,900 gyorgyf@37: # display calibrated gyorgyf@37: gyorgyf@37: # detect display resolution gyorgyf@37: import subprocess gyorgyf@37: screenres = subprocess.Popen('xrandr | grep "\*" | cut -d" " -f4',shell=True, stdout=subprocess.PIPE).communicate()[0] gyorgyf@37: screenres = map(lambda x: int(x.strip()), screenres.split('x')) gyorgyf@37: XF,YF = screenres gyorgyf@37: print "Screen resolution: ",XF,YF gyorgyf@37: gyorgyf@37: gyorgyf@37: # NBLOBS = 18 gyorgyf@37: # BLOBSIZE = 25 gyorgyf@37: # G=110 gyorgyf@37: # FADE = 15 gyorgyf@37: # DIST = 0.15 # blob equivalence tolerance gyorgyf@37: # FRAMERATE = 60 gyorgyf@37: gyorgyf@37: # new parameters gyorgyf@37: NBLOBS = 18 gyorgyf@37: BLOBSIZE = 25 gyorgyf@37: G=110 gyorgyf@37: FADE = 25 gyorgyf@37: DIST = 0.10 # blob equivalence tolerance gyorgyf@37: FRAMERATE = 120 gyorgyf@37: gyorgyf@37: gyorgyf@37: # Connection: gyorgyf@37: # IP = "127.0.0.1:8030" gyorgyf@37: # IP = "192.168.2.158:8030" gyorgyf@37: IP = "138.37.95.215" # this is the IP of kakapo<=>golden gyorgyf@37: HTTP_TIMEOUT = 3 gyorgyf@37: SERVER_UPDATE_INTERVAL = 0.8 gyorgyf@37: gyorgyf@37: gyorgyf@37: class Indicator(object): gyorgyf@37: gyorgyf@37: gyorgyf@37: def __init__(self,bg,pos,invisible=False): gyorgyf@37: gyorgyf@37: self.off_color = pg.Color(110,0,0) gyorgyf@37: self.on_color = pg.Color(0,120,0) gyorgyf@37: if invisible : gyorgyf@37: self.off_color = pg.Color(0,0,0) gyorgyf@37: self.on_color = pg.Color(0,0,120) gyorgyf@37: self.visible = True gyorgyf@37: self.ison = True gyorgyf@37: self.x,self.y = pos gyorgyf@37: self.xs = int(self.x * X) gyorgyf@37: self.ys = int(Y - (self.y * Y)) gyorgyf@37: self.c = self.off_color gyorgyf@37: self.size = 6 gyorgyf@37: self.bg = bg gyorgyf@37: gyorgyf@37: def reinit(self,bg): gyorgyf@37: self.bg = bg gyorgyf@37: self.xs = int(self.x * X) gyorgyf@37: self.ys = int(Y - (self.y * Y)) gyorgyf@37: gyorgyf@37: def draw(self): gyorgyf@37: if self.visible : gyorgyf@37: # pg.draw.circle(self.bg, self.c, (self.xs,self.ys),self.size,0) gyorgyf@37: # gd.aacircle(self.bg, self.xs, self.ys, self.size+1, self.c) gyorgyf@37: gd.filled_circle(self.bg, self.xs, self.ys, self.size, self.c) gyorgyf@37: gd.aacircle(self.bg, self.xs, self.ys, self.size, self.c) gyorgyf@37: gyorgyf@37: gyorgyf@37: def toggle(self): gyorgyf@37: if self.ison == True : gyorgyf@37: self.off() gyorgyf@37: else : gyorgyf@37: self.on() gyorgyf@37: return self gyorgyf@37: gyorgyf@37: def on(self): gyorgyf@37: self.c = self.on_color gyorgyf@37: self.ison = True gyorgyf@37: return self gyorgyf@37: gyorgyf@37: def off(self): gyorgyf@37: self.c = self.off_color gyorgyf@37: self.ison = False gyorgyf@37: return self gyorgyf@37: gyorgyf@37: def now(self,screen): gyorgyf@37: # for i in self.indicators.itervalues() : gyorgyf@37: # i.draw() gyorgyf@37: self.draw() gyorgyf@37: screen.blit(self.bg, (0, 0)) gyorgyf@37: pg.display.flip() gyorgyf@37: return self gyorgyf@37: gyorgyf@37: class MovingBlob(object): gyorgyf@37: gyorgyf@37: black_color = pg.Color(0,0,0) gyorgyf@37: gyorgyf@37: def __init__(self,bg,x,y,color=(255,255,255),mood=None,fade=FADE): gyorgyf@37: self.x = x gyorgyf@37: self.y = y gyorgyf@37: self.xs = x * X gyorgyf@37: self.ys = Y - (y * Y) gyorgyf@37: self.bg = bg gyorgyf@37: self.size = BLOBSIZE gyorgyf@37: self.time = time.time() gyorgyf@37: self.alpha = 255 gyorgyf@37: self.c = color gyorgyf@37: self.count = 1 gyorgyf@37: self.visible = True gyorgyf@37: self.FADE = fade gyorgyf@37: self.mood = mood gyorgyf@37: if mood and mood.color : gyorgyf@37: self.c = mood.color gyorgyf@37: self.title = mood.word gyorgyf@37: self.speed_factor = 80.0 gyorgyf@37: self.target_x = 0.0 gyorgyf@37: self.target_y = 0.0 gyorgyf@37: gyorgyf@37: def set_target(self,x,y): gyorgyf@37: self.target_x = x gyorgyf@37: self.target_y = y gyorgyf@37: gyorgyf@37: def draw(self): gyorgyf@37: if not self.visible : return gyorgyf@37: gyorgyf@37: global xavg,yavg,moods gyorgyf@37: # xspeed = (xavg - self.x) / self.speed_factor gyorgyf@37: # yspeed = (yavg - self.y) / self.speed_factor gyorgyf@37: # self.x = self.x + xspeed gyorgyf@37: # self.y = self.y + yspeed gyorgyf@37: self.x = self.x + (self.target_x - self.x) / self.speed_factor gyorgyf@37: self.y = self.y + (self.target_y - self.y) / self.speed_factor gyorgyf@37: gyorgyf@37: #self.size = countavg//TODO gyorgyf@37: self.xs = self.x * X gyorgyf@37: self.ys = Y - (self.y * Y) gyorgyf@37: #d=int(self.size) gyorgyf@37: gyorgyf@37: d = cd = sys.float_info.max gyorgyf@37: gyorgyf@37: for mood in moods : gyorgyf@37: d = mood.get_distance(self.x,self.y) gyorgyf@37: if d < cd : gyorgyf@37: cd = d gyorgyf@37: self.mood = mood gyorgyf@37: self.c = mood.color gyorgyf@37: self.title = mood.word gyorgyf@37: gyorgyf@37: # self.bg.blit(gradients.radial(self.size, (self.c[0],self.c[1],self.c[2],self.alpha), (0,0,0,self.alpha)), (self.xs-BLOBSIZE,self.ys-BLOBSIZE)) gyorgyf@37: d=int(self.size) gyorgyf@37: # print d gyorgyf@37: self.bg.blit(gradients.radial(self.size, (self.c[0],self.c[1],self.c[2],self.alpha), (0,0,0,self.alpha)), (self.xs-d,self.ys-d)) gyorgyf@37: gd.aacircle(self.bg, int(self.xs), int(self.ys), int(self.size), self.black_color) gyorgyf@37: gd.aacircle(self.bg, int(self.xs), int(self.ys), int(self.size-1), self.black_color) gyorgyf@37: gyorgyf@37: gyorgyf@37: font = pg.font.Font(None, 36) gyorgyf@37: text = font.render(self.title, 1, self.c) gyorgyf@37: textpos = text.get_rect() gyorgyf@37: #print textpos.width gyorgyf@37: if self.xs > X- textpos.width: gyorgyf@37: if self.ys > Y- textpos.height: gyorgyf@37: self.bg.blit(text, (self.xs - textpos.width,self.ys - textpos.height)) gyorgyf@37: else: gyorgyf@37: self.bg.blit(text, (self.xs - textpos.width,self.ys)) gyorgyf@37: gyorgyf@37: else : gyorgyf@37: if self.ys > Y- textpos.height: gyorgyf@37: self.bg.blit(text, (self.xs,self.ys - textpos.height)) gyorgyf@37: else: gyorgyf@37: self.bg.blit(text, (self.xs,self.ys)) gyorgyf@37: #self.bg.blit(gradients.radial(self.size, (self.c[0],self.c[1],self.c[2],self.alpha), (0,0,0,self.alpha)), (self.xs-d,self.ys-d)) gyorgyf@37: #self.alpha = 255 - int(self.age()*self.FADE) gyorgyf@37: #if self.alpha < 5 : gyorgyf@37: # self.alpha = 1 gyorgyf@37: # self.visible = False gyorgyf@37: gyorgyf@37: def age(self): gyorgyf@37: return time.time() - self.time gyorgyf@37: gyorgyf@37: def resize(self,count): gyorgyf@37: if self.count == count : gyorgyf@37: return None gyorgyf@37: self.time = time.time() gyorgyf@37: self.count = count gyorgyf@37: # self.size = int(BLOBSIZE * int(self.count/1.5)) gyorgyf@37: self.to = int(BLOBSIZE * int(self.count/1.5)) gyorgyf@37: if self.to < BLOBSIZE : gyorgyf@37: self.to = BLOBSIZE gyorgyf@37: if self.to and self.size != self.to: gyorgyf@37: self.start_animate() gyorgyf@37: # print "resize to",count,self.to gyorgyf@37: gyorgyf@37: def get_distance(self,x,y): gyorgyf@37: return math.sqrt( math.pow((self.x-x),2) + math.pow((self.y-y),2) ) gyorgyf@37: gyorgyf@37: def fade(self,fade): gyorgyf@37: if not fade : self.alpha = 255 gyorgyf@37: self.FADE = fade gyorgyf@37: gyorgyf@37: def reset_time(self): gyorgyf@37: self.time = time.time() gyorgyf@37: gyorgyf@37: def reinit(self,bg): gyorgyf@37: self.bg = bg gyorgyf@37: self.xs = int(self.x * X) gyorgyf@37: self.ys = int(Y - (self.y * Y)) gyorgyf@37: gyorgyf@37: def start_animate(self): gyorgyf@37: self.thread = Thread(target = self.animate) gyorgyf@37: self.thread.daemon = True gyorgyf@37: self.thread.start() gyorgyf@37: gyorgyf@37: def animate(self): gyorgyf@37: '''Animate the way bubbles are grown.''' gyorgyf@37: tolerance = 5 gyorgyf@37: # while self.size > self.to-tolerance and self.size < self.to+tolerance : gyorgyf@37: while self.size != self.to : gyorgyf@37: self.size = int(self.size + int(self.to-self.size) * 0.1) gyorgyf@37: time_inc = 20.0 / (pow(1.2, abs(self.to-self.size)) * 200.0) gyorgyf@37: time.sleep(0.02+time_inc) gyorgyf@37: # print "sizing to ", self.to gyorgyf@37: gyorgyf@37: gyorgyf@37: class Blob(object): gyorgyf@37: gyorgyf@37: def __init__(self,bg,x,y,color=(255,255,255),mood=None,fade=FADE): gyorgyf@37: self.x = x gyorgyf@37: self.y = y gyorgyf@37: self.xs = x * X gyorgyf@37: self.ys = Y - (y * Y) gyorgyf@37: self.bg = bg gyorgyf@37: self.size = BLOBSIZE #pixels gyorgyf@37: self.time = time.time() #s gyorgyf@37: self.const_time = time.time() #s gyorgyf@37: self.alpha = 255 #8-bit alpha channel value gyorgyf@37: self.c = color #RGB colour 3-tuple gyorgyf@37: self.count = 1 gyorgyf@37: self.visible = True gyorgyf@37: self.FADE = fade gyorgyf@37: if mood and mood.color : gyorgyf@37: self.c = mood.color gyorgyf@37: self.title = mood.word gyorgyf@37: self.inactivity_delay = 75.0 #s gyorgyf@37: self.proximity_delay = 35.0 #s gyorgyf@37: self.proximity_tolerance = 0.13 gyorgyf@37: self.target_in_proximity = None gyorgyf@37: gyorgyf@37: def __cmp__(self,other): gyorgyf@37: if other is None : gyorgyf@37: return -1 gyorgyf@37: d = math.sqrt( math.pow((self.x-other.x),2) + math.pow((self.y-other.y),2) ) gyorgyf@37: if d < DIST : gyorgyf@37: return 0 gyorgyf@37: else : gyorgyf@37: return -1 gyorgyf@37: gyorgyf@37: def object_in_proximity(self,other): gyorgyf@37: if other is None : gyorgyf@37: return False gyorgyf@37: d = math.sqrt( math.pow((self.x-other.x),2) + math.pow((self.y-other.y),2) ) gyorgyf@37: if d < self.proximity_tolerance : gyorgyf@37: return True gyorgyf@37: else : gyorgyf@37: return False gyorgyf@37: gyorgyf@37: def check_target_proximity(self,target): gyorgyf@37: '''Check if the moving bubble is in proximity of this object. As soon as it is there, mark the time. gyorgyf@37: We do not want to reset this time just wait until this bubble dies due to inactivity in its region.''' gyorgyf@37: prox = self.object_in_proximity(target) gyorgyf@37: if self.target_in_proximity is None and prox is True : gyorgyf@37: self.target_in_proximity = time.time() gyorgyf@37: # if prox is False : gyorgyf@37: # self.target_in_proximity = None gyorgyf@37: gyorgyf@37: def draw(self): gyorgyf@37: if not self.visible : return gyorgyf@37: gyorgyf@37: d=int(self.size) gyorgyf@37: self.bg.blit(gradients.radial(self.size, (self.c[0],self.c[1],self.c[2],self.alpha), (0,0,0,self.alpha)), (self.xs-d,self.ys-d)) gyorgyf@37: self.alpha = 255 - int(self.age()*self.FADE) gyorgyf@37: if self.alpha < 5 : gyorgyf@37: self.alpha = 1 gyorgyf@37: self.visible = False gyorgyf@37: gyorgyf@37: def age(self): gyorgyf@37: return time.time() - self.time gyorgyf@37: gyorgyf@37: def real_age(self): gyorgyf@37: return time.time() - self.const_time gyorgyf@37: gyorgyf@37: def age_weight(self): gyorgyf@37: age_s = time.time() - self.const_time gyorgyf@37: if age_s < self.inactivity_delay : gyorgyf@37: return 1.0 gyorgyf@37: return 1.0 / ((age_s-self.inactivity_delay+1)*10.0) gyorgyf@37: gyorgyf@37: def proximity_weight(self): gyorgyf@37: if self.target_in_proximity == None : gyorgyf@37: return 1.0 gyorgyf@37: age_s = time.time() - self.target_in_proximity gyorgyf@37: if age_s < self.proximity_delay : gyorgyf@37: return 1.0 gyorgyf@37: return 1.0 / ((age_s-self.proximity_delay+1)*10.0) gyorgyf@37: gyorgyf@37: def increment(self,count): gyorgyf@37: self.time = time.time() gyorgyf@37: self.count = count gyorgyf@37: # self.size = int(BLOBSIZE * int(self.count/1.5)) gyorgyf@37: self.to = int(BLOBSIZE * int(self.count/1.5)) gyorgyf@37: if self.to < 250 : gyorgyf@37: self.start_animate() gyorgyf@37: gyorgyf@37: def get_distance(self,x,y): gyorgyf@37: return math.sqrt( math.pow((self.x-x),2) + math.pow((self.y-y),2) ) gyorgyf@37: gyorgyf@37: def fade(self,fade): gyorgyf@37: if not fade : self.alpha = 255 gyorgyf@37: self.FADE = fade gyorgyf@37: gyorgyf@37: def reset_time(self): gyorgyf@37: self.time = time.time() gyorgyf@37: gyorgyf@37: def start_animate(self): gyorgyf@37: self.thread = Thread(target = self.animate) gyorgyf@37: self.thread.daemon = True gyorgyf@37: self.thread.start() gyorgyf@37: gyorgyf@37: def animate(self): gyorgyf@37: '''Animate the way bubbles are grown.''' gyorgyf@37: while self.size < self.to : gyorgyf@37: self.size += 1 gyorgyf@37: time_inc = 20.0 / (pow(1.2, self.to-self.size) * 200.0) gyorgyf@37: time.sleep(0.02+time_inc) gyorgyf@37: gyorgyf@37: def force(self,other): gyorgyf@37: '''Calculate the force between this object and another''' gyorgyf@37: if other is None : gyorgyf@37: return 0.0,0.0,False gyorgyf@37: captured = False gyorgyf@37: ds = math.pow((self.x-other.x),2) + math.pow((self.y-other.y),2) gyorgyf@37: if ds < 0.005 : gyorgyf@37: return 0.0,0.0,False gyorgyf@37: d = math.sqrt(ds) gyorgyf@37: if d < 0.07 : gyorgyf@37: captured = True gyorgyf@37: # return 0.0,0.0,False gyorgyf@37: m1,m2 = self.size,other.size gyorgyf@37: G = 6.674 * 0.000001 gyorgyf@37: f = - G * (m1*m2) / ds gyorgyf@37: x = f * (other.x-self.x) / d gyorgyf@37: y = f * (other.y-self.y) / d gyorgyf@37: return x,y,captured gyorgyf@37: gyorgyf@37: gyorgyf@37: class BlobTrail(object): gyorgyf@37: gyorgyf@37: def __init__(self,bg,x,y,color=(255,255,255),mood=None,fade=FADE): gyorgyf@37: self.x = x gyorgyf@37: self.y = y gyorgyf@37: self.xs = x * X gyorgyf@37: self.ys = Y - (y * Y) gyorgyf@37: self.bg = bg gyorgyf@37: self.size = BLOBSIZE gyorgyf@37: self.time = time.time() gyorgyf@37: self.alpha = 255 gyorgyf@37: self.c = color gyorgyf@37: self.count = 1 gyorgyf@37: self.visible = True gyorgyf@37: self.FADE = fade gyorgyf@37: if mood and mood.color : gyorgyf@37: self.c = mood.color gyorgyf@37: self.title = mood.word gyorgyf@37: gyorgyf@37: def __cmp__(self,other): gyorgyf@37: d = math.sqrt( math.pow((self.x-other.x),2) + math.pow((self.y-other.y),2) ) gyorgyf@37: if d < DIST : gyorgyf@37: return 0 gyorgyf@37: else : gyorgyf@37: return -1 gyorgyf@37: gyorgyf@37: def draw(self): gyorgyf@37: if not self.visible : return gyorgyf@37: gyorgyf@37: d=int(self.size) gyorgyf@37: self.bg.blit(gradients.radial(self.size, (self.c[0],self.c[1],self.c[2],self.alpha), (0,0,0,0)), (self.xs-d,self.ys-d)) gyorgyf@37: self.alpha = 255 - int(self.age()*self.FADE) gyorgyf@37: if self.alpha < 5 : gyorgyf@37: self.alpha = 1 gyorgyf@37: self.visible = False gyorgyf@37: gyorgyf@37: def age(self): gyorgyf@37: return time.time() - self.time gyorgyf@37: gyorgyf@37: def increment(self,count): gyorgyf@37: self.time = time.time() gyorgyf@37: self.count = count gyorgyf@37: # self.size = int(BLOBSIZE * int(self.count/1.5)) gyorgyf@37: self.to = int(BLOBSIZE * int(self.count/1.5)) gyorgyf@37: self.start_animate() gyorgyf@37: gyorgyf@37: def get_distance(self,x,y): gyorgyf@37: return math.sqrt( math.pow((self.x-x),2) + math.pow((self.y-y),2) ) gyorgyf@37: gyorgyf@37: def fade(self,fade): gyorgyf@37: if not fade : self.alpha = 255 gyorgyf@37: self.FADE = fade gyorgyf@37: gyorgyf@37: def reset_time(self): gyorgyf@37: self.time = time.time() gyorgyf@37: gyorgyf@37: def start_animate(self): gyorgyf@37: self.thread = Thread(target = self.animate) gyorgyf@37: self.thread.daemon = True gyorgyf@37: self.thread.start() gyorgyf@37: gyorgyf@37: def animate(self): gyorgyf@37: '''Animate the way bubbles are grown.''' gyorgyf@37: while self.size < self.to : gyorgyf@37: self.size += 1 gyorgyf@37: time_inc = 20.0 / (pow(1.2, self.to-self.size) * 200.0) gyorgyf@37: time.sleep(0.02+time_inc) gyorgyf@37: gyorgyf@37: gyorgyf@37: class Mood(): gyorgyf@37: gyorgyf@37: def __init__(self,word,x,y): gyorgyf@37: self.word = word gyorgyf@37: self.x = (float(x)/ 2.0) + 0.5 gyorgyf@37: self.y = (float(y)/ 2.0) + 0.5 gyorgyf@37: self.color = [] gyorgyf@37: gyorgyf@37: def get_distance(self,x,y): gyorgyf@37: return math.sqrt( math.pow((self.x-x),2) + math.pow((self.y-y),2) ) gyorgyf@37: gyorgyf@37: def __repr__(self): gyorgyf@37: return "Mood(%s,%3.2f,%3.2f)" %(self.word,self.x,self.y) gyorgyf@37: gyorgyf@37: gyorgyf@37: gyorgyf@37: class VisualClient(object): gyorgyf@37: '''Main visualisation client.''' gyorgyf@37: global moods,blobTrail gyorgyf@37: gyorgyf@37: def __init__(self): gyorgyf@37: # self.conn = ht.HTTPConnection("192.168.2.184:8030") gyorgyf@37: # self.conn = ht.HTTPConnection("138.37.95.215") gyorgyf@37: self.s_age = 10 gyorgyf@37: self.s_dist = DIST gyorgyf@37: self.s_ninp = 18 gyorgyf@37: gyorgyf@37: pg.init() gyorgyf@37: pg.font.init() gyorgyf@37: gyorgyf@37: # fontObj = pg.font.Font("freesansbold.ttf",18) gyorgyf@37: white = ( 255, 255, 255) gyorgyf@37: black = ( 0,0,0) gyorgyf@37: gyorgyf@37: self.fpsClock = pg.time.Clock() gyorgyf@37: self.screen = pg.display.set_mode((X, Y)) gyorgyf@37: pg.display.set_caption('Mood Conductor') gyorgyf@37: self.bg = pg.Surface(self.screen.get_size()) gyorgyf@37: self.bg = self.bg.convert() gyorgyf@37: self.bg.fill((0,0,0)) gyorgyf@37: pg.display.set_gamma(100.0) gyorgyf@37: gyorgyf@37: gyorgyf@37: self.scol = (0,255,0,255) gyorgyf@37: self.ecol = (0,0,0,255) gyorgyf@37: coordstxt = "test" gyorgyf@37: gyorgyf@37: self.blobs = [] gyorgyf@37: #self.moods = [] gyorgyf@37: self.bt=[] gyorgyf@37: gyorgyf@37: self.movingBlob = None gyorgyf@37: gyorgyf@37: self.read_mood_data() gyorgyf@37: gyorgyf@37: self.FADE = FADE gyorgyf@37: gyorgyf@37: self.indicators = { gyorgyf@37: "conn":Indicator(self.bg,(0.98,0.02)), # connection active gyorgyf@37: "update":Indicator(self.bg,(0.96,0.02)), # update thread executing gyorgyf@37: "data":Indicator(self.bg,(0.94,0.02)), # data status changed gyorgyf@37: "receive":Indicator(self.bg,(0.92,0.02)), # data received gyorgyf@37: "grow":Indicator(self.bg,(0.90,0.02)), # blob growth active gyorgyf@37: "ignore":Indicator(self.bg,(0.88,0.02),True), # little AI: ignore some clusters in certain condition gyorgyf@37: "suspend":Indicator(self.bg,(0.86,0.02),True), # prevent adding new blobs (key: d) gyorgyf@37: "config":Indicator(self.bg,(0.84,0.02),True), # sending config data gyorgyf@37: "fade":Indicator(self.bg,(0.82,0.02),True)} # fade on/off (key: s) gyorgyf@37: gyorgyf@37: self.thread = None gyorgyf@37: self.running = False gyorgyf@37: self.fullscreen = False gyorgyf@37: self.init_reconnect = False gyorgyf@37: self.suspend = False gyorgyf@37: gyorgyf@37: pass gyorgyf@37: gyorgyf@37: gyorgyf@37: def read_mood_data(self): gyorgyf@37: '''Read the mood position and color information form csv file.''' gyorgyf@37: # file = 'moods.csv' gyorgyf@37: file = '../tags/mc_moodtags_lfm_curated2.csv' gyorgyf@37: with open(file) as mf: gyorgyf@37: data = mf.readlines()[1:] gyorgyf@37: for line in data : gyorgyf@37: l = line.split(',') gyorgyf@37: l = map(lambda x:x.replace("'","").strip(),l) gyorgyf@37: mood = Mood(l[0],l[1],l[2]) gyorgyf@37: moods.append(mood) gyorgyf@37: print moods gyorgyf@37: for mood in moods: gyorgyf@37: print"['%s',%2.2f,%2.2f,0,0]," %(mood.word,mood.x,mood.y) gyorgyf@37: gyorgyf@37: with open('colors.txt') as ff: gyorgyf@37: data = ff.readlines()[1:] gyorgyf@37: data = map(lambda x: x.split(','),data) gyorgyf@37: for mood in moods : gyorgyf@37: d = cd = sys.float_info.max gyorgyf@37: for colors in data : gyorgyf@37: d = mood.get_distance(float(colors[0]),float(colors[1])) gyorgyf@37: if d < cd : gyorgyf@37: cd = d gyorgyf@37: # mood.color = tuple(map(lambda x: int(pow(math.atan((float(x)/7.0)),12.5)),(colors[2],colors[3],colors[4]))) gyorgyf@37: mood.color = self.set_color(tuple(map(lambda x: int(x),(colors[2],colors[3],colors[4])))) gyorgyf@37: return True gyorgyf@37: gyorgyf@37: def set_color(self,color): gyorgyf@37: '''Move to HLS colour space and manipulate saturation there.''' gyorgyf@37: # TODO: ideally, we need a non-linear compressor of the lightness and saturation values gyorgyf@37: r,g,b = map(lambda x: (1.0*x/255.0), color) gyorgyf@37: h,l,s = cs.rgb_to_hls(r,g,b) gyorgyf@37: s = 1.0 #1.0 - (1.0 / pow(50.0,s)) gyorgyf@37: l = 1.0 - (1.0 / pow(20.0,l)) #0.6 gyorgyf@37: r,g,b = map(lambda x: int(x*255), cs.hls_to_rgb(h,l,s)) gyorgyf@37: return r,g,b gyorgyf@37: gyorgyf@37: def start_update_thread(self): gyorgyf@37: '''Start the thread that reads data from the server.''' gyorgyf@37: time.sleep(SERVER_UPDATE_INTERVAL) gyorgyf@37: self.thread = Thread(target = self.update_thread) gyorgyf@37: self.thread.daemon = True gyorgyf@37: self.running = True gyorgyf@37: self.thread.start() gyorgyf@37: print "OK. Update thread started." gyorgyf@37: gyorgyf@37: def stop_update_thread(self): gyorgyf@37: '''Stop the thread and allow some time fot the connections to close.''' gyorgyf@37: self.running = False gyorgyf@37: try : gyorgyf@37: self.thread.join(2) gyorgyf@37: self.indicators["conn"].off() gyorgyf@37: self.indicators["update"].off() gyorgyf@37: except : gyorgyf@37: print "No update thread to join." gyorgyf@37: gyorgyf@37: def update_thread(self): gyorgyf@37: '''The server update thread''' gyorgyf@37: print "Thread reporting..." gyorgyf@37: while self.running : gyorgyf@37: # self.update() gyorgyf@37: try : gyorgyf@37: self.update() gyorgyf@37: # self.indicators["update"].visible = True gyorgyf@37: except Exception, e: gyorgyf@37: if str(e).strip() : print "Exception: ", str(e), type(e), len(str(e).strip()) gyorgyf@37: self.indicators["conn"].off() gyorgyf@37: # self.indicators["update"].visible = False gyorgyf@37: try : gyorgyf@37: time.sleep(SERVER_UPDATE_INTERVAL) gyorgyf@37: except : gyorgyf@37: if str(e).strip() : print "Exception: ", str(e), type(e), len(str(e).strip()) gyorgyf@37: self.indicators["conn"].off() gyorgyf@37: gyorgyf@37: gyorgyf@37: def update(self): gyorgyf@37: '''Update the blob list from the server. This should be in a thread.''' gyorgyf@37: # global xavg, yavg, countavg gyorgyf@37: # indicate connection health by toggling an indictor gyorgyf@37: self.indicators["update"].toggle() gyorgyf@37: gyorgyf@37: # delete invisibles gyorgyf@37: for blob in self.blobs : gyorgyf@37: if not blob.visible : gyorgyf@37: self.blobs.remove(blob) gyorgyf@37: gyorgyf@37: # get new coordinates from the server gyorgyf@37: self.conn.putrequest("GET","/moodconductor/result", skip_host=True) gyorgyf@37: self.conn.putheader("Host", "www.isophonics.net") gyorgyf@37: self.conn.endheaders() gyorgyf@37: res = self.conn.getresponse() gyorgyf@37: data = res.read() gyorgyf@37: data = eval(data) gyorgyf@37: if not data : gyorgyf@37: self.conn.close() gyorgyf@37: self.indicators["data"].toggle() gyorgyf@37: return False gyorgyf@37: gyorgyf@37: tempx = 0 gyorgyf@37: tempy = 0 gyorgyf@37: tempcount = 0 gyorgyf@37: gyorgyf@37: for d in data : gyorgyf@37: # coordstxt = "x:%s y:%s c:%s" %d gyorgyf@37: x,y,count = d gyorgyf@37: gyorgyf@37: tempx = tempx + x*count gyorgyf@37: tempy = tempy + y*count gyorgyf@37: tempcount = tempcount + count gyorgyf@37: gyorgyf@37: self.add_blob(x,y,count) gyorgyf@37: self.indicators["receive"].toggle() gyorgyf@37: gyorgyf@37: xavg = tempx/tempcount gyorgyf@37: yavg = tempy/tempcount gyorgyf@37: countavg = tempcount/len(data) gyorgyf@37: # print xavg, yavg, countavg gyorgyf@37: # if not self.blobs : gyorgyf@37: # self.add_blob(xavg,yavg,countavg) gyorgyf@37: # self.indicators["receive"].toggle() gyorgyf@37: gyorgyf@37: self.conn.close() gyorgyf@37: self.blobs = self.blobs[:NBLOBS] gyorgyf@37: return True gyorgyf@37: gyorgyf@37: gyorgyf@37: def add_blob(self,x,y,count=1): gyorgyf@37: '''Insert a blob to the list of blobs''' gyorgyf@37: # find mood correxponding to x,y gyorgyf@37: if self.suspend : gyorgyf@37: return None gyorgyf@37: cmood = None gyorgyf@37: d = cd = sys.float_info.max gyorgyf@37: for mood in moods : gyorgyf@37: d = mood.get_distance(x,y) gyorgyf@37: if d < cd : gyorgyf@37: cd = d gyorgyf@37: cmood = mood gyorgyf@37: # create new blob or increase click count on existing one gyorgyf@37: new = Blob(self.bg,x,y,mood=cmood,fade=self.FADE) gyorgyf@37: if self.movingBlob == None : gyorgyf@37: self.movingBlob = MovingBlob(self.bg,x,y,mood=cmood,fade=self.FADE) gyorgyf@37: if not new in self.blobs : gyorgyf@37: self.blobs.insert(0,new) gyorgyf@37: elif count > self.blobs[self.blobs.index(new)].count: gyorgyf@37: self.blobs[self.blobs.index(new)].increment(count) gyorgyf@37: self.indicators["grow"].toggle() gyorgyf@37: pass gyorgyf@37: gyorgyf@37: gyorgyf@37: def draw(self): gyorgyf@37: '''Draw all objects''' gyorgyf@37: global xavg, yavg, countavg gyorgyf@37: gyorgyf@37: self.bg.fill((0,0,0,1)) gyorgyf@37: # self.bg.blit(gradients.radial(19, self.scol, self.ecol), (rect_x,rect_y)) gyorgyf@37: forces = [] gyorgyf@37: l = copy.copy(self.blobs) gyorgyf@37: l.reverse() gyorgyf@37: xt,yt = 0.0,0.0 gyorgyf@37: bs = 1 gyorgyf@37: c = 1 gyorgyf@37: # captured_by = None gyorgyf@37: gyorgyf@37: # calculate exponential weighted average of the visible blobs gyorgyf@37: ignore = False gyorgyf@37: for blob in l : gyorgyf@37: blob.draw() gyorgyf@37: c = c + blob.count gyorgyf@37: # aw = blob.age_weight() gyorgyf@37: aw = blob.proximity_weight() gyorgyf@37: if aw < 1.0 : ignore = True gyorgyf@37: w = math.pow(blob.size+(blob.alpha/2.0),7) * aw gyorgyf@37: xt = xt + blob.x * w gyorgyf@37: yt = yt + blob.y * w gyorgyf@37: bs = bs + w gyorgyf@37: if self.movingBlob != None : gyorgyf@37: blob.check_target_proximity(self.movingBlob) gyorgyf@37: xavg = xt / bs gyorgyf@37: yavg = yt / bs gyorgyf@37: # countavg = bs/(len(l)+1) gyorgyf@37: countavg = int(c/(len(l)+1)) gyorgyf@37: if ignore : gyorgyf@37: self.indicators["ignore"].on() gyorgyf@37: else : gyorgyf@37: self.indicators["ignore"].off() gyorgyf@37: gyorgyf@37: # compute gravity force gyorgyf@37: # if self.movingBlob != None : gyorgyf@37: # x,y,c = blob.force(self.movingBlob) gyorgyf@37: # forces.append((x,y)) gyorgyf@37: # if c : captured_by = blob gyorgyf@37: # tx,ty = reduce(lambda a,b:(a[0]+b[0],a[1]+b[1]), forces, (0.5,0.5)) gyorgyf@37: gyorgyf@37: # print tx,ty gyorgyf@37: # if tx>1.0 : tx = 1.0 gyorgyf@37: # if tx<0.0 : tx = 0.0 gyorgyf@37: # if ty>1.0 : ty = 1.0 gyorgyf@37: # if ty<0.0 : ty = 0.0 gyorgyf@37: gyorgyf@37: # xavg,yavg = tx,ty gyorgyf@37: gyorgyf@37: # if tx <= 1.0 and tx >= 0.0 and ty <= 1.0 and ty >= 0.0 : gyorgyf@37: # xavg,yavg = tx,ty gyorgyf@37: # countavg = 15 gyorgyf@37: # print tx,ty gyorgyf@37: # else : gyorgyf@37: # print "out of bounds:",tx,ty gyorgyf@37: # if captured_by != None : gyorgyf@37: # xavg,yavg = captured_by.x,captured_by.y gyorgyf@37: l = copy.copy(self.bt) gyorgyf@37: l.reverse() gyorgyf@37: for trail in l: gyorgyf@37: trail.draw() gyorgyf@37: if self.movingBlob != None : gyorgyf@37: # self.movingBlob.resize(countavg) gyorgyf@37: self.movingBlob.set_target(xavg,yavg) gyorgyf@37: self.movingBlob.draw() gyorgyf@37: new = BlobTrail(self.bg,self.movingBlob.x,self.movingBlob.y,mood=self.movingBlob.mood,fade=18) gyorgyf@37: self.bt.insert(0,new) gyorgyf@37: # axis gyorgyf@37: pg.draw.line(self.bg, (G,G,G), (int(X/2.0),0),(int(X/2.0),Y), 1) gyorgyf@37: pg.draw.line(self.bg, (G,G,G), (0,int(Y/2.0)),(X,int(Y/2.0)), 1) gyorgyf@37: gyorgyf@37: # indicators gyorgyf@37: for i in self.indicators.itervalues() : gyorgyf@37: i.draw() gyorgyf@37: gyorgyf@37: def read_keys(self): gyorgyf@37: '''Read keys''' gyorgyf@37: for event in pg.event.get() : gyorgyf@37: # Quit (event) gyorgyf@37: if event.type == QUIT: gyorgyf@37: self.quit() gyorgyf@37: elif event.type == KEYDOWN : gyorgyf@37: # Post Quit: Esc, q gyorgyf@37: if event.key == K_ESCAPE or event.key == K_q : gyorgyf@37: pg.event.post(pg.event.Event(QUIT)) gyorgyf@37: # Reset: Space gyorgyf@37: elif event.key == K_SPACE : gyorgyf@37: if not self.blobs : gyorgyf@37: self.bt = [] gyorgyf@37: self.blobs = [] gyorgyf@37: # Random : r gyorgyf@37: elif event.key == K_r : gyorgyf@37: self.add_blob(random(),random(),count=5) gyorgyf@37: # Connection : c gyorgyf@37: elif event.key == K_c : gyorgyf@37: self.init_reconnect = True gyorgyf@37: self.indicators["conn"].off() gyorgyf@37: # Fullscreen: f gyorgyf@37: elif event.key == K_f : gyorgyf@37: # pg.display.toggle_fullscreen() gyorgyf@37: self.toggle_screen_mode() gyorgyf@37: # Toggle suspend: d gyorgyf@37: elif event.key == K_d : gyorgyf@37: if self.suspend : gyorgyf@37: print "suspend off" gyorgyf@37: self.indicators["suspend"].off() gyorgyf@37: self.suspend = False gyorgyf@37: else: gyorgyf@37: print "suspend on" gyorgyf@37: self.indicators["suspend"].on() gyorgyf@37: self.suspend = True gyorgyf@37: # Toggle fade: s gyorgyf@37: elif event.key == K_s : gyorgyf@37: if self.FADE > 0: gyorgyf@37: print "fade off" gyorgyf@37: self.indicators["fade"].off() gyorgyf@37: self.FADE = 0 gyorgyf@37: for blob in self.blobs : gyorgyf@37: blob.fade(0) gyorgyf@37: else: gyorgyf@37: print "fade on" gyorgyf@37: self.indicators["fade"].on() gyorgyf@37: self.FADE = FADE gyorgyf@37: for blob in self.blobs : gyorgyf@37: blob.fade(FADE) gyorgyf@37: blob.reset_time() gyorgyf@37: # inc age gyorgyf@37: elif event.key == K_1 : gyorgyf@37: self.s_age += 1 gyorgyf@37: self.update_server_config(self.s_age,self.s_dist,self.s_ninp) gyorgyf@37: # dec age gyorgyf@37: elif event.key == K_2 : gyorgyf@37: self.s_age -= 1 gyorgyf@37: self.update_server_config(self.s_age,self.s_dist,self.s_ninp) gyorgyf@37: # inc dist gyorgyf@37: elif event.key == K_3 : gyorgyf@37: self.s_dist += 0.025 gyorgyf@37: self.update_server_config(self.s_age,self.s_dist,self.s_ninp) gyorgyf@37: # dec dist gyorgyf@37: elif event.key == K_4 : gyorgyf@37: self.s_dist -= 0.025 gyorgyf@37: if self.s_dist < 0.025 : self.s_dist = 0.025 gyorgyf@37: self.update_server_config(self.s_age,self.s_dist,self.s_ninp) gyorgyf@37: # inc ninp gyorgyf@37: elif event.key == K_5 : gyorgyf@37: self.s_ninp += 1 gyorgyf@37: self.update_server_config(self.s_age,self.s_dist,self.s_ninp) gyorgyf@37: # dec ninp gyorgyf@37: elif event.key == K_6 : gyorgyf@37: self.s_ninp -= 1 gyorgyf@37: if self.s_ninp < 2 : self.s_ninp = 2 gyorgyf@37: self.update_server_config(self.s_age,self.s_dist,self.s_ninp) gyorgyf@37: # choose different app and restart server gyorgyf@37: elif event.key == K_9 : gyorgyf@37: self.choose_app() gyorgyf@37: gyorgyf@37: pass gyorgyf@37: pass gyorgyf@37: gyorgyf@37: def toggle_screen_mode(self): gyorgyf@37: '''Go back and forth between full screen mode.''' gyorgyf@37: if self.fullscreen == False: gyorgyf@37: globals()['_X'] = globals()['X'] gyorgyf@37: globals()['_Y'] = globals()['Y'] gyorgyf@37: globals()['X'] = XF gyorgyf@37: globals()['Y'] = YF gyorgyf@37: self.screen = pg.display.set_mode((X, Y)) gyorgyf@37: # self.screen = pg.display.set_mode((0,0),pg.FULLSCREEN) gyorgyf@37: self.fullscreen = True gyorgyf@37: self.bg = pg.Surface(self.screen.get_size()) gyorgyf@37: self.bg = self.bg.convert() gyorgyf@37: self.bg.fill((0,0,0)) gyorgyf@37: for i in self.indicators.itervalues() : gyorgyf@37: i.reinit(self.bg) gyorgyf@37: i.draw() gyorgyf@37: if self.movingBlob != None : gyorgyf@37: self.movingBlob.reinit(self.bg) gyorgyf@37: self.movingBlob.draw() gyorgyf@37: else : gyorgyf@37: globals()['X'] = globals()['_X'] gyorgyf@37: globals()['Y'] = globals()['_Y'] gyorgyf@37: self.screen = pg.display.set_mode((X, Y)) gyorgyf@37: self.fullscreen = False gyorgyf@37: self.bg = pg.Surface(self.screen.get_size()) gyorgyf@37: self.bg = self.bg.convert() gyorgyf@37: self.bg.fill((0,0,0)) gyorgyf@37: for i in self.indicators.itervalues() : gyorgyf@37: i.reinit(self.bg) gyorgyf@37: i.draw() gyorgyf@37: if self.movingBlob != None : gyorgyf@37: self.movingBlob.reinit(self.bg) gyorgyf@37: self.movingBlob.draw() gyorgyf@37: pg.display.toggle_fullscreen() gyorgyf@37: gyorgyf@37: gyorgyf@37: gyorgyf@37: def run(self): gyorgyf@37: gyorgyf@37: # setup connection gyorgyf@37: self.connect() gyorgyf@37: gyorgyf@37: # main loop gyorgyf@37: while True : gyorgyf@37: # pg.draw.circle(screen, pg.Color(255,0,0), (300,50),20,0) gyorgyf@37: # screen.blit(gradients.radial(99, scol, ecol), (401, 1)) gyorgyf@37: gyorgyf@37: self.read_keys() gyorgyf@37: gyorgyf@37: # Draw gyorgyf@37: self.draw() gyorgyf@37: gyorgyf@37: # update display gyorgyf@37: self.screen.blit(self.bg, (0, 0)) gyorgyf@37: pg.display.flip() gyorgyf@37: self.fpsClock.tick(FRAMERATE) gyorgyf@37: gyorgyf@37: if self.init_reconnect: gyorgyf@37: self.reconnect() gyorgyf@37: gyorgyf@37: return True gyorgyf@37: gyorgyf@37: def choose_app(self): gyorgyf@37: '''Experimental function for chaging served apps remotely. Disabled for now...''' gyorgyf@37: return False gyorgyf@37: try : gyorgyf@37: print "Changing app and restarting... the connection will be lost." gyorgyf@37: self.conn.putrequest("GET","/moodconductor/changeapp", skip_host=True) gyorgyf@37: self.conn.putheader("Host", "www.isophonics.net") gyorgyf@37: self.conn.endheaders() gyorgyf@37: res = self.conn.getresponse() gyorgyf@37: res.read() gyorgyf@37: except : gyorgyf@37: pass gyorgyf@37: gyorgyf@37: def configure_server(self): gyorgyf@37: '''Send the server some configuration data.''' gyorgyf@37: # age = 10.0 gyorgyf@37: # dist = DIST gyorgyf@37: # ninp = 18 gyorgyf@37: self.update_server_config(self.s_age,self.s_dist,self.s_ninp) gyorgyf@37: gyorgyf@37: gyorgyf@37: def update_server_config(self,age,dist,ninp,retry = 3): gyorgyf@37: '''Send the server some configuration data.''' gyorgyf@37: self.indicators["config"].on().now(self.screen) gyorgyf@37: try : gyorgyf@37: print "Sending configuration data." gyorgyf@37: self.conn.putrequest("GET","/moodconductor/config?age=%(age)s&dist=%(dist)s&ninp=%(ninp)s" %locals(), skip_host=True) gyorgyf@37: self.conn.putheader("Host", "www.isophonics.net") gyorgyf@37: self.conn.endheaders() gyorgyf@37: res = self.conn.getresponse() gyorgyf@37: res.read() gyorgyf@37: if not res.status == 200 : gyorgyf@37: print "Server response:", res.status, res.reason gyorgyf@37: self.indicators["conn"].off() gyorgyf@37: time.sleep(0.5) gyorgyf@37: self.conn.putrequest("GET","/moodconductor/getconf", skip_host=True) gyorgyf@37: self.conn.putheader("Host", "www.isophonics.net") gyorgyf@37: self.conn.endheaders() gyorgyf@37: res = self.conn.getresponse() gyorgyf@37: if not res.status == 200 : gyorgyf@37: print "Server response:", res.status, res.reason gyorgyf@37: self.indicators["conn"].off() gyorgyf@37: # self.indicators["config"].on() gyorgyf@37: print "Server configuration:", res.read() gyorgyf@37: self.indicators["config"].off() gyorgyf@37: self.indicators["conn"].on() gyorgyf@37: except: gyorgyf@37: print "Failed to send configuration data." gyorgyf@37: time.sleep(2) gyorgyf@37: retry -= 1 gyorgyf@37: self.update_server_config(age,dist,ninp,retry) gyorgyf@37: gyorgyf@37: gyorgyf@37: def connect(self,retry = 5): gyorgyf@37: '''Connect to the server and test connection.''' gyorgyf@37: if not retry : gyorgyf@37: print "Server unreachable" gyorgyf@37: pg.quit() gyorgyf@37: raise SystemExit gyorgyf@37: if retry < 5 : gyorgyf@37: time.sleep(3) gyorgyf@37: try : gyorgyf@37: print "connecting to server..." gyorgyf@37: self.conn = ht.HTTPConnection(IP,timeout=HTTP_TIMEOUT) gyorgyf@37: self.indicators["conn"].on() gyorgyf@37: except : gyorgyf@37: self.indicators["conn"].off() gyorgyf@37: self.connect(retry = retry-1) gyorgyf@37: print "connection failed." gyorgyf@37: gyorgyf@37: try: gyorgyf@37: print "Testing connection." gyorgyf@37: # self.conn.putrequest("GET","/moodconductor/index.html", skip_host=True) gyorgyf@37: self.conn.putrequest("GET","/moodconductor/test", skip_host=True) gyorgyf@37: self.conn.putheader("Host", "www.isophonics.net") gyorgyf@37: self.conn.endheaders() gyorgyf@37: res = self.conn.getresponse() gyorgyf@37: print res.read() gyorgyf@37: if res.status == 200 : gyorgyf@37: self.indicators["conn"].on() gyorgyf@37: else : gyorgyf@37: print "Server response:", res.status, res.reason gyorgyf@37: self.indicators["conn"].off() gyorgyf@37: if not hasattr(self,"noretry") and raw_input("Go offline? ") in ['y',''] : gyorgyf@37: return False gyorgyf@37: else : gyorgyf@37: print "Failed. retrying." gyorgyf@37: self.noretry = None gyorgyf@37: self.connect(retry = retry-1) gyorgyf@37: except Exception as e: gyorgyf@37: print "Exception while testing connection.", e gyorgyf@37: self.indicators["conn"].off() gyorgyf@37: # comment out in offline mode gyorgyf@37: if not hasattr(self,"noretry") and raw_input("Go offline? ") in ['y',''] : gyorgyf@37: return False gyorgyf@37: else : gyorgyf@37: self.noretry = None gyorgyf@37: self.connect(retry = retry-1) gyorgyf@37: self.configure_server() gyorgyf@37: print "OK. Starting update thread..." gyorgyf@37: self.start_update_thread() gyorgyf@37: return True gyorgyf@37: gyorgyf@37: gyorgyf@37: gyorgyf@37: def reconnect(self): gyorgyf@37: '''Called when c is pressed.''' gyorgyf@37: self.indicators["config"].on().now(self.screen) gyorgyf@37: self.init_reconnect = False gyorgyf@37: gyorgyf@37: self.stop_update_thread() gyorgyf@37: time.sleep(1) gyorgyf@37: try : gyorgyf@37: self.conn.close() gyorgyf@37: except : gyorgyf@37: self.indicators["conn"].off() gyorgyf@37: try : gyorgyf@37: self.conn = ht.HTTPConnection(IP,timeout=HTTP_TIMEOUT) gyorgyf@37: self.conn.connect() gyorgyf@37: self.indicators["conn"].on() gyorgyf@37: print "Reconnected." gyorgyf@37: except : gyorgyf@37: self.indicators["conn"].off() gyorgyf@37: print "Error while reconnecting." gyorgyf@37: self.start_update_thread() gyorgyf@37: self.indicators["config"].off().now(self.screen) gyorgyf@37: gyorgyf@37: gyorgyf@37: def quit(self): gyorgyf@37: print "Quitting.." gyorgyf@37: self.indicators["conn"].off() gyorgyf@37: self.stop_update_thread() gyorgyf@37: self.conn.close() gyorgyf@37: pg.quit() gyorgyf@37: sys.exit() gyorgyf@37: gyorgyf@37: gyorgyf@37: def main(): gyorgyf@37: gyorgyf@37: v = VisualClient() gyorgyf@37: v.run() gyorgyf@37: gyorgyf@37: if __name__ == '__main__': gyorgyf@37: pass gyorgyf@37: main() gyorgyf@37: