def main():
    global window, scene

    glutInit(sys.argv)

    # Select type of Display mode:   
    #  Double buffer 
    #  RGBA color
    # Alpha components supported 
    # Depth buffer
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH)
    
    # get a 640 x 480 window 
    glutInitWindowSize(960, 480)
    
    # the window starts at the upper left corner of the screen 
    glutInitWindowPosition(0, 0)
    
    # Okay, like the C version we retain the window id to use when closing, but for those of you new
    # to Python (like myself), remember this assignment would make the variable local and not global
    # if it weren't for the global declaration at the start of main.
    window = glutCreateWindow("ACCRE Cluster Status Monitor")

    # Register the drawing function with glut, BUT in Python land, at least using PyOpenGL, we need to
    # set the function pointer and invoke a function to actually register the callback, otherwise it
    # would be very much like the C version of the code.    
    glutDisplayFunc(DrawGLScene)
    #glutDisplayFunc()
    
    # Uncomment this line to get full screen.
    # glutFullScreen()

    # When we are doing nothing, redraw the scene.
    glutIdleFunc(doIdle)
        
    # Register the function called when our window is resized.
    glutReshapeFunc(ReSizeGLScene)

    # Register the function called when the keyboard is pressed.  
    glutKeyboardFunc(keyPressed)
    
    glutMouseFunc( mousePressed )
    
    # Load the stages
    storageStage   = StorageStage()
    globeStage     = TexturedGlobe()

    LHCStatusStage = CurlStage( pos = [40.9604490329, 580.455382799, 797.001287513],
                                url = "http://vistar-capture.web.cern.ch/vistar-capture/lhc1.png",
                                updateRate = 160 * 1000)
    DAQStatusStage = CurlStage( pos = [36.9604490329, 580.455382799, 797.001287513],
                                url = "http://cmsonline.cern.ch/daqStatusSCX/aDAQmon/DAQstatusGre.jpg",
                                updateRate = 150 * 1000)
    CMSStatusStage = CurlStage( pos = [32.9604490329, 580.455382799, 797.001287513],
                                url = "http://cmspage1.web.cern.ch/cmspage1/data/page1.png",
                                updateRate = 180 * 1000)
    
    scene['camera'].lookat = LHCStatusStage.pos
    scene['camera'].pos = [40.9604490329, 580.455382799, 799.001287513]
     
    scene['objects'].extend( [storageStage, globeStage, LHCStatusStage, DAQStatusStage, CMSStatusStage] )
    
    globalCameraTween    = MoveCameraTween( scene['camera'], [137.74360349518597, 1769.5965518451512, 2418.585277263117],
                                            [0,0,0],[0,1,0] )
    
    #globalViewTween = RotateCameraTween( scene['camera'], 36.1658, -86.7844, 3000, 1, [0,0,0], [0,1,0])
    globalViewTween = RotateCameraTween( scene['camera'], 36.1658,-86.7844, 3000, 1, [0,0,0], [0,1,0])

    storageCamTween  = MoveCameraTween( scene['camera'],
                                             [45.9604490329, 580.455382799, 799.001287513],
                                             [45.9604490329, 580.455382799, 797.001287513],
                                             [0,1,0] )

    
    hideGlobe = HideTween( [ globeStage] )
    showGlobe = ShowTween( [ globeStage] )
    
    storageTimeline = Timeline( name = "Vampire - Storage")
    storageTimeline.tweens.append( storageCamTween )
    storageTimeline.tweens.append( hideGlobe )
    storageToGlobal = Timeline( name = "Zoom to world")
    storageToGlobal.tweens.append( globalCameraTween )
    storageToGlobal.tweens.append( showGlobe )
    globalTimeline  = Timeline( name = "CMS - Global")
    globalTimeline.tweens.append( globalViewTween )
    #globalTimeline.duration = 50000
    globalToStorage = Timeline( name = "Zoom to ACCRE")
    globalToStorage.tweens.append( storageCamTween )
    
    plotsToMonitor = ["http://vistar-capture.web.cern.ch/vistar-capture/lhc1.png",
                      "http://cmsonline.cern.ch/daqStatusSCX/aDAQmon/DAQstatusGre.jpg",
                      "http://cmspage1.web.cern.ch/cmspage1/data/page1.png"]
    initialPlotPos = [40.9604490329, 580.455382799, 797.001287513]
    previousTimeline = storageTimeline
    for plot in plotsToMonitor:
        stage = CurlStage( pos = initialPlotPos,
                                url = plot,
                                updateRate = 160 * 1000)
        
        plotSwapTween  = MoveCameraTween( scene['camera'],
                                             Vectors.add(stage.pos, [0,0,2]),
                                             stage.pos,
                                             [0,1,0],
                                             arrivalAlpha = 0.1 )
        currentTimeline = Timeline( name = "Monitoring Plots")
        currentTimeline.tweens.append( plotSwapTween )
        previousTimeline.setNext( currentTimeline )
        previousTimeline = currentTimeline
        initialPlotPos = Vectors.add(initialPlotPos, [-4,0,0])

    currentTimeline.setNext(storageToGlobal)
    storageToGlobal.setNext( globalTimeline )
    globalTimeline.setNext(  globalToStorage )
    globalToStorage.setNext( storageTimeline )
    
    scene['currentTimeline'] = globalTimeline
    globalTimeline.start( 0 )
    # Initialize our window. 
    InitGL(960, 480)