#!/usr/bin/env python
# GdkX11 to get access to xid, GstVideo to get access to set_window_handle
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('Gst', '1.0')
gi.require_version('GstVideo', '1.0')
from gi.repository import Gtk, Gst, GstVideo, GdkX11
import signal

settings = Gtk.Settings.get_default()
settings.props.gtk_button_images = True

class Main:
    def __init__(self):

        # Create gui bits and bobs

        self.mainwindow = Gtk.Builder()
        self.mainwindow.add_from_file("stream.glade")

        signals = {
            "on_stream_clicked" : self.OnStream,
            "on_stop_clicked" : self.OnStop,
            "on_quit_clicked" : self.OnQuit,
        }

        self.mainwindow.connect_signals(signals)

        # Create GStreamer bits and bobs

        # Initiate the pipeline
        Gst.init(None)
        self.pipeline = Gst.Pipeline("mypipeline")

        # Add our video source, the first v4l2 device we can find
        self.videosrc = Gst.ElementFactory.make("v4l2src", "videosource")
        self.pipeline.add(self.videosrc)

        # Add a jpeg decoder to force the v4l2src to output jpeg data
        self.jpegdec = Gst.ElementFactory.make("jpegdec", "jpegdec")
        self.pipeline.add(self.jpegdec)
        self.videosrc.link(self.jpegdec)

        # Add some video convert magic
        self.videoconvert = Gst.ElementFactory.make("videoconvert", "videoconvert")
        self.pipeline.add(self.videoconvert)
        self.jpegdec.link(self.videoconvert)

        # Add a videosink element to the pipeline
        self.videosink = Gst.ElementFactory.make("autovideosink", "videosink")
        self.videosink.set_property("sync", False)
        self.pipeline.add(self.videosink)
        self.videoconvert.link(self.videosink)

        # Start playing
        self.pipeline.set_state(Gst.State.PLAYING)

        # Set up a bus to our pipeline to get notified when the video is ready
        self.bus = self.pipeline.get_bus()
        self.bus.enable_sync_message_emission()
        self.bus.connect("sync-message::element", self.OnSyncElement)

        # Summon the window and connect the window's close button to quit
        self.window = self.mainwindow.get_object("mainwindow")
        self.window.connect("delete-event", Gtk.main_quit)
        self.window.show_all()

        # Get window ID of the viewport widget from the GUI
        self.win_id = self.mainwindow.get_object("viewport").get_window().get_xid()


    # When we get a message that video is ready to display, set the
    # correct window id to hook it to our viewport
    def OnSyncElement(self, bus, message):
        if message.get_structure().get_name() == "prepare-window-handle":
            print "prepare-window-handle"
            message.src.set_window_handle(self.win_id)

    def OnStream(self, widget):
        print "stream"
        self.pipeline.set_state(Gst.State.PLAYING)

    def OnStop(self, widget):
        print "stop"
        self.pipeline.set_state(Gst.State.READY)

    def OnQuit(self, widget):
        print "quit"
        Gtk.main_quit()

    # Workaround to get Ctrl+C to terminate from command line
    # ref: https://bugzilla.gnome.org/show_bug.cgi?id=622084#c12
    signal.signal(signal.SIGINT, signal.SIG_DFL)

start = Main()
Gtk.main()
