#!/usr/bin/env python

import gst
import sys
import traceback
import cairo
from math import pi, cos, sin

frame_no = 1

def draw_on(buf):
    global frame_no

    # Setup Cairo
    try:
        full_ts = (float (buf.timestamp) / gst.SECOND)
        ts = full_ts % 2.0

        caps = buf.get_caps()
        width = caps[0]['width']
        height = caps[0]['height']
        framerate = caps[0]['framerate']
        surface = cairo.ImageSurface.create_for_data (buf, cairo.FORMAT_ARGB32, width, height, 4 * width)
        ctx = cairo.Context(surface)

        # fps is the number of frames between the start of the current 
        # sec and the start of the next
        cur_sec = buf.timestamp / gst.SECOND
        start_frame = int (framerate.num * cur_sec / framerate.denom)
        end_frame = int (framerate.num * (cur_sec + 1) / framerate.denom)
        start_ts = float (start_frame * framerate.denom) / framerate.num
        end_ts = float (end_frame * framerate.denom) / framerate.num
        if start_ts < cur_sec:
          start_frame += 1
        if end_ts >= cur_sec + 1:
          end_frame -= 1
        fps = end_frame - start_frame + 1
        cur_frame = (buf.timestamp * framerate.num + (gst.SECOND * framerate.denom)/2) / (gst.SECOND * framerate.denom)
    except:
        print "Failed to create cairo surface for buffer"
        traceback.print_exc()
        return

    #start_ts = float (start_frame * framerate.denom) / framerate.num
    #end_ts = float (end_frame * framerate.denom) / framerate.num
    #print "TS %f frame %d in %d to %d (%f to %f) (%d frames)\n" % (full_ts, cur_frame, start_frame, end_frame, start_ts, end_ts, fps)
    
    cur_frame = cur_frame - start_frame + 1 
    try:
      radius = float (min (width, height)) * 0.15
      center_x = min (24 + radius, width/4)
      center_y = max (height - 24 - radius, 3*height/4)

      # draw a circle
      ctx.set_source_rgba (0.0, 0.0, 0.0, 0.9)
      ctx.move_to (width/2,height/2)
      ctx.arc (center_x, center_y, radius, 0, 2.0*pi)
      ctx.close_path()
      ctx.fill()
      
      # draw the time arc
      if ts <= 1.0:
        start = 0
        end = ts * 2 * pi
      else:
        start = 2*pi + ts * 2 * pi
        end = 2*pi

      start -= pi/2
      end -= pi/2
      
      ctx.set_source_rgba (1.0, 0.0, 0.0, 0.7)
      ctx.move_to (center_x, center_y)
      ctx.arc (center_x, center_y, radius, start, end)
      ctx.close_path()
      ctx.fill()
      
      # Draw dial outline

      # Set thickness of brush
      ctx.set_line_width(0.05 * radius)
    
      ctx.set_source_rgba (1.0, 1.0, 1.0, 1.0)
      ctx.arc (center_x, center_y, radius, 0, 2.0*pi)
      ctx.close_path()
      ctx.stroke()

      # draw 'fps' tick-marks around the dial
      cur = -pi/2
      end = 3*pi/2
      while cur < end:
          ctx.move_to (center_x + radius * cos (cur), center_y + radius * sin(cur))
          ctx.line_to (center_x+ 0.9 * radius * cos (cur), center_y + 0.9*radius * sin (cur))
          ctx.stroke()
          cur += (2*pi)/fps

      # Write seconds count in the center
      secs = int (full_ts)
      ctx.set_font_size(radius)
      txt = "%d" % (secs)
      extents = ctx.text_extents (txt)
      ctx.move_to(center_x - (extents[2]/2) - 0.05 * radius, center_y + (extents[3]/2) - 0.2 * radius)
      ctx.text_path(txt)
      ctx.close_path()
      ctx.set_source_rgba (1.0, 1.0, 1.0, 1.0)
      ctx.fill()
      ctx.set_line_width(0.05)
      ctx.move_to(center_x - (extents[2]/2) - 0.05 * radius, center_y + (extents[3]/2) - 0.2 * radius)
      ctx.text_path(txt)
      ctx.set_source_rgba (0.0, 0.0, 0.0, 1.0)
      ctx.stroke()

      ctx.set_font_size(0.3 * radius)
      txt = "%d/%d" % (cur_frame, fps)
      extents = ctx.text_extents (txt)
      ctx.move_to(center_x - extents[2]/2, center_y + extents[3]/2 + 0.5 * radius)
      ctx.text_path(txt)
      ctx.set_source_rgba (1.0, 1.0, 1.0, 1.0)
      ctx.fill()
      ctx.move_to(center_x - extents[2]/2, center_y + extents[3]/2 + 0.5 * radius)
      ctx.text_path(txt)
      ctx.set_source_rgba (0.0, 0.0, 0.0, 1.0)
      ctx.stroke()
    except:
        print "Failed cairo render"
        traceback.print_exc()
        return

    try:
      # surface.write_to_png("render/%04d.png" % (frame_no))
      frame_no += 1
    except:
        print "Failed to write output"
        traceback.print_exc()
        return
