/* Automatically generated from Squeak on #(16 January 2001 1:51:05 pm) */

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

/* Default EXPORT macro that does nothing (see comment in sq.h): */
#define EXPORT(returnType) returnType

/* Do not include the entire sq.h file but just those parts needed. */
/*  The virtual machine proxy definition */
#include "sqVirtualMachine.h"
/* Configuration options */
#include "sqConfig.h"
/* Platform specific definitions */
#include "sqPlatformSpecific.h"

#define true 1
#define false 0
#define null 0  /* using 'null' because nil is predefined in Think C */

/* memory access macros */
#define byteAt(i) (*((unsigned char *) (i)))
#define byteAtput(i, val) (*((unsigned char *) (i)) = val)
#define longAt(i) (*((int *) (i)))
#define longAtput(i, val) (*((int *) (i)) = val)

/*** Variables ***/
struct VirtualMachine* interpreterProxy;
const char *moduleName = "SirenMIDIPlugin 16 January 2001 (e)";

/*** Function Prototypes ***/
#pragma export on
EXPORT(int) closeMIDI(void);
EXPORT(int) getMIDIDeviceName(void);
EXPORT(const char*) getModuleName(void);
EXPORT(int) ioctlMIDI(void);
EXPORT(int) openMIDI(void);
EXPORT(int) putMIDIOn(void);
EXPORT(int) readMIDIControl(void);
EXPORT(int) readMIDIPacket(void);
EXPORT(int) setInterpreter(struct VirtualMachine* anInterpreter);
#pragma export off


/*	Shutdown and close the MIDI interface. */
/*	MIDIPort primCloseMIDI */
/*	int sqCloseMIDI (void) */

EXPORT(int) closeMIDI(void) {
    int err;

	err = sqCloseMIDI ();
	if (interpreterProxy->failed()) {
		return null;
	}
	interpreterProxy->pop(1);
	interpreterProxy->push(((err << 1) | 1));
}


/*	Answer the name of the given MIDI interface. */
/*	MIDIPort primitiveGetMIDIInterfaceName: index into: nameString */
/*	int sqGetMIDIDeviceName(int index, int name) */

EXPORT(int) getMIDIDeviceName(void) {
    int answer;
    int index;
    int name;

	name = interpreterProxy->stackValue(0);
	index = interpreterProxy->stackIntegerValue(1);
	interpreterProxy->success(interpreterProxy->isBytes(name));
	if (interpreterProxy->failed()) {
		return null;
	}
	answer = sqGetMIDIDeviceName(index, name + 4);
	if (interpreterProxy->failed()) {
		return null;
	}
	interpreterProxy->pop(3);
	interpreterProxy->push(((answer << 1) | 1));
}


/*	Note: This is hardcoded so it can be run from Squeak.
	The module name is used for validating a module *after*
	it is loaded to check if it does really contain the module
	we're thinking it contains. This is important! */

EXPORT(const char*) getModuleName(void) {
	return moduleName;
}


/*	Perform a MIDI Driver state query or set/clear. */
/*	MIDIPort primMIDIIoctl: selector do: argument */
/*	int sqMIDIioctl(int which, int onOff); */

EXPORT(int) ioctlMIDI(void) {
    int answer;
    int which;
    int toggle;

	which = interpreterProxy->stackIntegerValue(1);

	/* Call the primitive */

	toggle = interpreterProxy->stackIntegerValue(0);
	answer = sqMIDIioctl (which, toggle);
	if (interpreterProxy->failed()) {
		return null;
	}
	interpreterProxy->pop(3);
	if (toggle == 0) {
		if (answer == 0) {
			interpreterProxy->push(interpreterProxy->falseObject());
		} else {
			interpreterProxy->push(interpreterProxy->trueObject());
		}
	} else {
		interpreterProxy->push(((answer << 1) | 1));
	}
}


/*	Open and setup the MIDI interface. */
/*	MIDIPort primOpenMIDI: theReadSemaphore socket: inputSocket */
/*	int sqOpenMIDI (int callBackSemaphore, int socket) */

EXPORT(int) openMIDI(void) {
    int theMRSemaphore;
    int theMRSocket;
    int answer;

	theMRSemaphore = interpreterProxy->stackIntegerValue(1);

	/* Call the primitive */

	theMRSocket = interpreterProxy->stackIntegerValue(0);

	/* Pop the args and rcvr */

	answer = sqOpenMIDI (theMRSemaphore, theMRSocket);
	if (interpreterProxy->failed()) {
		return null;
	}
	interpreterProxy->pop(3);
	interpreterProxy->push(((answer << 1) | 1));
}


/*	Play the given message (bytes) out MIDI interface. */
/*	MIDIPort primPut: buffer size: len on: interface */
/*	int sqMIDIPlaySizeOn (int message, int length, int interface) */

EXPORT(int) putMIDIOn(void) {
    int answer;
    int length;
    int message;
    int interface;

	message = interpreterProxy->stackValue(2);
	length = interpreterProxy->stackIntegerValue(1);
	interface = interpreterProxy->stackIntegerValue(0);
	interpreterProxy->success(interpreterProxy->isBytes(message));
	if (interpreterProxy->failed()) {
		return null;
	}
	answer = sqMIDIPlaySizeOn (message + 4, length, interface);
	if (interpreterProxy->failed()) {
		return null;
	}
	interpreterProxy->pop(4);
	interpreterProxy->push(((answer << 1) | 1));
}


/*	Read a control value (int) from the MIDI driver's cache. */
/*	MIDIPort primReadControllersFrom: from to: to into: array */
/*	int sqReadMIDIControl (int from, int to, int *results); */

EXPORT(int) readMIDIControl(void) {
    int results;
    int answer;
    int fromC;
    int toC;

	fromC = interpreterProxy->stackIntegerValue(2);
	toC = interpreterProxy->stackIntegerValue(1);
	if (fromC > 271) {
		results = interpreterProxy->stackIntegerValue(0);
	} else {
		results = interpreterProxy->stackValue(0);
	}
	answer = sqReadMIDIControl (fromC, toC, results);
	if (interpreterProxy->failed()) {
		return null;
	}
	interpreterProxy->pop(4);
	interpreterProxy->push(((answer << 1) | 1));
}


/*	Read a message (a MIDIPacket) from the MIDI interface. */
/*	MIDIPort primReadPacket: packet dsize: dsize data: data */
/*	int sqReadMIDIPacket (int packet, int dsize, int data); */

EXPORT(int) readMIDIPacket(void) {
    int packet;
    int answer;
    int dsize;
    int data;

	data = interpreterProxy->stackValue(0);
	dsize = interpreterProxy->stackIntegerValue(1);
	packet = interpreterProxy->stackValue(2);
	interpreterProxy->success(interpreterProxy->isBytes(data));
	if (interpreterProxy->failed()) {
		return null;
	}
	answer = sqReadMIDIPacket (packet, dsize, data + 4);
	if (interpreterProxy->failed()) {
		return null;
	}
	interpreterProxy->pop(4);
	interpreterProxy->push(((answer << 1) | 1));
}


/*	Note: This is coded so that is can be run from Squeak. */

EXPORT(int) setInterpreter(struct VirtualMachine* anInterpreter) {
    int ok;

	interpreterProxy = anInterpreter;
	ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR;
	if (ok == 0) {
		return 0;
	}
	ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR;
	return ok;
}
