/* 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.txt," in this distribution.  */

#include "m_imp.h"
#ifdef UNIX
#include <unistd.h>
#include <sys/time.h>
#ifndef __linux__
#include <bstring.h>
#endif
#endif
#ifdef NT
#include <winsock.h>
#include <sys/types.h>
#include <sys/timeb.h>
#endif
#include <string.h>
#include <stdio.h>
#include <signal.h>

#ifdef UNIX
int sys_signal(int signo, t_sighandler sigfun)
{
    struct sigaction action;
    action.sa_flags = 0;
    action.sa_handler = SIG_IGN;
    memset(&action.sa_mask, 0, sizeof(action.sa_mask));
    return (sigaction(signo, &action, 0) < 0);
}
#endif

void sys_gettime(t_systime *st)
{
#ifdef UNIX
    struct timeval now;
    gettimeofday(&now, 0);
    st->st_sec = now.tv_sec;
    st->st_microsec = now.tv_usec;
#endif
#ifdef NT
    struct _timeb now;
    _ftime(&now);
    st->st_sec = now.time;
    st->st_microsec = now.millitm * 1000;
#endif
}

int sys_microsecsince(t_systime *st)
{
    int foo;
    t_systime stnow;
    sys_gettime(&stnow);
    if (stnow.st_sec > st->st_sec + 1000) return (0x7fffffff);
    else return (1000000 * (stnow.st_sec - st->st_sec) +
    	stnow.st_microsec - st->st_microsec);
}

double sys_secsince(t_systime *st)
{
    int foo;
    t_systime stnow;
    sys_gettime(&stnow);
    if (stnow.st_sec > st->st_sec + 1000000) return (0x7fffffff);
    else return (1. * (stnow.st_sec - st->st_sec) +
    	(0.000001 * (stnow.st_microsec - st->st_microsec)));
}

/* LATER do something with this */
#if 0
static void sys_virtalarmhandler(int n)
{
    fprintf(stderr, "Pd died due to timeout\n");
    fflush(stderr);
    exit(0);
}

void sys_setvirtualalarm(int sec)
{
    struct itimerval gonzo,  bonzo;
    gonzo.it_interval.tv_sec = 0;
    gonzo.it_interval.tv_usec = 0;
    gonzo.it_value.tv_sec = sec;
    gonzo.it_value.tv_usec = 0;
    	/* this looks like overkill: */
    sys_signal(SIGVTALRM, sys_virtalarmhandler);
    setitimer(ITIMER_VIRTUAL, &gonzo, &bonzo);
    sys_signal(SIGVTALRM, sys_virtalarmhandler);
}
#endif

#define MIDI_NOTEON 144
#define MIDI_POLYAFTERTOUCH 160
#define MIDI_CONTROLCHANGE 176
#define MIDI_PROGRAMCHANGE 192
#define MIDI_AFTERTOUCH 208
#define MIDI_PITCHBEND 224

void sys_putmidimess(int portno, int a, int b, int c);

void outmidi_noteon(int portno, int channel, int pitch, int velo)
{
    if (pitch < 0) pitch = 0;
    else if (pitch > 127) pitch = 127;
    if (velo < 0) velo = 0;
    else if (velo > 127) velo = 127;
    sys_putmidimess(portno, MIDI_NOTEON + (channel & 0xf), pitch, velo);
}

void outmidi_controlchange(int portno, int channel, int ctl, int value)
{
    if (ctl < 0) ctl = 0;
    else if (ctl > 127) ctl = 127;
    if (value < 0) value = 0;
    else if (value > 127) value = 127;
    sys_putmidimess(portno, MIDI_CONTROLCHANGE + (channel & 0xf), ctl, value);
}

void outmidi_programchange(int portno, int channel, int value)
{
    if (value < 0) value = 0;
    else if (value > 127) value = 127;
    sys_putmidimess(portno, MIDI_PROGRAMCHANGE + (channel & 0xf), value, 0);
}

void outmidi_pitchbend(int portno, int channel, int value)
{
    if (value < 0) value = 0;
    else if (value > 16383) value = 16383;
    sys_putmidimess(portno, MIDI_PITCHBEND + (channel & 0xf),
    	(value & 127), ((value>>7) & 127));
}

void outmidi_aftertouch(int portno, int channel, int value)
{
    if (value < 0) value = 0;
    else if (value > 127) value = 127;
    sys_putmidimess(portno, MIDI_AFTERTOUCH + (channel & 0xf), value, 0);
}

void outmidi_polyaftertouch(int portno, int channel, int pitch, int value)
{
    if (pitch < 0) pitch = 0;
    else if (pitch > 127) pitch = 127;
    if (value < 0) value = 0;
    else if (value > 127) value = 127;
    sys_putmidimess(portno, MIDI_POLYAFTERTOUCH + (channel & 0xf),
    	pitch, value);
}



