/* Copyright (c) 1997 The Regents of the University of California.
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.TERMS," in this distribution.  */

/* code for profile pd class */

#include "m_pd.h"
#include <sys/time.h>
#include <sys/times.h>
#include <sys/param.h>

typedef struct profile
{
    t_object x_ob;
    double x_settime;
    struct timeval x_setrealtime;
    struct tms x_setcputime;
    t_outlet *x_realout;
    t_outlet *x_cpuout;
    t_outlet *x_logicalout;
} t_profile;

static void profile_bang(t_profile *x)
{
    float elapsedlogical = clock_gettimesince(x->x_settime);
    float elapsedreal, elapsedcpu;
    struct tms newcputime;
    struct timeval newrealtime;
    struct timezone tz;

    gettimeofday(&newrealtime, &tz); 
    times(&newcputime);

    elapsedcpu = 1000 * (
    	newcputime.tms_utime + newcputime.tms_stime -
	    x->x_setcputime.tms_utime - x->x_setcputime.tms_stime) / HZ;
    elapsedreal = 1000 * (newrealtime.tv_sec - x->x_setrealtime.tv_sec) +
	(newrealtime.tv_usec - x->x_setrealtime.tv_usec) / 1000;

    outlet_float(x->x_realout, elapsedreal);
    outlet_float(x->x_cpuout, elapsedcpu);
    outlet_float(x->x_logicalout, elapsedlogical);
    
    x->x_settime = clock_getsystime();
    x->x_setcputime = newcputime;
    x->x_setrealtime = newrealtime;
}

void profile_free() { }

t_class *profile_class;

void *profile_new()
{
    t_profile *x = (t_profile *)pd_new(profile_class);
    struct timezone tz;
    
    x->x_realout = outlet_new(&x->x_ob, &s_float);
    x->x_cpuout = outlet_new(&x->x_ob,  &s_float);
    x->x_logicalout = outlet_new(&x->x_ob,  &s_float);
    x->x_settime = clock_getsystime();
    times(&x->x_setcputime);
    gettimeofday(&x->x_setrealtime, &tz);
    return (void *)x;
}

profile_setup()
{
    profile_class = class_new(gensym("profile"), profile_new, 0,
    	sizeof(t_profile), 0, 0);
    class_addbang(profile_class, profile_bang);
}

