#!/usr/bin/env python

import pygtk
pygtk.require ("2.0")
import gobject
gobject.threads_init()

import pygst
pygst.require('0.10')
import gst

import sys

import counter_render
from counter_audio import PyAudioBeep

WIDTH, HEIGHT = 640, 480
FRAMERATE_N = 2396
FRAMERATE_D = 100
FRAMES = 800

class PyCountClock(gst.Element):
    _sinkpadtemplate = gst.PadTemplate ("sink",
                                         gst.PAD_SINK,
                                         gst.PAD_ALWAYS,
                                         gst.caps_from_string ("video/x-raw-rgb,bpp=32,depth=32,blue_mask=-16777216,green_mask=16711680, red_mask=65280, alpha_mask=255,width=[ 1, 2147483647 ],height=[ 1, 2147483647 ],framerate=[ 0/1, 2147483647/1 ]"))
    _srcpadtemplate = gst.PadTemplate ("src",
                                         gst.PAD_SRC,
                                         gst.PAD_ALWAYS,
                                         gst.caps_from_string ("video/x-raw-rgb,bpp=32,depth=32,blue_mask=-16777216,green_mask=16711680, red_mask=65280, alpha_mask=255,width=[ 1, 2147483647 ],height=[ 1, 2147483647 ],framerate=[ 0/1, 2147483647/1 ]"))

    def __init__(self):
        gst.Element.__init__(self)

        self.sinkpad = gst.Pad(self._sinkpadtemplate, "sink")
        self.sinkpad.set_chain_function(self.chainfunc)
        self.sinkpad.set_event_function(self.eventfunc)
        self.sinkpad.set_getcaps_function(gst.Pad.proxy_getcaps)
        self.sinkpad.set_setcaps_function(gst.Pad.proxy_setcaps)
        self.add_pad (self.sinkpad)

        self.srcpad = gst.Pad(self._srcpadtemplate, "src")

        self.srcpad.set_event_function(self.srceventfunc)
        self.srcpad.set_query_function(self.srcqueryfunc)
        self.srcpad.set_getcaps_function(gst.Pad.proxy_getcaps)
        self.srcpad.set_setcaps_function(gst.Pad.proxy_setcaps)
        self.add_pad (self.srcpad)

    def chainfunc(self, pad, buffer):
        try:
            outbuf = buffer.copy_on_write ()
            counter_render.draw_on (outbuf)
            return self.srcpad.push (outbuf)
        except:
            return GST_FLOW_ERROR

    def eventfunc(self, pad, event):
        return self.srcpad.push_event (event)
        
    def srcqueryfunc (self, pad, query):
        return self.sinkpad.query (query)
    def srceventfunc (self, pad, event):
        return self.sinkpad.push_event (event)

def on_new_decoded_pad (element, pad, last):
    global cf
    try:
       if not pad.link (cf.get_pad ('sink')):
          pad.link (ac.get_pad ('sink'))
    except:
       try:
          pad.link (ac.get_pad ('sink'))
       except:
          pass

gobject.type_register(PyCountClock)

if __name__ == '__main__':
    pipe = gst.Pipeline()
    
    if len(sys.argv) > 1:
        src = gst.element_factory_make ("filesrc")
        fname = sys.argv[1]
        src.set_property ("location", fname)
        db = gst.element_factory_make ("decodebin")
        cf = gst.element_factory_make ("ffmpegcolorspace")
    else:
        src = gst.element_factory_make ("videotestsrc")
        src.set_property ("num-buffers", FRAMES)
        cf = gst.element_factory_make ("capsfilter")
        caps = gst.caps_from_string ("video/x-raw-rgb,width=%d,height=%d,framerate=%d/%d" % (WIDTH, HEIGHT, FRAMERATE_N, FRAMERATE_D))
        cf.set_property ("caps", caps)
        db = None
    
    c1 = PyCountClock()
    color = gst.element_factory_make ("ffmpegcolorspace")
    scale = gst.element_factory_make ("videoscale")
    q1 = gst.element_factory_make ("queue")
    sink = gst.element_factory_make ("autovideosink")
    
    ac = gst.element_factory_make ("audioconvert")
    a1 = PyAudioBeep()
    ac2 = gst.element_factory_make ("audioconvert")
    resamp = gst.element_factory_make ("audioresample")
    asink = gst.element_factory_make ("autoaudiosink")
    
    if db is not None:
        pipe.add (src, db, cf, c1, q1, color, scale, sink)
        pipe.add (ac, a1, ac2, resamp, asink)
 
        gst.element_link_many (src, db)
        gst.element_link_many (cf, c1, q1, color, scale, sink)
        gst.element_link_many (ac, a1, ac2, resamp, asink)

        db.connect ('new-decoded-pad', on_new_decoded_pad)
    else:
        asrc = gst.element_factory_make ("audiotestsrc")
        asrc.set_property ("wave", 4)
        asrc.set_property ("num-buffers", (44100 * FRAMES * FRAMERATE_D) / (FRAMERATE_N * 1024))
    
        pipe.add (src, cf, c1, q1, color, scale, sink)
        pipe.add (asrc, ac, a1, ac2, resamp, asink)
        gst.element_link_many (src, cf, c1, q1, color, scale, sink)
        gst.element_link_many (asrc, ac, a1, ac2, resamp, asink)
    
    def on_eos (bus, msg):
        mainloop.quit()
    
    bus = pipe.get_bus()
    bus.add_signal_watch()
    bus.connect('message::eos', on_eos)
    
    pipe.set_state (gst.STATE_PLAYING)
    
    mainloop = gobject.MainLoop()
    try:
        mainloop.run()
    except:
        pass
    
    pipe.set_state (gst.STATE_NULL)
    pipe.get_state (gst.CLOCK_TIME_NONE)
