annotate visualclient/visclient.py @ 54:c0b34039917a tip

Server: added an exposed function to log the start time of a performance (for log-to-audio sync)
author Mathieu Barthet <mathieu.barthet@eecs.qmul.ac.uk>
date Wed, 14 Oct 2015 19:20:08 +0100
parents ea2ec5f95ad8
children
rev   line source
gyorgyf@5 1 #!/usr/bin/env python
gyorgyf@5 2 # encoding: utf-8
gyorgyf@5 3 """
gyorgyf@5 4 visclient.py
gyorgyf@5 5
gyorgyf@5 6 Created by George Fazekas on 2012-06-17.
gyorgyf@5 7 Copyright (c) 2012 . All rights reserved.
gyorgyf@5 8 """
gyorgyf@5 9
gyorgyf@12 10 import sys,os,math,time,copy
gyorgyf@5 11 import pygame as pg
gyorgyf@5 12 from pygame.locals import *
gyorgyf@31 13 from pygame import gfxdraw as gd
gyorgyf@5 14 import httplib as ht
gyorgyf@5 15
gyorgyf@5 16 import gradients
gyorgyf@5 17 from gradients import genericFxyGradient
gyorgyf@5 18
gyorgyf@27 19 from threading import Thread
gyorgyf@27 20 from random import random
gyorgyf@27 21
gyorgyf@28 22 import colorsys as cs
gyorgyf@28 23
gyorgyf@12 24 scol = (0,255,0,255)
gyorgyf@12 25 ecol = (0,0,0,255)
gyorgyf@12 26
gyorgyf@12 27 # X,Y=1140,900
gyorgyf@27 28 # X,Y = 600,400
gyorgyf@27 29 X,Y = 800,600
gyorgyf@27 30
gyorgyf@28 31 # Fullscreen resolution:
gyorgyf@28 32 # XF,YF = 1280,900
gyorgyf@28 33 # XF,YF = 1440,900
gyorgyf@28 34 XF,YF = 1344,900
gyorgyf@28 35 # display calibrated
gyorgyf@28 36
gyorgyf@28 37 # detect display resolution
gyorgyf@28 38 import subprocess
gyorgyf@28 39 screenres = subprocess.Popen('xrandr | grep "\*" | cut -d" " -f4',shell=True, stdout=subprocess.PIPE).communicate()[0]
gyorgyf@28 40 screenres = map(lambda x: int(x.strip()), screenres.split('x'))
gyorgyf@28 41 XF,YF = screenres
gyorgyf@28 42 print "Screen resolution: ",XF,YF
gyorgyf@28 43
gyorgyf@27 44 NBLOBS = 18
gyorgyf@22 45 BLOBSIZE = 25
gyorgyf@14 46 G=110
gyorgyf@22 47 FADE = 15
gyorgyf@30 48 DIST = 0.15 # blob equivalence tolerance
gyorgyf@27 49 FRAMERATE = 60
gyorgyf@27 50
gyorgyf@27 51 # Connection:
gyorgyf@35 52 # IP = "127.0.0.1:8030"
gyorgyf@29 53 # IP = "192.168.2.158:8030"
gyorgyf@35 54 IP = "138.37.95.215"
gyorgyf@27 55 HTTP_TIMEOUT = 3
gyorgyf@27 56 SERVER_UPDATE_INTERVAL = 0.8
gyorgyf@27 57
gyorgyf@29 58
gyorgyf@27 59 class Indicator(object):
gyorgyf@27 60
gyorgyf@27 61 off_color = pg.Color(110,0,0)
gyorgyf@27 62 on_color = pg.Color(0,120,0)
gyorgyf@27 63
gyorgyf@27 64 def __init__(self,bg,pos):
gyorgyf@27 65 self.visible = True
gyorgyf@27 66 self.ison = True
gyorgyf@27 67 self.x,self.y = pos
gyorgyf@27 68 self.xs = int(self.x * X)
gyorgyf@27 69 self.ys = int(Y - (self.y * Y))
gyorgyf@27 70 self.c = self.off_color
gyorgyf@27 71 self.size = 6
gyorgyf@27 72 self.bg = bg
gyorgyf@27 73
gyorgyf@27 74 def reinit(self,bg):
gyorgyf@27 75 self.bg = bg
gyorgyf@27 76 self.xs = int(self.x * X)
gyorgyf@27 77 self.ys = int(Y - (self.y * Y))
gyorgyf@27 78
gyorgyf@27 79 def draw(self):
gyorgyf@27 80 if self.visible :
gyorgyf@31 81 # pg.draw.circle(self.bg, self.c, (self.xs,self.ys),self.size,0)
gyorgyf@31 82 # gd.aacircle(self.bg, self.xs, self.ys, self.size+1, self.c)
gyorgyf@31 83 gd.filled_circle(self.bg, self.xs, self.ys, self.size, self.c)
gyorgyf@31 84 gd.aacircle(self.bg, self.xs, self.ys, self.size, self.c)
gyorgyf@31 85
gyorgyf@27 86
gyorgyf@27 87 def toggle(self):
gyorgyf@27 88 if self.ison == True :
gyorgyf@27 89 self.off()
gyorgyf@27 90 else :
gyorgyf@27 91 self.on()
gyorgyf@27 92 return self
gyorgyf@27 93
gyorgyf@27 94 def on(self):
gyorgyf@27 95 self.c = self.on_color
gyorgyf@27 96 self.ison = True
gyorgyf@27 97 return self
gyorgyf@27 98
gyorgyf@27 99 def off(self):
gyorgyf@27 100 self.c = self.off_color
gyorgyf@27 101 self.ison = False
gyorgyf@27 102 return self
gyorgyf@27 103
gyorgyf@12 104
gyorgyf@12 105 class Blob(object):
gyorgyf@12 106
gyorgyf@22 107 def __init__(self,bg,x,y,color=(255,255,255),mood=None,fade=FADE):
gyorgyf@12 108 self.x = x
gyorgyf@12 109 self.y = y
gyorgyf@12 110 self.xs = x * X
gyorgyf@12 111 self.ys = Y - (y * Y)
gyorgyf@12 112 self.bg = bg
gyorgyf@14 113 self.size = BLOBSIZE
gyorgyf@12 114 self.time = time.time()
gyorgyf@12 115 self.alpha = 255
gyorgyf@12 116 self.c = color
gyorgyf@14 117 self.count = 1
gyorgyf@12 118 self.visible = True
gyorgyf@22 119 self.FADE = fade
gyorgyf@12 120 if mood and mood.color :
gyorgyf@12 121 self.c = mood.color
gyorgyf@12 122
gyorgyf@12 123 def __cmp__(self,other):
gyorgyf@12 124 d = math.sqrt( math.pow((self.x-other.x),2) + math.pow((self.y-other.y),2) )
gyorgyf@27 125 if d < DIST :
gyorgyf@12 126 return 0
gyorgyf@12 127 else :
gyorgyf@12 128 return -1
gyorgyf@12 129
gyorgyf@12 130 def draw(self):
gyorgyf@27 131 if not self.visible : return
gyorgyf@14 132 d=int(self.size)
gyorgyf@14 133 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@22 134 self.alpha = 255 - int(self.age()*self.FADE)
gyorgyf@12 135 if self.alpha < 5 :
gyorgyf@12 136 self.alpha = 1
gyorgyf@12 137 self.visible = False
gyorgyf@12 138
gyorgyf@12 139 def age(self):
gyorgyf@12 140 return time.time() - self.time
gyorgyf@12 141
gyorgyf@12 142 def increment(self,count):
gyorgyf@21 143 self.time = time.time()
gyorgyf@14 144 self.count = count
gyorgyf@28 145 # self.size = int(BLOBSIZE * int(self.count/1.5))
gyorgyf@28 146 self.to = int(BLOBSIZE * int(self.count/1.5))
gyorgyf@28 147 self.start_animate()
gyorgyf@12 148
gyorgyf@12 149 def get_distance(self,x,y):
gyorgyf@12 150 return math.sqrt( math.pow((self.x-x),2) + math.pow((self.y-y),2) )
gyorgyf@22 151
gyorgyf@22 152 def fade(self,fade):
gyorgyf@22 153 if not fade : self.alpha = 255
gyorgyf@22 154 self.FADE = fade
gyorgyf@22 155
gyorgyf@22 156 def reset_time(self):
gyorgyf@22 157 self.time = time.time()
gyorgyf@28 158
gyorgyf@28 159 def start_animate(self):
gyorgyf@28 160 self.thread = Thread(target = self.animate)
gyorgyf@28 161 self.thread.daemon = True
gyorgyf@28 162 self.thread.start()
gyorgyf@28 163
gyorgyf@28 164 def animate(self):
gyorgyf@28 165 '''Animate the way bubbles are grown.'''
gyorgyf@28 166 while self.size < self.to :
gyorgyf@28 167 self.size += 1
gyorgyf@28 168 time_inc = 20.0 / (pow(1.2, self.to-self.size) * 200.0)
gyorgyf@28 169 time.sleep(0.02+time_inc)
gyorgyf@12 170
gyorgyf@12 171
gyorgyf@12 172
gyorgyf@12 173
gyorgyf@12 174 class Mood():
gyorgyf@12 175 def __init__(self,word,x,y):
gyorgyf@12 176 self.word = word
gyorgyf@12 177 self.x = float(x)
gyorgyf@12 178 self.y = float(y)
gyorgyf@12 179 self.color = []
gyorgyf@12 180
gyorgyf@12 181 def get_distance(self,x,y):
gyorgyf@12 182 return math.sqrt( math.pow((self.x-x),2) + math.pow((self.y-y),2) )
gyorgyf@12 183
gyorgyf@12 184
gyorgyf@12 185
gyorgyf@12 186 class VisualClient(object):
gyorgyf@27 187 '''Main visualisation client.'''
gyorgyf@12 188
gyorgyf@12 189 def __init__(self):
gyorgyf@12 190 # self.conn = ht.HTTPConnection("192.168.2.184:8030")
gyorgyf@27 191 # self.conn = ht.HTTPConnection("138.37.95.215")
gyorgyf@29 192 self.s_age = 10
gyorgyf@29 193 self.s_dist = DIST
gyorgyf@29 194 self.s_ninp = 18
gyorgyf@12 195
gyorgyf@12 196 pg.init()
gyorgyf@12 197
gyorgyf@12 198 # fontObj = pg.font.Font("freesansbold.ttf",18)
gyorgyf@12 199 white = ( 255, 255, 255)
gyorgyf@12 200 black = ( 0,0,0)
gyorgyf@12 201
gyorgyf@12 202 self.fpsClock = pg.time.Clock()
gyorgyf@12 203 self.screen = pg.display.set_mode((X, Y))
gyorgyf@12 204 pg.display.set_caption('Mood Conductor')
gyorgyf@12 205 self.bg = pg.Surface(self.screen.get_size())
gyorgyf@12 206 self.bg = self.bg.convert()
gyorgyf@12 207 self.bg.fill((0,0,0))
gyorgyf@27 208 pg.display.set_gamma(100.0)
gyorgyf@12 209
gyorgyf@12 210
gyorgyf@12 211 self.scol = (0,255,0,255)
gyorgyf@12 212 self.ecol = (0,0,0,255)
gyorgyf@12 213 coordstxt = "test"
gyorgyf@12 214
gyorgyf@12 215 self.blobs = []
gyorgyf@12 216 self.moods = []
gyorgyf@12 217 self.read_mood_data()
gyorgyf@12 218
gyorgyf@22 219 self.FADE = FADE
gyorgyf@22 220
gyorgyf@27 221 self.indicators = {
gyorgyf@27 222 "conn":Indicator(self.bg,(0.98,0.02)),
gyorgyf@27 223 "update":Indicator(self.bg,(0.96,0.02)),
gyorgyf@27 224 "data":Indicator(self.bg,(0.94,0.02)),
gyorgyf@27 225 "receive":Indicator(self.bg,(0.92,0.02))}
gyorgyf@27 226
gyorgyf@27 227 self.thread = None
gyorgyf@27 228 self.running = False
gyorgyf@27 229 self.fullscreen = False
gyorgyf@27 230 self.init_reconnect = False
gyorgyf@30 231
gyorgyf@12 232 pass
gyorgyf@12 233
gyorgyf@27 234
gyorgyf@12 235 def read_mood_data(self):
gyorgyf@27 236 '''Read the mood position and color information form csv file.'''
gyorgyf@12 237 with open('moods.csv') as mf:
gyorgyf@12 238 data = mf.readlines()[1:]
gyorgyf@12 239 for line in data :
gyorgyf@12 240 l = line.split(',')
gyorgyf@14 241 mood = Mood(l[0],l[1],l[2])
gyorgyf@12 242 self.moods.append(mood)
gyorgyf@22 243 with open('colors.txt') as ff:
gyorgyf@22 244 data = ff.readlines()[1:]
gyorgyf@22 245 data = map(lambda x: x.split(','),data)
gyorgyf@12 246 for mood in self.moods :
gyorgyf@22 247 d = cd = sys.float_info.max
gyorgyf@12 248 for colors in data :
gyorgyf@22 249 d = mood.get_distance(float(colors[0]),float(colors[1]))
gyorgyf@22 250 if d < cd :
gyorgyf@22 251 cd = d
gyorgyf@28 252 # mood.color = tuple(map(lambda x: int(pow(math.atan((float(x)/7.0)),12.5)),(colors[2],colors[3],colors[4])))
gyorgyf@28 253 mood.color = self.set_color(tuple(map(lambda x: int(x),(colors[2],colors[3],colors[4]))))
gyorgyf@27 254 return True
gyorgyf@27 255
gyorgyf@28 256 def set_color(self,color):
gyorgyf@28 257 '''Move to HLS colour space and manipulate saturation there.'''
gyorgyf@28 258 # TODO: ideally, we need a non-linear compressor of the lightness and saturation values
gyorgyf@28 259 r,g,b = map(lambda x: (1.0*x/255.0), color)
gyorgyf@28 260 h,l,s = cs.rgb_to_hls(r,g,b)
gyorgyf@28 261 s = 1.0 #1.0 - (1.0 / pow(50.0,s))
gyorgyf@28 262 l = 1.0 - (1.0 / pow(20.0,l)) #0.6
gyorgyf@28 263 r,g,b = map(lambda x: int(x*255), cs.hls_to_rgb(h,l,s))
gyorgyf@28 264 return r,g,b
gyorgyf@22 265
gyorgyf@27 266 def start_update_thread(self):
gyorgyf@27 267 '''Start the thread that reads data from the server.'''
gyorgyf@27 268 self.thread = Thread(target = self.update_thread)
gyorgyf@27 269 self.thread.daemon = True
gyorgyf@35 270 self.running = True
gyorgyf@27 271 self.thread.start()
gyorgyf@32 272 print "OK. Update thread started."
gyorgyf@12 273
gyorgyf@27 274 def stop_update_thread(self):
gyorgyf@27 275 '''Stop the thread and allow some time fot the connections to close.'''
gyorgyf@27 276 self.running = False
gyorgyf@27 277 try :
gyorgyf@27 278 self.thread.join(2)
gyorgyf@27 279 except :
gyorgyf@27 280 print "No update thread to join."
gyorgyf@27 281
gyorgyf@27 282 def update_thread(self):
gyorgyf@27 283 '''The server update thread'''
gyorgyf@35 284 print "Thread reporting..."
gyorgyf@27 285 while self.running :
gyorgyf@32 286 # self.update()
gyorgyf@27 287 try :
gyorgyf@27 288 self.update()
gyorgyf@27 289 # self.indicators["update"].visible = True
gyorgyf@27 290 except Exception, e:
gyorgyf@27 291 if str(e).strip() : print "Exception: ", str(e), type(e), len(str(e).strip())
gyorgyf@27 292 self.indicators["conn"].off()
gyorgyf@27 293 # self.indicators["update"].visible = False
gyorgyf@27 294 time.sleep(SERVER_UPDATE_INTERVAL)
gyorgyf@27 295
gyorgyf@12 296
gyorgyf@12 297 def update(self):
gyorgyf@27 298 '''Update the blob list from the server. This should be in a thread.'''
gyorgyf@27 299
gyorgyf@27 300 # indicate connection health by toggling an indictor
gyorgyf@27 301 self.indicators["update"].toggle()
gyorgyf@12 302
gyorgyf@12 303 # delete invisibles
gyorgyf@12 304 for blob in self.blobs :
gyorgyf@12 305 if not blob.visible :
gyorgyf@12 306 self.blobs.remove(blob)
gyorgyf@12 307
gyorgyf@12 308 # get new coordinates from the server
gyorgyf@12 309 self.conn.putrequest("GET","/moodconductor/result", skip_host=True)
gyorgyf@12 310 self.conn.putheader("Host", "www.isophonics.net")
gyorgyf@12 311 self.conn.endheaders()
gyorgyf@12 312 res = self.conn.getresponse()
gyorgyf@12 313 data = res.read()
gyorgyf@27 314 data = eval(data)
gyorgyf@12 315 if not data :
gyorgyf@12 316 self.conn.close()
gyorgyf@27 317 self.indicators["data"].toggle()
gyorgyf@12 318 return False
gyorgyf@12 319 for d in data :
gyorgyf@14 320 # coordstxt = "x:%s y:%s c:%s" %d
gyorgyf@27 321 x,y,count = d
gyorgyf@27 322 self.add_blob(x,y,count)
gyorgyf@27 323 self.indicators["receive"].toggle()
gyorgyf@12 324 self.conn.close()
gyorgyf@21 325 self.blobs = self.blobs[:NBLOBS]
gyorgyf@12 326 return True
gyorgyf@27 327
gyorgyf@27 328
gyorgyf@27 329 def add_blob(self,x,y,count=1):
gyorgyf@27 330 '''Insert a blob to the list of blobs'''
gyorgyf@27 331 # find mood correxponding to x,y
gyorgyf@27 332 cmood = None
gyorgyf@27 333 d = cd = sys.float_info.max
gyorgyf@27 334 for mood in self.moods :
gyorgyf@27 335 d = mood.get_distance(x,y)
gyorgyf@27 336 if d < cd :
gyorgyf@27 337 cd = d
gyorgyf@27 338 cmood = mood
gyorgyf@27 339 # create new blob or increase click count on existing one
gyorgyf@27 340 new = Blob(self.bg,x,y,mood=cmood,fade=self.FADE)
gyorgyf@27 341 if not new in self.blobs :
gyorgyf@27 342 self.blobs.insert(0,new)
gyorgyf@27 343 elif count > self.blobs[self.blobs.index(new)].count:
gyorgyf@27 344 self.blobs[self.blobs.index(new)].increment(count)
gyorgyf@27 345 pass
gyorgyf@12 346
gyorgyf@12 347
gyorgyf@12 348 def draw(self):
gyorgyf@27 349 self.bg.fill((0,0,0))
gyorgyf@12 350 # self.bg.blit(gradients.radial(19, self.scol, self.ecol), (rect_x,rect_y))
gyorgyf@12 351 l = copy.copy(self.blobs)
gyorgyf@12 352 l.reverse()
gyorgyf@12 353 for blob in l :
gyorgyf@12 354 blob.draw()
gyorgyf@12 355
gyorgyf@14 356 # axis
gyorgyf@14 357 pg.draw.line(self.bg, (G,G,G), (int(X/2.0),0),(int(X/2.0),Y), 1)
gyorgyf@14 358 pg.draw.line(self.bg, (G,G,G), (0,int(Y/2.0)),(X,int(Y/2.0)), 1)
gyorgyf@14 359
gyorgyf@27 360 # indicators
gyorgyf@27 361 for i in self.indicators.itervalues() :
gyorgyf@27 362 i.draw()
gyorgyf@27 363
gyorgyf@27 364 def read_keys(self):
gyorgyf@27 365 '''Read keys'''
gyorgyf@27 366 for event in pg.event.get() :
gyorgyf@27 367 # Quit (event)
gyorgyf@27 368 if event.type == QUIT:
gyorgyf@27 369 self.quit()
gyorgyf@27 370 elif event.type == KEYDOWN :
gyorgyf@27 371 # Post Quit: Esc, q
gyorgyf@27 372 if event.key == K_ESCAPE or event.key == K_q :
gyorgyf@27 373 pg.event.post(pg.event.Event(QUIT))
gyorgyf@27 374 # Reset: Space
gyorgyf@27 375 elif event.key == K_SPACE :
gyorgyf@27 376 self.blobs = []
gyorgyf@27 377 # Random : r
gyorgyf@27 378 elif event.key == K_r :
gyorgyf@27 379 self.add_blob(random(),random(),count=5)
gyorgyf@27 380 # Connection : c
gyorgyf@27 381 elif event.key == K_c :
gyorgyf@27 382 self.init_reconnect = True
gyorgyf@27 383 self.indicators["conn"].off()
gyorgyf@27 384 # Fullscreen: f
gyorgyf@27 385 elif event.key == K_f :
gyorgyf@27 386 # pg.display.toggle_fullscreen()
gyorgyf@27 387 self.toggle_screen_mode()
gyorgyf@27 388 # Toggle fade: s
gyorgyf@27 389 elif event.key == K_s :
gyorgyf@27 390 if self.FADE :
gyorgyf@27 391 print "fade off"
gyorgyf@27 392 self.indicators["conn"].off()
gyorgyf@27 393 self.FADE = 0
gyorgyf@27 394 for blob in self.blobs :
gyorgyf@27 395 blob.fade(0)
gyorgyf@27 396 else:
gyorgyf@27 397 print "fade on"
gyorgyf@27 398 self.indicators["conn"].on()
gyorgyf@27 399 self.FADE = 15
gyorgyf@27 400 for blob in self.blobs :
gyorgyf@27 401 blob.fade(15)
gyorgyf@27 402 blob.reset_time()
gyorgyf@29 403 # inc age
gyorgyf@29 404 elif event.key == K_1 :
gyorgyf@29 405 self.s_age += 1
gyorgyf@29 406 self.update_server_config(self.s_age,self.s_dist,self.s_ninp)
gyorgyf@29 407 # dec age
gyorgyf@29 408 elif event.key == K_2 :
gyorgyf@29 409 self.s_age -= 1
gyorgyf@29 410 self.update_server_config(self.s_age,self.s_dist,self.s_ninp)
gyorgyf@29 411 # inc dist
gyorgyf@29 412 elif event.key == K_3 :
gyorgyf@29 413 self.s_dist += 0.025
gyorgyf@29 414 self.update_server_config(self.s_age,self.s_dist,self.s_ninp)
gyorgyf@29 415 # dec dist
gyorgyf@29 416 elif event.key == K_4 :
gyorgyf@29 417 self.s_dist -= 0.025
gyorgyf@29 418 if self.s_dist < 0.025 : self.s_dist = 0.025
gyorgyf@29 419 self.update_server_config(self.s_age,self.s_dist,self.s_ninp)
gyorgyf@29 420 # inc ninp
gyorgyf@29 421 elif event.key == K_5 :
gyorgyf@29 422 self.s_ninp += 1
gyorgyf@29 423 self.update_server_config(self.s_age,self.s_dist,self.s_ninp)
gyorgyf@29 424 # dec ninp
gyorgyf@29 425 elif event.key == K_6 :
gyorgyf@29 426 self.s_ninp -= 1
gyorgyf@29 427 if self.s_ninp < 2 : self.s_ninp = 2
gyorgyf@29 428 self.update_server_config(self.s_age,self.s_dist,self.s_ninp)
gyorgyf@29 429
gyorgyf@29 430 pass
gyorgyf@27 431 pass
gyorgyf@27 432
gyorgyf@27 433 def toggle_screen_mode(self):
gyorgyf@27 434 '''Go back and forth between full screen mode.'''
gyorgyf@27 435 if self.fullscreen == False:
gyorgyf@27 436 globals()['_X'] = globals()['X']
gyorgyf@27 437 globals()['_Y'] = globals()['Y']
gyorgyf@28 438 globals()['X'] = XF
gyorgyf@28 439 globals()['Y'] = YF
gyorgyf@28 440 self.screen = pg.display.set_mode((X, Y))
gyorgyf@28 441 # self.screen = pg.display.set_mode((0,0),pg.FULLSCREEN)
gyorgyf@27 442 self.fullscreen = True
gyorgyf@27 443 self.bg = pg.Surface(self.screen.get_size())
gyorgyf@27 444 self.bg = self.bg.convert()
gyorgyf@27 445 self.bg.fill((0,0,0))
gyorgyf@27 446 for i in self.indicators.itervalues() :
gyorgyf@27 447 i.reinit(self.bg)
gyorgyf@27 448 i.draw()
gyorgyf@27 449 else :
gyorgyf@27 450 globals()['X'] = globals()['_X']
gyorgyf@27 451 globals()['Y'] = globals()['_Y']
gyorgyf@27 452 self.screen = pg.display.set_mode((X, Y))
gyorgyf@27 453 self.fullscreen = False
gyorgyf@27 454 self.bg = pg.Surface(self.screen.get_size())
gyorgyf@27 455 self.bg = self.bg.convert()
gyorgyf@27 456 self.bg.fill((0,0,0))
gyorgyf@27 457 for i in self.indicators.itervalues() :
gyorgyf@27 458 i.reinit(self.bg)
gyorgyf@27 459 i.draw()
gyorgyf@27 460 pg.display.toggle_fullscreen()
gyorgyf@27 461
gyorgyf@14 462
gyorgyf@12 463
gyorgyf@12 464 def run(self):
gyorgyf@12 465
gyorgyf@27 466 # setup connection
gyorgyf@27 467 self.connect()
gyorgyf@27 468
gyorgyf@12 469 # main loop
gyorgyf@12 470 while True :
gyorgyf@12 471 # pg.draw.circle(screen, pg.Color(255,0,0), (300,50),20,0)
gyorgyf@12 472 # screen.blit(gradients.radial(99, scol, ecol), (401, 1))
gyorgyf@12 473
gyorgyf@27 474 self.read_keys()
gyorgyf@12 475
gyorgyf@12 476 # Draw
gyorgyf@12 477 self.draw()
gyorgyf@12 478
gyorgyf@12 479 # update display
gyorgyf@12 480 self.screen.blit(self.bg, (0, 0))
gyorgyf@12 481 pg.display.flip()
gyorgyf@27 482 self.fpsClock.tick(FRAMERATE)
gyorgyf@27 483
gyorgyf@27 484 if self.init_reconnect:
gyorgyf@27 485 self.reconnect()
gyorgyf@27 486
gyorgyf@27 487 return True
gyorgyf@28 488
gyorgyf@28 489 def configure_server(self):
gyorgyf@28 490 '''Send the server some configuration data.'''
gyorgyf@29 491 # age = 10.0
gyorgyf@29 492 # dist = DIST
gyorgyf@29 493 # ninp = 18
gyorgyf@29 494 self.update_server_config(self.s_age,self.s_dist,self.s_ninp)
gyorgyf@29 495
gyorgyf@27 496
gyorgyf@29 497 def update_server_config(self,age,dist,ninp,retry = 3):
gyorgyf@29 498 '''Send the server some configuration data.'''
gyorgyf@29 499 try :
gyorgyf@32 500 print "Sending configuration data."
gyorgyf@29 501 self.conn.putrequest("GET","/moodconductor/config?age=%(age)s&dist=%(dist)s&ninp=%(ninp)s" %locals(), skip_host=True)
gyorgyf@29 502 self.conn.putheader("Host", "www.isophonics.net")
gyorgyf@29 503 self.conn.endheaders()
gyorgyf@29 504 res = self.conn.getresponse()
gyorgyf@32 505 res.read()
gyorgyf@29 506 if not res.status == 200 :
gyorgyf@29 507 print "Server response:", res.status, res.reason
gyorgyf@29 508 self.indicators["conn"].off()
gyorgyf@29 509 time.sleep(0.5)
gyorgyf@29 510 self.conn.putrequest("GET","/moodconductor/getconf", skip_host=True)
gyorgyf@29 511 self.conn.putheader("Host", "www.isophonics.net")
gyorgyf@29 512 self.conn.endheaders()
gyorgyf@29 513 res = self.conn.getresponse()
gyorgyf@29 514 if not res.status == 200 :
gyorgyf@29 515 print "Server response:", res.status, res.reason
gyorgyf@32 516 self.indicators["conn"].off()
gyorgyf@29 517 print "Server configuration:", res.read()
gyorgyf@29 518 except:
gyorgyf@32 519 print "Failed to send configuration data."
gyorgyf@29 520 time.sleep(2)
gyorgyf@29 521 retry -= 1
gyorgyf@29 522 self.update_server_config(age,dist,ninp,retry)
gyorgyf@29 523
gyorgyf@27 524
gyorgyf@27 525 def connect(self,retry = 5):
gyorgyf@27 526 '''Connect to the server and test connection.'''
gyorgyf@27 527 if not retry :
gyorgyf@27 528 print "Server unreachable"
gyorgyf@27 529 pg.quit()
gyorgyf@27 530 raise SystemExit
gyorgyf@27 531 if retry < 5 :
gyorgyf@27 532 time.sleep(3)
gyorgyf@27 533 try :
gyorgyf@32 534 print "connecting to server..."
gyorgyf@27 535 self.conn = ht.HTTPConnection(IP,timeout=HTTP_TIMEOUT)
gyorgyf@27 536 self.indicators["conn"].on()
gyorgyf@27 537 except :
gyorgyf@27 538 self.indicators["conn"].off()
gyorgyf@27 539 self.connect(retry = retry-1)
gyorgyf@32 540 print "connection failed."
gyorgyf@27 541
gyorgyf@27 542 try:
gyorgyf@32 543 print "Testing connection."
gyorgyf@33 544 # self.conn.putrequest("GET","/moodconductor/index.html", skip_host=True)
gyorgyf@33 545 self.conn.putrequest("GET","/moodconductor/test", skip_host=True)
gyorgyf@27 546 self.conn.putheader("Host", "www.isophonics.net")
gyorgyf@27 547 self.conn.endheaders()
gyorgyf@27 548 res = self.conn.getresponse()
gyorgyf@33 549 print res.read()
gyorgyf@27 550 if res.status == 200 :
gyorgyf@27 551 self.indicators["conn"].on()
gyorgyf@27 552 else :
gyorgyf@27 553 print "Server response:", res.status, res.reason
gyorgyf@27 554 self.indicators["conn"].off()
gyorgyf@27 555 if not hasattr(self,"noretry") and raw_input("Go offline? ") in ['y',''] :
gyorgyf@27 556 return False
gyorgyf@27 557 else :
gyorgyf@32 558 print "Failed. retrying."
gyorgyf@27 559 self.noretry = None
gyorgyf@27 560 self.connect(retry = retry-1)
gyorgyf@27 561 except :
gyorgyf@27 562 print "Exception while testing connection."
gyorgyf@27 563 self.indicators["conn"].off()
gyorgyf@27 564 # comment out in offline mode
gyorgyf@27 565 if not hasattr(self,"noretry") and raw_input("Go offline? ") in ['y',''] :
gyorgyf@27 566 return False
gyorgyf@27 567 else :
gyorgyf@27 568 self.noretry = None
gyorgyf@27 569 self.connect(retry = retry-1)
gyorgyf@28 570 self.configure_server()
gyorgyf@32 571 print "OK. Starting update thread..."
gyorgyf@27 572 self.start_update_thread()
gyorgyf@27 573 return True
gyorgyf@27 574
gyorgyf@27 575
gyorgyf@27 576
gyorgyf@27 577 def reconnect(self):
gyorgyf@27 578 '''Called when c is pressed.'''
gyorgyf@27 579 self.init_reconnect = False
gyorgyf@27 580
gyorgyf@27 581 self.stop_update_thread()
gyorgyf@27 582 time.sleep(1)
gyorgyf@27 583 try :
gyorgyf@27 584 self.conn.close()
gyorgyf@27 585 except :
gyorgyf@27 586 self.indicators["conn"].off()
gyorgyf@27 587 try :
gyorgyf@27 588 self.conn = ht.HTTPConnection(IP,timeout=HTTP_TIMEOUT)
gyorgyf@27 589 self.conn.connect()
gyorgyf@27 590 self.indicators["conn"].on()
gyorgyf@27 591 print "Reconnected."
gyorgyf@27 592 except :
gyorgyf@27 593 self.indicators["conn"].off()
gyorgyf@27 594 print "Error while reconnecting."
gyorgyf@27 595 self.start_update_thread()
gyorgyf@27 596
gyorgyf@27 597
gyorgyf@27 598 def quit(self):
gyorgyf@27 599 print "Quitting.."
gyorgyf@27 600 self.indicators["conn"].off()
gyorgyf@27 601 self.stop_update_thread()
gyorgyf@27 602 self.conn.close()
gyorgyf@27 603 pg.quit()
gyorgyf@27 604 sys.exit()
gyorgyf@5 605
gyorgyf@5 606
gyorgyf@5 607 def main():
gyorgyf@5 608
gyorgyf@12 609 v = VisualClient()
gyorgyf@12 610 v.run()
gyorgyf@5 611
gyorgyf@5 612 if __name__ == '__main__':
gyorgyf@5 613 pass
gyorgyf@5 614 main()
gyorgyf@5 615