#!/usr/bin/env python

import gobject
gobject.threads_init()
import gtk
gtk.gdk.threads_init()
import hildon
import gst
import sys
import os

# VideoWidget taken from play.py in gst-python examples
class VideoWidget(gtk.DrawingArea):
    def __init__(self):
        gtk.DrawingArea.__init__(self)
        self.imagesink = None
        self.unset_flags(gtk.DOUBLE_BUFFERED)

    def do_expose_event(self, event):
        if self.imagesink:
            self.imagesink.expose()
            return False
        else:
            return True

    def set_sink(self, sink):
        assert self.window.xid
        self.imagesink = sink
        self.imagesink.set_xwindow_id(self.window.xid)

class MaemoGstView:

    def __init__(self):
        if os.path.exists("/dev/video1"):
            self.model = 'N900'
        else:
            self.model = 'N8x0'
	    
	self.zoomtoggle = False
	self.camtoggle = False
	self.restoggle = False
            
        # hildon has one program instance per app, so get instance
        self.p = hildon.Program.get_instance()
        # set name of application: this shows in titlebar
        gtk.set_application_name("Mirror")
        # stackable window in case we want more windows in future in app
        self.w = hildon.StackableWindow()
        self.l = gtk.Label("No option selected")
        menu = self.create_menu(self.l)
        self.w.set_app_menu(menu)
        box = gtk.VBox()
        self.video_widget = VideoWidget()
        # video widget we want to expand to size
        box.pack_start(self.video_widget, True, True, 0)
        # a button finger height to play/pause 
        self.button = hildon.Button(gtk.HILDON_SIZE_FINGER_HEIGHT,
            hildon.BUTTON_ARRANGEMENT_VERTICAL, title="Pause")
        self.button.connect_after("clicked", self.on_button_clicked)
        
        self.w.connect("window-state-event", self.on_window_state_change) 
        self.window_in_fullscreen = False   
        
        self.video_widget.connect_after("button-press-event", self.on_img_clicked)
#        g_signal_connect (G_OBJECT (self.video_widget), "expose_event",
#                    G_CALLBACK (self.on_button_clicked), NULL);
        self.video_widget.add_events(gtk.gdk.BUTTON_PRESS_MASK)
        # don't want button to expand or fill, just stay finger height
#        box.pack_start(self.button, False, False, 0)
        self.w.add(box)
        self.w.connect("destroy", self.destroy)
        self.w.connect("delete-event", gtk.main_quit)
        self.p.add_window(self.w)
        self.w.show_all()
        self.start_streaming()
        
    def menu_button_clicked(self, button, label):
        buttontext = button.get_label()
        if buttontext == "Toggle camera":
            self.camtoggle = not self.camtoggle
	elif buttontext == "Toggle wide":
            self.restoggle = not self.restoggle
	elif buttontext == "Toggle zoom":
            self.zoomtoggle = not self.zoomtoggle
	    
        print >>sys.stderr, "Button clicked: %s" % buttontext
	self.destroy(None)
	self.start_streaming()


    def create_menu(self, label):
        menu = hildon.AppMenu()
   
        options = ["Toggle zoom", "Toggle wide"]
#        if self.model == 'N900':
#            options.append("Toggle camera")
        
        for i in options:
            # Create menu entries
            button = hildon.GtkButton(gtk.HILDON_SIZE_AUTO)
            command_id = i
            button.set_label(command_id)
    
            # Attach callback to clicked signal
            button.connect("clicked", self.menu_button_clicked, label)
    
            # Add entry to the view menu
            menu.append(button)
   
        menu.show_all()
   
        return menu
 
    def start_streaming(self):
        if self.model == 'N900' and not self.camtoggle:
            devno = '1'
        else:
            devno = '0'
        
	if self.zoomtoggle and self.restoggle:
	    zoom = "videocrop top=160 left=160 right=160 bottom=160 !"
	elif self.restoggle:
	    zoom = "videocrop top=60 bottom=60 !"
	elif self.zoomtoggle:
	    zoom = "videocrop top=120 left=160 right=160 bottom=120 !"
	else:
	    zoom = ''
	    
        # we use ximagesink solely for screenshotting ability
        # less cpu usage would happen with videotestsrc ! xvimagesink
        self.pipeline = \
            gst.parse_launch("v4l2src device=/dev/video%s ! ffmpegcolorspace ! %s gamma gamma=2.0 ! videoflip method=4 ! xvimagesink" % (devno, zoom))
            
        bus = self.pipeline.get_bus()
        # need to connect to sync message handler so we get the sink to be
        # embedded at the right time and not have a temporary new window
        bus.enable_sync_message_emission()
        bus.add_signal_watch()
        bus.connect("sync-message::element", self.on_sync_message)
        bus.connect("message", self.on_message)
        self.pipeline.set_state(gst.STATE_PLAYING)

    def destroy(self, widget, data=None):
	# it is important to stop pipeline so there will be no
	# X-related errors when window is destroyed before the video sink
	self.pipeline.set_state(gst.STATE_NULL)

    def on_sync_message(self, bus, message):
        if message.structure is None:
            return
        if message.structure.get_name() == 'prepare-xwindow-id':
            # all this is needed to sync with the X server before giving the
            # x id to the sink
            gtk.gdk.threads_enter()
            gtk.gdk.display_get_default().sync()
            self.video_widget.set_sink(message.src)
            message.src.set_property("force-aspect-ratio", True)
            gtk.gdk.threads_leave()

    def on_message(self, bus, message):
        if message.type == gst.MESSAGE_ERROR:
            err, debug = message.parse_error()
            hildon.hildon_banner_show_information(self.w, '', 
                "Error: %s" % err)

            
    def on_window_state_change(self, widget, event, *args): 
        if event.new_window_state & gtk.gdk.WINDOW_STATE_FULLSCREEN: 
            self.window_in_fullscreen = True 
        else: 
            self.window_in_fullscreen = False 
      
    def on_img_clicked(self, widget, button):
        print >>sys.stderr, "imgclick"
        success, state, pending = self.pipeline.get_state(1)
        # do not listen if in middle of state change
        
        if self.window_in_fullscreen: 
            self.w.unfullscreen () 
        else: 
            self.w.fullscreen () 
        
    def on_button_clicked(self, widget):
        success, state, pending = self.pipeline.get_state(1)
        # do not listen if in middle of state change
        if not pending:
            if state == gst.STATE_PLAYING:
                self.pipeline.set_state(gst.STATE_PAUSED)
                self.button.set_label("Play")
            else:
                self.pipeline.set_state(gst.STATE_PLAYING)
                self.button.set_label("Pause")

def main():
    view = MaemoGstView()
    gtk.main()

if __name__ == '__main__':
    main()
    
#!/bin/sh
#gst-launch-0.10 v4l2src device=/dev/video1 ! ffmpegcolorspace ! gamma gamma=2.0 ! videoflip method=4 ! autovideosink
