/* 
 * Real-Time and Multimedia Systems Laboratory
 * Copyright (c) 2000 Carnegie Mellon University
 * All Rights Reserved.
 * 
 * Permission to use, copy, modify and distribute this software and its
 * documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 * 
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 * 
 * Carnegie Mellon requests users of this software to return to
 * 
 *  Real-Time and Multimedia Systems Laboratory
 *  Attn: Prof. Raj Rajkumar
 *  Electrical and Computer Engineering, and Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 *
 *  or via email to raj@ece.cmu.edu
 * 
 * any improvements or extensions that they make and grant Carnegie Mellon
 * the rights to redistribute these changes.
 */
/*			program developed by Luca Abeni
 *					luca@sssup.it
 *					http://hartik.sssup.it/~luca
 */


#include <gtk/gtk.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <wait.h>
#include <signal.h>

#include <mpeg.h>

#include <rk/rk.h>
#include <rk/rk_error.h>
#include <rk/posix_timers.h>
#include <rk/timespec.h>

#include <arch/local.h>
#include "qos.h"

static GdkPixmap *screen;
static GdkGC *gc, *gc1;

static unsigned long long int timevect[10000];
static unsigned long int timevect1[10000];
static unsigned long int timevect2[10000];

static int end = 0;

extern gint ac;
extern gchar *av[];

#define MAXSLIDE 500

gint delete_event(GtkWidget * widget, GdkEvent * event, gpointer data)
{
    end = 1;

    return (TRUE);
}

gboolean expose_event(GtkWidget * widget, GdkEventExpose * event,
		      gpointer data)
{
    if ((screen != NULL) && (!end)) {
	gdk_draw_pixmap(widget->window,
			widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
			screen, event->area.x, event->area.y,
			event->area.x, event->area.y, event->area.width,
			event->area.height);
    }

    return TRUE;
}

gint configure_event(GtkWidget * widget, GdkEventConfigure * event)
{
    if (!screen) {
	screen =
	    gdk_pixmap_new(widget->window, widget->allocation.width,
			   widget->allocation.height, -1);
	gdk_draw_rectangle(screen, widget->style->white_gc, TRUE, 0, 0,
			   widget->allocation.width,
			   widget->allocation.height);
    }
    return TRUE;
}

//gint mpdbody(gint argc, gchar *argv[])
gint mpbody(int num)
{
    gint argc;
    gchar **argv;
    GtkWidget *prbar;
    GtkWidget *d_area;
    GtkWidget *window;
    GtkWidget *vbox;
    GtkWidget *hbox;
    GtkWidget *label;
    GtkObject *adj2;
    GdkColor black;
    GdkColor white;
    GdkRectangle u_area;
    char buff[80];
    int x, y, ox, oy, dir;
    gint expid, confid;
    long int l;
    FILE *mpeg;
    int moreframes;
    ImageDesc img;
    unsigned char *rgbbuff;

    struct timespec now;
    FILE *f;
    char filename[20];
    int i;

    argc = ac;
    argv = av;
    gtk_init(&argc, &argv);
    if (argc != 2) {
	printf("Gimme the file name, please!!!\n");
	exit(-1);
    }

    mpeg = fopen(argv[1], "rb");
    if (mpeg == NULL) {
	perror("Error opening:");
	exit(-1);
    }
    SetMPEGOption(MPEG_DITHER, FULL_COLOR_DITHER);
    if (!OpenMPEG(mpeg, &img)) {
	fprintf(stderr, "OpenMPEG on %s failed\n", argv[1]);
	exit(-1);
    }
    rgbbuff = malloc(img.Size * sizeof(char));
    printf("Image: %dx%dx%d\n", img.Width, img.Height, img.Depth);

    gdk_rgb_init();
    gtk_widget_set_default_colormap(gdk_rgb_get_cmap());
    gtk_widget_set_default_visual(gdk_rgb_get_visual());

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_default_size(GTK_WINDOW(window), img.Width,
				img.Height + 50);

    vbox = gtk_vbox_new(FALSE, 0);
    hbox = gtk_hbox_new(FALSE, 0);
    gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(vbox));


    adj2 = gtk_adjustment_new(0.0, 0.0, 21.0, 0.1, 1.0, 1.0);
    prbar = gtk_progress_bar_new_with_adjustment(GTK_ADJUSTMENT(adj2));
    gtk_box_pack_start(GTK_BOX(vbox), prbar, TRUE, TRUE, 0);
    gtk_widget_show(prbar);
//drawing area
    d_area = gtk_drawing_area_new();
    gtk_drawing_area_size(GTK_DRAWING_AREA(d_area), img.Width, img.Height);
    expid =
	gtk_signal_connect(GTK_OBJECT(d_area), "expose_event",
			   GTK_SIGNAL_FUNC(expose_event), NULL);
    confid =
	gtk_signal_connect(GTK_OBJECT(d_area), "configure_event",
			   GTK_SIGNAL_FUNC(configure_event), NULL);
    gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(d_area), FALSE, FALSE, 5);
    gtk_widget_show(d_area);

    sprintf(buff, "QoSlib Demo");
    label = gtk_label_new(buff);
    gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label), FALSE, FALSE, 5);
    gtk_widget_show(label);

    gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, FALSE, 5);

    gtk_widget_show(hbox);
    gtk_widget_show(vbox);
    gtk_widget_show(window);
    gtk_signal_connect(GTK_OBJECT(window), "delete_event",
		       GTK_SIGNAL_FUNC(delete_event), NULL);

    u_area.x = 0;
    u_area.y = 0;
    u_area.width = d_area->allocation.width;
    u_area.height = d_area->allocation.height;
    gc = gdk_gc_new(d_area->window);
    gc1 = gdk_gc_new(d_area->window);

    gdk_color_black(gdk_colormap_get_system(), &black);
    gdk_color_white(gdk_colormap_get_system(), &white);
    gdk_gc_set_foreground(gc, &black);
    gdk_gc_set_background(gc, &white);
    gdk_gc_set_foreground(gc1, &white);
    gdk_gc_set_background(gc1, &black);

    x = 60;
    y = 60;
    ox = x;
    oy = y;
    dir = 10;
    i = 0;

    cprintf("Starting...\n");
    rt_wait_for_start_time();
    while (!end) {
	clock_gettime(CLOCK_REALTIME, &now);
	timevect[i] = now.tv_nsec / 1000 + now.tv_sec * 1000000;
#ifdef VIDEO
	while (gtk_events_pending()) {
	    gtk_main_iteration_do(FALSE);
	}
#endif
	if (gtk_events_pending()) {
	    gtk_main_iteration_do(FALSE);
	}
	if (!end) {
	    moreframes = GetMPEGFrame(rgbbuff);
	    if (moreframes == 0) {
		end = 1;
	    }
	    gdk_draw_rgb_32_image(screen, gc,
				  0, 0, img.Width, img.Height,
				  GDK_RGB_DITHER_MAX, rgbbuff,
				  img.Width * 4);
	    gtk_widget_draw(GTK_WIDGET(d_area), &u_area);
	}
	l = howlate(0);
	timevect2[i] = l;
	l = l / 33000;
	if (l > MAXSLIDE) {
	    l = MAXSLIDE;
	}
	gtk_progress_bar_update(GTK_PROGRESS_BAR(prbar),
				(float) l / (float) MAXSLIDE);

	clock_gettime(CLOCK_REALTIME, &now);
	timevect1[i++] = now.tv_nsec / 1000 + now.tv_sec * 1000000;
	qtask_endcycle();

    }
    CloseMPEG();
    fclose(mpeg);
    free(rgbbuff);

    printf("Saving\n");
    sprintf(filename, "res_%d_if.tim", num);
    f = fopen(filename, "w");
    for (i = 1; i < 5000; i++) {
	if (timevect1[i] != 0) {
	    if (timevect[i] < timevect[i - 1]) {
		timevect[i] = timevect[i - 1];
//              fprintf(f, "%d\t-1\t%lu\n", i, (unsigned long int)timevect[i] /*- timevect[0]*/);
	    } else {
		if (timevect[i - 1] != timevect[i - 2]) {
		    fprintf(f, "%d\t%lu\t%lu\n", i,
			    (unsigned long int) (timevect[i] -
						 timevect[i - 1]),
			    (unsigned long int) timevect[i]
			    /*- timevect[0]*/
			);
		}
	    }
	}
    }
    sprintf(filename, "res_%d_ct.tim", num);
    f = fopen(filename, "w");
    for (i = 1; i < 500; i++) {
	if (timevect1[i] != 0) {
	    fprintf(f, "%d\t%lu\t1\n", i,
		    (unsigned long int) (timevect1[i] - timevect[i]));
	}
    }
    sprintf(filename, "res_%d_l.tim", num);
    f = fopen(filename, "w");
    for (i = 1; i < 500; i++) {
	fprintf(f, "%d\t%lu\n", i, timevect2[i]);
    }

    fclose(f);

    cprintf("Returning\n");
    return 1;
}
