Files
stk/STK/MD2SKINI.cpp
Gary Scavone 868787a5f9 Version 3.0
2013-09-29 22:41:42 +02:00

412 lines
11 KiB
C++

/*******************************************/
/* Simple Realtime MIDI to SKINI Parser */
/* Gary P. Scavone, February 1998. */
/* Revised for sockets, May & June 1998. */
/* SKINI/MIDI merge added August 1999. */
/* */
/* This object takes MIDI from the input */
/* stream (via the MIDIIO class), */
/* parses it, and turns it into SKINI */
/* messages. */
/*******************************************/
#include "MIDIIO.h"
#include "SKINI11.msg"
#if defined(__STK_REALTIME_)
int outAHere = 0;
// Do OS dependent declarations and includes
#if defined(__OS_IRIX_)
#include <sys/types.h>
#include <sys/prctl.h>
#include <signal.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
pid_t exit_thread;
#elif defined(__OS_Linux_)
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
pthread_t exit_thread;
#elif defined(__OS_Win_)
#include <process.h>
#include <winsock.h>
unsigned long exit_thread;
#endif
// The thread function definition protocols are slightly
// different under Irix, Linux, and Windoze.
#if defined(__OS_IRIX_)
void monitorStdin(void *)
#elif defined(__OS_Linux_)
void *monitorStdin(void *)
#elif defined(__OS_Win_)
void monitorStdin(void *)
#endif
{
char inputString[128];
printf("Type 'Exit<cr>' to quit.\n");
while (!outAHere) {
fgets(inputString, 128, stdin);
if (inputString[3] == 't' && inputString[1] == 'x'
&& inputString[2] == 'i' && inputString[0] == 'E') {
outAHere = 1;
}
else {
printf(inputString);
fflush(stdout);
}
}
}
void errorf(void) {
printf("useage: MD2SKINI <flag(s)>\n\n");
printf(" With no arguments, MD2SKINI converts MIDI input to SKINI\n");
printf(" format and sends the output directly to stdout.\n");
printf(" With flag = -s <hostname>, the output is sent over a socket\n");
printf(" connection to the optional hostname (default = localhost).\n");
printf(" With flag = -f <filename>, the output stream is simultaneously\n");
printf(" written to the file specified by the optional <filename>\n");
printf(" (default = test.ski).\n\n");
exit(0);
}
void main(int argc,char *argv[])
{
long j, i = 1;
MY_FLOAT byte2, byte3;
int channel;
int firstMessage = 1;
int writeFileOut = 0;
FILE *fileOut;
MIDIIO *controller;
char hostName[256];
char fileName[256];
int useSocket = 0;
int theSocket;
struct sockaddr_in saServer;
if (argc>5) {
errorf();
}
// Parse the command-line arguments.
while (i < argc) {
if (argv[i][0] == '-') {
switch(argv[i][1]) {
case 's':
if ((i+1 < argc) && argv[i+1][0] != '-') {
i++;
strcpy(hostName,argv[i]);
}
else strcpy(hostName,"localhost");
useSocket = 1;
break;
case 'f':
if ((i+1 < argc) && argv[i+1][0] != '-') {
i++;
strcpy(fileName,argv[i]);
if (strstr(fileName,".ski") == NULL) strcat(fileName,".ski");
}
else strcpy(fileName,"test.ski");
fileOut = fopen(fileName,"wb");
writeFileOut = 1;
break;
default:
errorf();
break;
}
}
else errorf();
i++;
}
MY_FLOAT dt=0.0;
controller = new MIDIIO();
// If using sockets, setup the client socket
if (useSocket) {
#if defined(__OS_Win_) // Stupid Windoze only stuff
WSADATA wsaData;
WORD wVersionRequested = MAKEWORD(1,1);
WSAStartup(wVersionRequested, &wsaData);
if (wsaData.wVersion != wVersionRequested) {
fprintf(stderr,"\n Wrong Windoze socket library version!\n");
exit(0);
}
#endif
// Create the client-side socket
theSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (theSocket < 0) {
fprintf(stderr,"Couldn't create socket ... aborting!\n");
exit(0);
}
struct hostent *hostp;
if ((hostp = gethostbyname(hostName)) == 0) {
fprintf(stderr,"%s: unknown host ... aborting!\n", hostName);
exit(0);
}
// Fill in the address structure
saServer.sin_family = AF_INET;
memcpy((void *)&saServer.sin_addr, hostp->h_addr, hostp->h_length);
saServer.sin_port = htons(2001); // Port number
// Connect to the server
if(connect(theSocket, (struct sockaddr *)&saServer, sizeof(saServer)) < 0) {
fprintf(stderr,"Socket connect failed ... aborting!\n");
#if defined(__OS_Win_)
closesocket(theSocket);
WSACleanup();
#else
close(theSocket);
#endif
exit(0);
}
}
// Setup the exit thread.
#if defined(__OS_IRIX_)
exit_thread = sproc(monitorStdin, PR_SALL);
if (exit_thread == -1) {
fprintf(stderr, "Unable to create exit thread ... aborting.\n");
exit(0);
}
#elif defined(__OS_Linux_)
int err = 0;
err = pthread_create(&exit_thread, NULL, monitorStdin, NULL);
if (err) {
fprintf(stderr, "Unable to create exit thread ... aborting.\n");
exit(0);
}
#elif defined(__OS_Win_)
exit_thread = _beginthread(monitorStdin, 0, NULL);
if (exit_thread == -1) {
fprintf(stderr, "Unable to create exit thread ... aborting.\n");
exit(0);
}
#endif
/* Write SKINI messages to buffer 's'. This is the easiest way
to allow this single executable to work for both socketing
and printf's to stdout.
*/
char s[128];
while (!outAHere) {
if (controller->nextMessage() > 0) {
byte3 = controller->getByteThree();
byte2 = controller->getByteTwo();
channel = controller->getChannel();
if (writeFileOut) dt = controller->getDeltaTime();
if (firstMessage) { /* first MIDI message time stamp is meaningless */
dt = 0.0;
firstMessage = 0;
}
switch(controller->getType()) {
case __SK_NoteOn_:
if (byte3 < 1.0) {
sprintf(s,"NoteOff\t\t%.3f %d %.1f %.1f\n",0.0,channel,byte2,64.0);
if (writeFileOut) {
fprintf(fileOut,"NoteOff\t\t%.3f %d %.1f %.1f\n",dt,channel,byte2,64.0);
}
} else {
sprintf(s,"NoteOn\t\t%.3f %d %.1f %.1f\n",0.0,channel,byte2,byte3);
if (writeFileOut) {
fprintf(fileOut,"NoteOn\t\t%.3f %d %.1f %.1f\n",dt,channel,byte2,byte3);
}
}
break;
case __SK_NoteOff_:
if (byte3 < 2.0) byte3 = 64.0;
sprintf(s,"NoteOff\t\t%.3f %d %.1f %.1f\n",0.0,channel,byte2,byte3);
if (writeFileOut) {
fprintf(fileOut,"NoteOff\t\t%.3f %d %.1f %.1f\n",dt,channel,byte2,byte3);
}
break;
case __SK_PolyPressure_:
sprintf(s,"PolyPressure\t%.3f %d %.1f %.1f\n",0.0,channel,byte2,byte3);
if (writeFileOut) {
fprintf(fileOut,"PolyPressure\t%.3f %d %.1f %.1f\n",dt,channel,byte2,byte3);
}
break;
case __SK_ControlChange_:
j = (int) byte2;
switch(j) {
case __SK_Volume_:
sprintf(s,"Volume\t%.3f %d %.1f\n",0.0,channel,byte3);
if (writeFileOut) {
fprintf(fileOut,"Volume\t%.3f %d %.1f\n",dt,channel,byte3);
}
break;
case __SK_ModWheel_:
sprintf(s,"ModWheel\t%.3f %d %.1f\n",0.0,channel,byte3);
if (writeFileOut) {
fprintf(fileOut,"ModWheel\t%.3f %d %.1f\n",dt,channel,byte3);
}
break;
case __SK_Breath_:
sprintf(s,"Breath\t\t%.3f %d %.1f\n",0.0,channel,byte3);
if (writeFileOut) {
fprintf(fileOut,"Breath\t\t%.3f %d %.1f\n",dt,channel,byte3);
}
break;
case __SK_FootControl_:
sprintf(s,"FootControl\t%.3f %d %.1f\n",0.0,channel,byte3);
if (writeFileOut) {
fprintf(fileOut,"FootControl\t%.3f %d %.1f\n",dt,channel,byte3);
}
break;
case __SK_Portamento_:
sprintf(s,"Portamento\t%.3f %d %.1f\n",0.0,channel,byte3);
if (writeFileOut) {
fprintf(fileOut,"Portamento\t%.3f %d %.1f\n",dt,channel,byte3);
}
break;
case __SK_Balance_:
sprintf(s,"Balance\t%.3f %d %.1f\n",0.0,channel,byte3);
if (writeFileOut) {
fprintf(fileOut,"Balance\t%.3f %d %.1f\n",dt,channel,byte3);
}
break;
case __SK_Pan_:
sprintf(s,"Pan\t\t%.3f %d %.1f\n",0.0,channel,byte3);
if (writeFileOut) {
fprintf(fileOut,"Pan\t\t%.3f %d %.1f\n",dt,channel,byte3);
}
break;
case __SK_Sustain_:
sprintf(s,"Sustain\t%.3f %d %.1f\n",0.0,channel,byte3);
if (writeFileOut) {
fprintf(fileOut,"Sustain\t%.3f %d %.1f\n",dt,channel,byte3);
}
break;
case __SK_Expression_:
sprintf(s,"Expression\t%.3f %d %.1f\n",0.0,channel,byte3);
if (writeFileOut) {
fprintf(fileOut,"Expression\t%.3f %d %.1f\n",dt,channel,byte3);
}
break;
default:
sprintf(s,"ControlChange\t%.3f %d %ld %.1f\n",0.0,channel,j,byte3);
if (writeFileOut) {
fprintf(fileOut,"ControlChange\t%.3f %d %ld %.1f\n",dt,channel,j,byte3);
}
break;
}
break;
case __SK_ProgramChange_:
j = (int) byte2;
sprintf(s,"ProgramChange\t%.3f %d %ld\n",0.0,channel,j);
if (writeFileOut) {
fprintf(fileOut,"ProgramChange\t%.3f %d %ld\n",dt,channel,j);
}
break;
case __SK_ChannelPressure_:
sprintf(s,"ChannelPressure\t%.3f %d %.1f\n",0.0,channel,byte2);
if (writeFileOut) {
fprintf(fileOut,"ChannelPressure\t%.3f %d %.1f\n",dt,channel,byte2);
}
break;
case __SK_PitchBend_:
sprintf(s,"PitchBend\t%.3f %d %f\n",0.0,channel,byte2);
if (writeFileOut) {
fprintf(fileOut,"PitchBend\t%.3f %d %f\n",dt,channel,byte2);
}
break;
default:
sprintf(s,"// Unknown\t%.3f %d %f %f\n",0.0,channel,byte2,byte3);
if (writeFileOut) {
fprintf(fileOut,"// Unknown\t\t%.3f %d %f %f\n",dt,channel,byte2,byte3);
}
break;
}
if (useSocket) {
if (send(theSocket, s, strlen(s), 0) < 0) {
fprintf(stderr,"Socket connection failed ... aborting.\n");
#if defined(__OS_Win_)
closesocket(theSocket);
WSACleanup();
#else
close(theSocket);
#endif
outAHere = 1;
exit(0);
}
}
else {
printf("%s", s);
fflush(stdout);
}
memset(s, 0, sizeof(s));
#if defined(__OS_Win_)
} else Sleep ( (DWORD) 2);
#else
} else usleep( (unsigned long) 2000);
#endif
}
sprintf(s,"Exiting MD2SKINI process ... bye!\n");
if (useSocket) {
send(theSocket, s, strlen(s), 0);
#if defined(__OS_Win_)
closesocket(theSocket);
WSACleanup();
#else
close(theSocket);
#endif
}
else {
printf("%s", s);
fflush(stdout);
}
if (writeFileOut) {
printf("Wrote SKINI output to file %s.\n", fileName);
fclose(fileOut);
}
delete controller;
}
#endif