#!/usr/bin/env python

import sys
import gtk
import glib
import scipy as S
import scipy.misc.pilutil
import matplotlib.cm

from ApogeeCam import *
from Webcam import *
from CameraImage import *
from AwesomeColorMaps import awesome, isoluminant

class MainWindow:
    '''The main window for the LaserCam application.'''

    # Wrappers for C signal handlers called from gtk.Builder
    def gtk_widget_hide(self, widget, *args):
        widget.hide()

    def gtk_widget_hide_on_delete(self, widget, *args):
        return widget.hide_on_delete()

    def gtk_main_quit_on_delete(self, widget, *args):
        gtk.main_quit()
        return False

    # Signal handlers
    def action_about(self, action, data=None):
        self.about_window.present()
    
    def action_save(self, action, data=None):
        # First make a copy of the frame we will save
        save_frame = self.webcam.frame.copy()
        
        # Then find out where to save it
        dialog = gtk.FileChooserDialog('Save Image', self.main_window,
            gtk.FILE_CHOOSER_ACTION_SAVE,
            (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
            gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
        response = dialog.run()
        path = dialog.get_filename()
        dialog.destroy()
        if response != gtk.RESPONSE_ACCEPT:
            return
        
        # Save it
        S.misc.imsave(path, save_frame)
    
    def action_find_resolution(self, action, data=None):
        pass
    
    def action_take_video(self, action, data=None):
        # Set the 'Take Photo' action insensitive if 'Take Video' is on
        self.actiongroup.get_action('take_photo').set_sensitive(not action.get_active())
        
        if action.get_active():
            self.timeout_id = glib.timeout_add(50, self.image_capture)
        else:
            glib.source_remove(self.timeout_id)
    
    def action_take_photo(self, action, data=None):
        self.image_capture()
    
    def action_quit(self, action, data=None):
        gtk.main_quit()
    
    def on_rotate_box_changed(self, combo, data=None):
        self.screen.rotate = combo.props.active

    def _index_to_cmap(self, index):
        if index == 0:
            return None
        elif index == 1:
            return matplotlib.cm.gray
        elif index == 2:
            return matplotlib.cm.bone
        elif index == 3:
            return matplotlib.cm.pink
        elif index == 4:
            return matplotlib.cm.jet
        elif index == 5:
            return isoluminant
        elif index == 6:
            return awesome
        else:
            raise ValueError('Unexpected colormap value')

    def on_colorscale_box_changed(self, combo, data=None):
        self.screen.cmap = self._index_to_cmap(combo.props.active)
        self.cmap_sample.queue_draw()

    def on_cmap_sample_expose_event(self, widget, event, data=None):
        cmap = self._index_to_cmap(self.colorscale_box.props.active)
        if cmap is None:
            indices = [0] * 256
        else:
            cmap_array = N.array(cmap(N.arange(0, 256)) * 255, dtype=N.uint32)
            indices = list( cmap_array[:,0] << 16
                          | cmap_array[:,1] << 8
                          | cmap_array[:,2] )
        gc = self.cmap_sample.window.new_gc()
        data = N.require(N.outer(N.ones(10), N.arange(0, 256, 2)),
               dtype=N.uint8,
               requirements=['C_CONTIGUOUS', 'ALIGNED'])
        self.cmap_sample.window.draw_indexed_image(gc,
            0, 0,
            128, 10,
            gtk.gdk.RGB_DITHER_NONE,
            data, data.strides[0],
            indices)

    # Image capture timeout
    def image_capture(self):
        try:
            self.webcam.query_frame()
            self.screen.data = self.webcam.frame
                
        except CameraError:
            errmsg = gtk.MessageDialog(parent=self.main_window, 
                flags=gtk.DIALOG_MODAL, 
                type=gtk.MESSAGE_ERROR,
                buttons=gtk.BUTTONS_CLOSE,
                message_format='There was an error reading from the camera.')
            errmsg.run()
            sys.exit()
        
        while gtk.events_pending():
            gtk.main_iteration()
        
        return True  # keep the timeout going

    def __init__(self):
        # Load our user interface definition
        builder = gtk.Builder()
        builder.add_from_file('../data/LaserCam.ui')

        # Load our menu/toolbar definition
        manager = gtk.UIManager()
        manager.add_ui_from_file('../data/menus.xml')

        # Add all the actions to an action group for the menu and toolbar
        self.actiongroup = builder.get_object('actiongroup')
        actions = {
            'file_menu': '', 
            'edit_menu': '', 
            'view_menu': '', 
            'camera_menu': '', 
            'math_menu': '', 
            'help_menu': '',
            'about': '',
            'save': '<control>s',
            'find_resolution': '',
            'take_video': '',
            'take_photo': '',
            'quit': '<control>q',
        }
        for action,accel in actions.iteritems():
            self.actiongroup.add_action_with_accel(builder.get_object(action), accel)
        manager.insert_action_group(self.actiongroup)

        # Build the window
        self.main_window = builder.get_object('main_window')
        self.main_window.get_child().pack_start(manager.get_widget('/menubar'), expand=False)
        self.main_window.get_child().pack_start(manager.get_widget('/toolbar'), expand=False)
        self.screen = CameraImage()
        self.screen.set_size_request(640, 480)
        self.main_window.get_child().pack_start(self.screen)

        # Save pointers to other widgets
        self.about_window = builder.get_object('about_window')
        self.colorscale_box = builder.get_object('colorscale_box')
        self.cmap_sample = builder.get_object('cmap_sample')

        # Set up image capturing
        self.webcam = Webcam(cam=0) # index of camera to be used
        try:
            self.webcam.open()
        except CameraError:
            errmsg = gtk.MessageDialog(parent=self.main_window, 
                flags=gtk.DIALOG_MODAL, 
                type=gtk.MESSAGE_ERROR,
                buttons=gtk.BUTTONS_CLOSE,
                message_format='No camera was detected. Did you forget to plug it in?')
            errmsg.run()
            sys.exit()

        # Connect the signals last of all
        builder.connect_signals(self, self)

if __name__ == '__main__':
    mainwin = MainWindow()
    mainwin.main_window.show_all()
    gtk.main()

@@ -1791,23 +1791,20 @@
    self.
-timeout
+idle
 _id = gl
@@ -1810,24 +1810,17 @@
 lib.
-timeout
+idle
 _add(
-50, 
 self
@@ -1887,23 +1887,20 @@
 ve(self.
-timeout
+idle
 _id)%0D%0A  
@@ -3837,76 +3837,8 @@
 ()%0D%0A
-            self.screen.data = self.webcam.frame%0D%0A                %0D%0A
     
@@ -4184,32 +4184,36 @@
 exit()%0D%0A        
+    
 %0D%0A        while 
@@ -4210,79 +4210,44 @@
     
-while gtk.events_pending():%0D%0A            gtk.main_iteration()%0D%0A        
+self.screen.data = self.webcam.frame
 %0D%0A  
@@ -4276,23 +4276,29 @@
 eep the 
-timeout
+idle function
  going%0D%0A

Read the camera in an idle function instead of a timeout