|
|
Was able to get povray, megapov, and megapov_xrs installed on cygwin. Was
also able to verify correct operation for povray and megapov.
Megapov_xrs_server starts up ok and starts listening.
Megapov_xrs_client terminates with the following error:
==============
$ python pyxrsclient.py +Iwoodbox.pov +V +W800 +H600 +Owoodbox.png
+L/cygdrive/c/program_files/cygwin/tmp/povray-3.6.1/include
Traceback (most recent call last):
File "pyxrsclient.py", line 55, in ?
import gtk
File "/usr/lib/python2.4/site-packages/gtk-2.0/gtk/__init__.py", line 37,
in ?
from _gtk import *
RuntimeError: could not open display
===============
The pyxrsclient.py is:
#! /bin/python
#
# pyxrsclient.py
# George Pantazopoulos
# http://www.gammaburst.net
# Python client for distributed rendering using Megapov XRS Servers
# 28 Aug 2006
# Hyper-threaded, sweet buttery goodness.
# Server URL's, followed by the base POV directory (pov_basedir)
# URL's should be in the form "http://ip-address:port"
#
# pov_basedir should contain the following subdirs
# and be duplicated on all servers:
#
# fonts/
# imagemaps/
# include/
# LightsysIV/
# scenes/
#
# Only one of these directory structures is needed per machine
# even it has more than one CPU
# Server info format.
# -------------------
#
# ("http://server-ip:server-port", /"pov_basedir/for/this/server"),
#
# Edit this variable (last entry should not have a comma):
g_server_urls = [("http://localhost:9000",
"/cygdrive/c/program_files/cygwin/tmp/povray-3.6.1")]
# Required subdirs on all servers. Ordering counts! (not yet implemented)
#g_required_subdirs = ["scenes", "include", "fonts", "imagemaps",
"LightsysIV"]
# Max tiles to queue per server (default=4)
# Increase if servers are spending too much time in the READY state
g_max_tiles_to_queue = 4
g_polling_delay_sec = 1.0 # default=1.0. increase if there are many servers.
# Disable this is if it causes problems.
g_enable_status_display = True
import sys
if len(sys.argv) < 2:
print "Usage: " + str(sys.argv[0]) + " povray-args"
sys.exit(1)
import pygtk
pygtk.require('2.0')
import gtk
import xmlrpclib
import time
import threading
import socket
import gc
import Queue
import gobject
import os
import os.path
import re
from tilelib import genStartAndEndCoords, MakeTileGrid, MakeSpiralTileList
from xrslib import STATE_IDLE, STATE_INIT, STATE_READY,
STATE_RENDERING, STATE_CLEANUP, STATE_ERROR
g_parser = 0
g_name = "pyxrsclient"
g_version = "0.6.10"
#
-----------------------------------------------------------------------------
class CommandLineParser:
def __init__(self, arglist):
# Create a single string out of the argument list.
self.cmd = ""
for s in arglist:
self.cmd += s
self.cmd += " "
# Process the cmd so that any backslashes are replaced with
# forward slashes.
self.cmd = self.cmd.replace("\", "/")
# Force the display off. There is a bug in megapov_xrs_server
# version <= 2.0.4 that segfaulted on a user's AMD64 system
# unless -D was specified on the command line
self.cmd += " -D"
# The user can specify tile size using the POV-Ray 3.7 compatible
# +BSn option. However, we need to remove it from the POV-Ray
# string. This is for client use only.
# First match the n portion of the blocksize arg "+BSn"
rs_blocksize = re.search("(?<=[+-]BS)[0-9]+", self.cmd)
if rs_blocksize == None:
self.blocksize = 64
else:
self.blocksize = int(rs_blocksize.group(0))
# Then, match the whole +BSn string
# and excise it from the pov command line
rs_blocksize_str = re.search("([+-]BS[0-9]+)", self.cmd)
if rs_blocksize_str == None:
pass
else:
self.cmd = self.cmd.replace(rs_blocksize_str.group(0), "")
# remove any +o options
output_name_rs = re.search("([+-]o[^ ]*)", self.cmd)
if output_name_rs == None:
pass
else:
self.cmd = self.cmd.replace(output_name_rs.group(0), "")
def getCmd(self):
return self.cmd
def getImgWidth(self):
imgwidth = int(re.search("(?<=[+-]w)[0-9]+", self.cmd).group(0))
return imgwidth
def getImgHeight(self):
imgheight = int(re.search("(?<=[+-]h)[0-9]+", self.cmd).group(0))
return imgheight
def getBlockSize(self):
# TODO: take this out of the POV-ray command line afterwards!
return self.blocksize
def getImgFormat(self):
# Extract the user's image type preference
# TODO if not found, or a different type, enforce PNG (+fn)
image_format = re.search("(?<=[+-]f)[^ ]+", self.cmd).group(0)
return image_format
def getScenePath(self):
# Extract the scene file path. Path must not contain spaces.
#scene_path = re.search("(?<=[+-]I)[^ ]+", self.cmd).group(0)
# The Scene Path may or may not be preceded by a +I
# Thus, we search using the .pov extension, and strip
# away the +I, if present
scene_path = ""
rs_scene_path_option = re.search("([^ ]+)(?=.pov).pov", self.cmd)
if rs_scene_path_option == None:
raise "Could not find a .pov file in the command string"
else:
scene_path_option = rs_scene_path_option.group(0)
# strip away the +I, if present
# Use a positive lookbehind assertion.
# Match the rest of the string, if the +I was present
xim = re.search("(?<=[+-]I)[^ ]+", scene_path_option)
# If there was no +I, we can use the scene path as is
if xim == None:
scene_path = scene_path_option
else:
# The matching process stripped away the +I
scene_path = xim.group(0)
return scene_path
def getSceneFile(self):
scene_file = os.path.basename(self.getScenePath())
return scene_file
def getBaseDir(self):
# Until 'scenes' appears in the 'tail' portion
# keep splitting. Unsuccessful is head becomes the empty string
p = self.getScenePath()
import os.path
base_dir = ""
x = os.path.split(p)
while (x[1] != 'scenes') and (x[1] != ''):
x = os.path.split(x[0])
if (x[1] == ''):
base_dir = None
else:
base_dir = x[0]
# Ensure that base_dir contains a trailing slash
base_dir += "/"
return base_dir
#
-----------------------------------------------------------------------------
# Give the xmlrpclib's ServerProxy the ability to store
# other useful info, such as the working directory
class XrsProxy(xmlrpclib.ServerProxy):
def __init__(self, url, base_dir):
xmlrpclib.ServerProxy.__init__(self, url)
self.base_dir = base_dir
# ensure the base_dir has a trailing slash
self.base_dir += "/"
self.url = url
def getBaseDir(self):
return self.base_dir
def getUrl(self):
return self.url
#
-----------------------------------------------------------------------------
def PrintServerSettings(server_info):
for i in server_info:
print "URL: " + str(i[0])
print "POV BaseDir: " + str(i[1])
print ""
#
-----------------------------------------------------------------------------
def CreateServerProxies(server_urls):
""" Returns a list of active ServerProxies """
server_proxies = []
# For each Server URL, create a ServerProxy
for u in server_urls:
sp = XrsProxy(u[0], u[1])
# Try connecting to this server proxy
# If we don't get an exception, then we can add
# it to our list.
try:
sp.Status()
server_proxies.append(sp)
print "Server " + str(u[0]) + "... OK"
except socket.error, msg:
print "Server " + str(u[0]) + "... " + str(msg[1])
except xmlrpclib.ProtocolError, msg:
print "Server " + str(u[0]) + "... " + str(msg)
return server_proxies
#
-----------------------------------------------------------------------------
g_rendered_tiles = Queue.Queue()
g_tiles_to_display = Queue.Queue()
g_tiles_to_render = Queue.Queue()
def GenerateTiles(img_w, img_h, nx, ny):
tileGrid = MakeTileGrid(img_w, img_h, nx, ny)
return MakeSpiralTileList(nx, ny, tileGrid)
#
-----------------------------------------------------------------------------
class DisplayThread(threading.Thread):
stopthread = threading.Event()
def __init__(self, tile_q):
threading.Thread.__init__(self)
self.tile_q = tile_q
def run(self):
# loop until until terminated
while (not self.stopthread.isSet()):
try:
# block on queue and wait for a tile to become available
tile = self.tile_q.get()
# If we got woken up on purpose so we can exit,
# we want to exit here, before trying to display a fake tile
if (self.stopthread.isSet()):
return
# Extract the base64data from the tile and convert to binary
b = xmlrpclib.Binary()
b.decode(tile['base64data'])
# Save the image data to a temp file so it can be loaded by
gtk
output_dir = "./"
file_ext = "png";
filename = "retrieved_tile" + str(tile['id']) + "." +
file_ext
full_path = output_dir + filename
out_file = open(output_dir + filename, "wb")
out_file.write(b.data)
out_file.close()
# Display the tile
# Paste our tile into the appropriate location in the main
pixbuf
id = int(tile['id'])
sc = int(tile['sc'])
ec = int(tile['ec'])
sr = int(tile['sr'])
er = int(tile['er'])
tile_width = (ec-sc) + 1
tile_height = (er-sr) + 1
x_offset = sc - 1 # sc starts at 1
y_offset = sr - 1 # sr starts at 1
# Now that we have a file saved, create a gtk Pixbuf
# To hold our tile.
gtk.threads_enter()
#print "file info: " +
str(gtk.gdk.pixbuf_get_file_info(full_path))
tile_pb = gtk.gdk.pixbuf_new_from_file_at_size(full_path,
g_parser.getImgWidth(),
g_parser.getImgHeight()) #height
#POV-Ray creates PNGs with incorrect size params
# (the size of the original image). So we need to extract
# our actual rendered region/
# For now, only use vertical stripe tiles
tile_pb.copy_area(x_offset, 0,#y_offset, # This hack is
necessary to work with POV's screwed up PNG's
tile_width, tile_height,
g_pbmain,
x_offset, y_offset)
# update the main pixbuf
g_image.set_from_pixbuf(g_pbmain)
# With PyGTK, the pixbuf does not get destroyed
# when we go out of scope, leading to increasing memory
usage.
# According to the FAQ,
# the solution is to prod the garbage collector.
# Hopefully this won't slow things down too much here.
gc.collect()
# delete the image file now that we don't need it anymore.
os.remove(full_path)
gtk.threads_leave()
# This should catch Decompression errors with POV's wierd PNGs
except gobject.GError, msg:
print "Caught exception in DisplayThread: " + str(msg) + "
.... continuing"
# we must do this before continuing!
gtk.threads_leave()
continue
except OSError, msg:
print "Caught exception in DisplayThread: " + str(msg) + "
.... continuing"
# we must do this before continuing!
gtk.threads_leave()
continue
def stop(self):
self.stopthread.set()
# Put in a fake tile to unblock thread.
self.tile_q.put_nowait(None)
#
-----------------------------------------------------------------------------
# Each Render thread will handle one XRS Server.
class RenderClientThread(threading.Thread):
stopthread = threading.Event()
tiles_in_progress = Queue.Queue()
def __init__(self, sp):
# Must invoke the base-class ctor
threading.Thread.__init__(self)
# The ServerProxy
self.sp = sp
myname = "Render Thread for Server " + str(sp.getUrl())
self.setName(myname)
global g_parser
self.pov_basedir = sp.getBaseDir()
client_scene_path = g_parser.getScenePath()
client_pov_basedir = g_parser.getBaseDir()
self.scene_path = client_scene_path.replace(client_pov_basedir,
self.pov_basedir)
self.scene_dir = os.path.dirname(self.scene_path)
self.library_path =
"+L" + "." + " " +
"+L" + self.scene_dir + "/ "
"+L" + self.scene_dir + "/maps/ "
"+L" + self.pov_basedir + "/include/" + " " +
"+L" + self.pov_basedir + "/LightsysIV/" + " "
"+L" + self.pov_basedir + "/ "
"+L" + self.pov_basedir + "/imagemaps/" + " "
"+L" + self.pov_basedir + "/fonts/" + " "
# Pass along the povray command, but first edit out the
# the client's pov_basedir and replace it with our own
self.cmd = g_parser.getCmd()
self.cmd = self.cmd.replace(client_pov_basedir, self.pov_basedir)
# Add the library paths we just generated
self.cmd += " "
self.cmd += self.library_path
print "Command to be sent to Server " + str(self.sp.getUrl()) + ":"
print self.cmd
print ""
def run(self, **kwargs):
scene_id = 0
# Try to start a NewScene on the Server
try:
scene_id = self.sp.NewScene({'command':self.cmd})
#print "NewScene id = " + str(scene_id)
except socket.error, msg:
print "Caught exception in RenderClientThread: " + str(msg) + ".
Exiting thread"
return
except xmlrpclib.Fault, msg:
print "Caught exception in RenderClientThread: " + str(msg) + ".
Exiting thread"
return
# Ok, a NewScene() command was accepted.
# Note, the previous scene could still be cleaning up.
# Thus, we need to wait for the new scene's id to appear
# in the status response.
self.updateStatus()
while self.status['scene_id'] != scene_id:
self.updateStatus()
state = self.status['state']
scene_id = self.status['scene_id']
## print "scene_id=" + str(scene_id)
## + ", " + "state=" + str(state)
if self.stopthread.isSet():
return
time.sleep(0.5)
# Wait for our scene to be ready.
while self.status['state'] != STATE_READY:
self.updateStatus()
state = self.status['state']
scene_id = self.status['scene_id']
## print self.status
if state == STATE_ERROR:
print "Server reported STATE_ERROR for scene_id " +
str(scene_id)
return
if self.stopthread.isSet():
return
time.sleep(0.5)
# Refresh the status
self.updateStatus()
# Give the Server its first tile to render
# TODO: if the server comes late to the party,
# there could be no tiles available, causing an exception.
try:
tile = g_tiles_to_render.get_nowait()
self.sp.RenderTile(tile)
self.tiles_in_progress.put_nowait(tile)
except Queue.Empty:
print "no tiles to render. continuing wait loop"
return
time.sleep(0.1)
self.updateStatus()
# Loop as long as the Server is not in STATE_ERROR
while self.status['state'] != STATE_ERROR:
global g_polling_delay_sec
time.sleep(g_polling_delay_sec)
# Refresh the status
self.updateStatus()
if self.stopthread.isSet():
# Stop the Server from rendering by sending it a NewScene()
# with an empty command.
self.sp.NewScene({'command':""})
self.status['state'] = 'STOPPED'
g_server_status[self.sp.getUrl()]['state'] =
self.status['state']
return
try:
# Goal:
# Make sure Server has tiles to work on at all times,
# especially while it's transferring a bunch of
# rendered tiles.
num_tiles_ready = self.status['tiles_ready']
if num_tiles_ready > 0:
# Before we transfer any tiles that are ready
# Give the Server more work to do.
num_tiles_queued = self.status['tiles_queued']
global g_max_tiles_to_queue
max_tiles_to_queue = g_max_tiles_to_queue
tiles_to_queue = max(0, max_tiles_to_queue -
num_tiles_queued)
for i in range(tiles_to_queue):
# Give the Server a new tile to render.
self.updateStatus()
if (g_tiles_to_render.qsize() > 0):
tile = g_tiles_to_render.get_nowait()
self.sp.RenderTile(tile)
self.tiles_in_progress.put_nowait(tile)
# Now that the Server will be rendering, transfer the
# rendered tiles.
for i in range(num_tiles_ready):
self.updateStatus()
rendered_tile = self.sp.GetRenderedTile()
# If we made it here, then we retrieved a rendered
tile image
#print "retrieved image: " +
rendered_tile['filename']
# Pop the rendered tile from the server.
self.sp.PopRenderedTile(rendered_tile['id'])
# put the tile into the list of rendered tiles.
g_rendered_tiles.put_nowait(rendered_tile)
# Queue the tile up for display.
g_tiles_to_display.put_nowait(rendered_tile)
# When the tile is downloaded, remove it from
# our "in progress" queue.
# We assume that the Server preserves the ordering
of any
# tiles it's given to render.
self.tiles_in_progress.get_nowait()
except xmlrpclib.Fault, msg:
print "Caught exception in RenderClientThread: " + str(msg)
+ " Continuing..."
continue
# No more tiles to render.
except Queue.Empty:
print "no tiles to render. continuing wait loop"
continue
print "RenderClientThread finished"
def getServerProxy(self):
return self.sp
def updateStatus(self):
# Refresh the status
self.status = self.sp.Status()
# Update the status display
g_server_status[self.sp.getUrl()]['state'] = self.status['state']
g_server_status[self.sp.getUrl()]['tiles_queued'] =
self.status['tiles_queued']
g_server_status[self.sp.getUrl()]['tiles_ready'] =
self.status['tiles_ready']
## print str(self.sp) + ": " + "scene_id=" + str(scene_id)
## + ", " + "state=" + str(status['state'])
## + ", " + "tiles_ready=" + str(status['tiles_ready'])
## + ", " + "tiles_queued=" + str(status['tiles_queued'])
def getTilesInProgress(self):
# This is meant to be called after the thread has stopped
# so qsize() will be stable.
# This 'uses up' the tiles.
tiles = []
print "***** " + str(self.tiles_in_progress.qsize()) + "tiles to
recover"
for i in range(self.tiles_in_progress.qsize()):
tiles.append(self.tiles_in_progress.get_nowait())
return tiles
def stop(self):
self.stopthread.set()
#
-----------------------------------------------------------------------------
def main_quit(obj):
print "doing gtk.main_quit()"
g_status_window.destroy()
gtk.main_quit()
print "gtk.main_quit() done"
#
-----------------------------------------------------------------------------
# GUI Bootstrap
def InitGui():
global g_pbmain, g_image
g_pbmain = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8,
g_parser.getImgWidth(), g_parser.getImgHeight())
g_image = gtk.Image()
g_image.set_from_pixbuf(g_pbmain)
g_image.show()
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
window.add(g_image)
window.connect('destroy', main_quit)
window.set_title("Render Preview - " + g_name + " " + g_version)
window.show_all()
global g_status_window
g_status_window = gtk.Window(gtk.WINDOW_TOPLEVEL)
pass
#
-----------------------------------------------------------------------------
class MasterRenderThread(threading.Thread):
def __init__(self):
# Must invoke the base-class ctor
threading.Thread.__init__(self)
global g_parser
self.stopthread = threading.Event()
self.renderClientThreads = []
self.num_total_tiles = 0
def run(self):
global g_rendered_tiles
global g_tiles_to_render
global g_server_proxies
global g_parser, g_num_x_tiles, g_num_y_tiles
# Generate tiles
unrendered_tiles = GenerateTiles(g_parser.getImgWidth(),
g_parser.getImgHeight(),
g_num_x_tiles, g_num_y_tiles)
unrendered_tiles.reverse()
num_total_tiles = len(unrendered_tiles)
for t in unrendered_tiles:
g_tiles_to_render.put_nowait(t)
# Spawn Render Client Threads, one for each ServerProxy
print "spawning render client threads"
self.spawnRenderClientThreads(g_server_proxies)
# while the number of rendered tiles is less than
# the total tiles, wait.
while g_rendered_tiles.qsize() < num_total_tiles:
time.sleep(3)
# If any of the render threads need work,
# assign some to them.
# If we've run out of rendered tiles
# scene_file must be just a filename, no directories
scene_file = g_parser.getSceneFile()
# Separate out the .pov extension.
image_base_name = os.path.splitext(scene_file)[0]
output_filename = image_base_name + ".png"
g_pbmain.save(output_filename, "png", {})
# Check that at least one render thread is alive
num_threads_alive = 0
for thr in self.renderClientThreads:
if thr.isAlive():
num_threads_alive += 1
if num_threads_alive == 0:
print "all render threads have died. exiting Master Render
Thread.."
break
# If a render thread died, reclaim the tiles
# it was working on and requeue them.
for thr in self.renderClientThreads:
if (not thr.isAlive()):
tiles = thr.getTilesInProgress()
for t in tiles:
g_tiles_to_render.put_nowait(t)
self.killRenderClientThreads()
global g_start_time, g_stop_time
g_stop_time = time.time()
print "Master Render Thread is done"
print ""
print "- Render Stats
-----------------------------------------------------------------"
total_time = g_stop_time - g_start_time
print " Total Render time: " + str(total_time) + "s"
print
"--------------------------------------------------------------------------------"
print ""
def spawnRenderClientThreads(self, server_proxies):
for sp in server_proxies:
self.renderClientThreads.append(RenderClientThread(sp))
self.renderClientThreads[-1].start()
def killRenderClientThreads(self):
for t in self.renderClientThreads:
t.stop()
def stop(self):
self.stopthread.set()
self.killRenderClientThreads()
#
-----------------------------------------------------------------------------
class StatusDisplay:
def __init__(self, server_proxies):
# Create a list of dictionaries. One for each server.
# These will contain the widgets that can be dynamically updated
# as the info changes.
#self.serverinfo = []
self.widgets = {}
for k in g_server_status.keys():
gtk.threads_enter()
entry_name = gtk.Entry()
entry_name.set_editable(False)
entry_name.set_text(k)
entry_status = gtk.Entry()
entry_status.set_editable(False)
entry_status.set_text(g_server_status[k]['state'])
entry_tq = gtk.Entry()
entry_tq.set_editable(False)
entry_tq.set_text(str(g_server_status[k]['tiles_queued']))
entry_tr = gtk.Entry()
entry_tr.set_editable(False)
entry_tr.set_text(str(g_server_status[k]['tiles_ready']))
self.widgets[k] =
{'name_label':entry_name, 'state_display':entry_status,
'tq_display':entry_tq, 'tr_display':entry_tr}
gtk.threads_leave()
# For each serverinfo entry create a horizontal row containing
# info about the Server's state.
gtk.threads_enter()
#self.status_window = gtk.Window(gtk.WINDOW_TOPLEVEL)
# Seem to need a global window, otherwise it doesn't
# die when the program reaches the end, causing us to hang.
global g_status_window
self.status_window = g_status_window
self.status_window.set_title("XRS Server Status")
self.vbox = gtk.VBox(False,0)
hbox = gtk.HBox(homogeneous=True, spacing=0)
label_name = gtk.Label("Server Name")
label_state = gtk.Label("State")
label_tq = gtk.Label("Tiles Queued")
label_tr = gtk.Label("Tiles Ready")
hbox.pack_start(label_name)
hbox.pack_start(label_state)
hbox.pack_start(label_tq)
hbox.pack_start(label_tr)
self.vbox.pack_start(hbox)
for wk in self.widgets.keys():
# Create a horizonal box to hold a row for a single server
status
hbox = gtk.HBox(homogeneous=True, spacing=0)
hbox.pack_start(self.widgets[wk]['name_label'])
hbox.pack_start(self.widgets[wk]['state_display'])
hbox.pack_start(self.widgets[wk]['tq_display'])
hbox.pack_start(self.widgets[wk]['tr_display'])
hbox.show()
self.vbox.pack_start(hbox)
self.vbox.show()
self.status_window.add(self.vbox)
self.status_window.show_all()
gtk.threads_leave()
def refresh(self):
global g_server_status
gtk.threads_enter()
for wk in self.widgets.keys():
x = g_server_status[wk]
self.widgets[wk]['state_display'].set_text(x['state'])
self.widgets[wk]['tq_display'].set_text(str(x['tiles_queued']))
self.widgets[wk]['tr_display'].set_text(str(x['tiles_ready']))
self.status_window.queue_draw()
gtk.threads_leave()
#
-----------------------------------------------------------------------------
class StatusDisplayThread(threading.Thread):
def __init__(self, status_display):
threading.Thread.__init__(self)
self.stopthread = threading.Event()
self.status_display = status_display
def run(self):
while (not self.stopthread.isSet()):
self.status_display.refresh()
time.sleep(0.1)
def stop(self):
self.stopthread.set()
#
-----------------------------------------------------------------------------
import sys
g_parser = CommandLineParser(arglist=sys.argv[1:])
g_num_x_tiles = g_parser.getImgWidth() / g_parser.getBlockSize()
g_num_y_tiles = g_parser.getImgHeight() / g_parser.getBlockSize()
print ""
print
"--------------------------------------------------------------------------------"
print g_name + " version " + g_version
print "Python Megapov-XRS Client by George Pantazopoulos
http://www.gammaburst.net"
print
"--------------------------------------------------------------------------------"
print ""
print "- Image Settings
---------------------------------------------------------------"
print " " + str(g_num_x_tiles) + "x" +
str(g_num_y_tiles) + " tiles"
print ""
g_client_pov_basedir = g_parser.getBaseDir()
if (g_client_pov_basedir == None):
raise "POV Base dir could not be located. Path must contain scenes/"
g_pbmain = 0
g_image = 0
g_server_proxies = []
g_server_status = {}
gtk.threads_init()
InitGui()
# See Master Render Thread for when we stop the timer.
g_start_time = time.time()
print "- XRS Server settings
----------------------------------------------------------"
PrintServerSettings(g_server_urls)
# Create the Server Proxies, and weed out the unconnected servers
print ""
print "- Render Server Status
---------------------------------------------------------"
g_server_proxies = CreateServerProxies(g_server_urls)
print ""
print "Populating g_server_status"
for s in g_server_proxies:
g_server_status[s.getUrl()] = {'state':'N/A', 'tiles_queued':0,
'tiles_ready':0}
print ""
g_threads = []
print "creating Master Render Thread"
masterRenderThread = MasterRenderThread()
print "Creating Display Thread"
displayThread = DisplayThread(g_tiles_to_display)
if g_enable_status_display:
print ""
print "Creating Status Display"
g_sd = StatusDisplay(g_server_proxies)
print "Creating Status Display Thread"
statusDisplayThread = StatusDisplayThread(g_sd)
g_threads.append(statusDisplayThread)
g_threads.append(masterRenderThread)
g_threads.append(displayThread)
print "Starting helper and work threads"
for t in g_threads:
t.start()
print "main thread is going into gtk.main()"
gtk.threads_enter()
gtk.main()
gtk.threads_leave()
print "broke out from gtk.main()"
print "stopping threads"
for t in g_threads:
t.stop()
print "issued stop commmands"
print "waiting for threads to finish"
for t in g_threads:
t.join()
print "all threads finished"
print "reached end of main thread"
print "Exiting."
======================
The intended application supports work in atmospheric physics. We hope to
improve atmospheric correction in sensor data.
Best,
Peter.
Post a reply to this message
|
|