annotate visualclient/visclient.py @ 30:4a7fde8ff0fd

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