796 lines
24 KiB
C
796 lines
24 KiB
C
/* PdVst v0.0.2 - VST - Pd bridging plugin
|
||
** Copyright (C) 2004 Joseph A. Sarlo
|
||
**
|
||
** This program is free software; you can redistribute it and/orsig
|
||
** modify it under the terms of the GNU General Public License
|
||
** as published by the Free Software Foundation; either version 2
|
||
** of the License, or (at your option) any later version.
|
||
**
|
||
** This program is distributed in the hope that it will be useful,
|
||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
** GNU General Public License for more details.
|
||
**
|
||
** You should have received a copy of the GNU General Public License
|
||
** along with this program; if not, write to the Free Software
|
||
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||
**
|
||
** jsarlo@ucsd.edu
|
||
*/
|
||
|
||
#define _WIN32_WINDOWS 0x410
|
||
#include <windows.h>
|
||
#include <io.h>
|
||
#include <stdio.h>
|
||
#include "m_pd.h"
|
||
#include "s_stuff.h"
|
||
#include "pdvstTransfer.h"
|
||
#define MAXARGS 1024
|
||
#define MAXSTRLEN 1024
|
||
#define TIMEUNITPERSEC (32.*441000.)
|
||
|
||
#define kVstTransportChanged 1
|
||
#define kVstTransportPlaying 2
|
||
|
||
#define kVstTransportRecording 8
|
||
#ifdef VSTMIDIOUTENABLE
|
||
EXTERN int midi_outhead;
|
||
int _midi_outtail=0; // _midi_outtail defined locally
|
||
typedef struct _midiqelem
|
||
{
|
||
double q_time;
|
||
int q_portno;
|
||
unsigned char q_onebyte;
|
||
unsigned char q_byte1;
|
||
unsigned char q_byte2;
|
||
unsigned char q_byte3;
|
||
} t_midiqelem;
|
||
|
||
#ifndef MIDIQSIZE
|
||
#define MIDIQSIZE 1024
|
||
#endif /*MIDIQSIZE */
|
||
|
||
EXTERN t_midiqelem midi_outqueue[MIDIQSIZE];
|
||
//EXTERN int msw_nmidiout;
|
||
int msw_nmidiout=0;
|
||
|
||
#endif // VSTMIDIOUTENABLE
|
||
|
||
|
||
typedef struct _vstParameterReceiver
|
||
{
|
||
t_object x_obj;
|
||
t_symbol *x_sym;
|
||
}t_vstParameterReceiver;
|
||
|
||
typedef struct _vstGuiNameReceiver
|
||
{
|
||
t_object x_obj;
|
||
}t_vstGuiNameReceiver;
|
||
|
||
t_vstGuiNameReceiver *vstGuiNameReceiver;
|
||
|
||
typedef struct _vstChunkReceiver
|
||
{
|
||
t_object x_obj;
|
||
}t_vstChunkReceiver;
|
||
|
||
t_vstChunkReceiver *vstChunkReceiver;
|
||
|
||
|
||
|
||
t_vstParameterReceiver *vstParameterReceivers[MAXPARAMETERS];
|
||
|
||
t_class *vstParameterReceiver_class;
|
||
t_class *vstGuiNameReceiver_class;
|
||
t_class *vstChunkReceiver_class;
|
||
|
||
char *pdvstTransferMutexName,
|
||
*pdvstTransferFileMapName,
|
||
*vstProcEventName,
|
||
*pdProcEventName;
|
||
pdvstTransferData *pdvstData;
|
||
HANDLE vstHostProcess,
|
||
pdvstTransferMutex,
|
||
pdvstTransferFileMap,
|
||
vstProcEvent,
|
||
pdProcEvent;
|
||
pdvstTimeInfo timeInfo;
|
||
|
||
int tokenizeCommandLineString(char *clString, char **tokens)
|
||
{
|
||
int i, charCount = 0;
|
||
int tokCount= 0;
|
||
int quoteOpen = 0;
|
||
|
||
for (i = 0; i < (signed int)strlen(clString); i++)
|
||
{
|
||
if (clString[i] == '"')
|
||
{
|
||
quoteOpen = !quoteOpen;
|
||
}
|
||
else if (clString[i] == ' ' && !quoteOpen)
|
||
{
|
||
tokens[tokCount][charCount] = 0;
|
||
tokCount++;
|
||
charCount = 0;
|
||
}
|
||
else
|
||
{
|
||
tokens[tokCount][charCount] = clString[i];
|
||
charCount++;
|
||
}
|
||
}
|
||
tokens[tokCount][charCount] = 0;
|
||
tokCount++;
|
||
return tokCount;
|
||
}
|
||
|
||
void parseArgs(int argc, char **argv)
|
||
{
|
||
int vstHostProcessId;
|
||
|
||
while ((argc > 0) && (**argv == '-'))
|
||
{
|
||
if (strcmp(*argv, "-vsthostid") == 0)
|
||
{
|
||
vstHostProcessId = atoi(argv[1]);
|
||
vstHostProcess = OpenProcess(PROCESS_ALL_ACCESS,
|
||
FALSE,
|
||
vstHostProcessId);
|
||
if (vstHostProcess == NULL)
|
||
{
|
||
exit(1);
|
||
}
|
||
argc -= 2;
|
||
argv += 2;
|
||
}
|
||
if (strcmp(*argv, "-mutexname") == 0)
|
||
{
|
||
pdvstTransferMutexName = argv[1];
|
||
argc -= 2;
|
||
argv += 2;
|
||
}
|
||
if (strcmp(*argv, "-filemapname") == 0)
|
||
{
|
||
pdvstTransferFileMapName = argv[1];
|
||
argc -= 2;
|
||
argv += 2;
|
||
}
|
||
if (strcmp(*argv, "-vstproceventname") == 0)
|
||
{
|
||
vstProcEventName = argv[1];
|
||
argc -= 2;
|
||
argv += 2;
|
||
}
|
||
if (strcmp(*argv, "-pdproceventname") == 0)
|
||
{
|
||
pdProcEventName = argv[1];
|
||
argc -= 2;
|
||
argv += 2;
|
||
}
|
||
else
|
||
{
|
||
argc--;
|
||
argv++;
|
||
}
|
||
}
|
||
}
|
||
|
||
int setPdvstGuiState(int state)
|
||
{
|
||
t_symbol *tempSym;
|
||
|
||
tempSym = gensym("rvstopengui");
|
||
if (tempSym->s_thing)
|
||
{
|
||
pd_float(tempSym->s_thing, (float)state);
|
||
return 1;
|
||
}
|
||
else
|
||
return 0;
|
||
}
|
||
|
||
|
||
int setPdvstPlugName(char* instanceName)
|
||
{
|
||
t_symbol *tempSym;
|
||
tempSym = gensym("rvstplugname");
|
||
if (tempSym->s_thing)
|
||
{
|
||
pd_symbol(tempSym->s_thing, gensym(instanceName));
|
||
return 1;
|
||
}
|
||
else
|
||
return 0;
|
||
}
|
||
|
||
int setPdvstChunk(char* instanceName)
|
||
{
|
||
t_symbol *tempSym;
|
||
tempSym = gensym("rvstdata");
|
||
if (tempSym->s_thing)
|
||
{
|
||
pd_symbol(tempSym->s_thing, gensym(instanceName));
|
||
return 1;
|
||
}
|
||
else
|
||
return 0;
|
||
}
|
||
|
||
|
||
int setPdvstFloatParameter(int index, float value)
|
||
{
|
||
t_symbol *tempSym;
|
||
char string[1024];
|
||
|
||
sprintf(string, "rvstparameter%d", index);
|
||
tempSym = gensym(string);
|
||
if (tempSym->s_thing)
|
||
{
|
||
pd_float(tempSym->s_thing, value);
|
||
return 1;
|
||
}
|
||
else
|
||
{
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
void sendPdVstFloatParameter(t_vstParameterReceiver *x, t_float floatValue)
|
||
{
|
||
int index;
|
||
|
||
index = atoi(x->x_sym->s_name + strlen("svstParameter"));
|
||
WaitForSingleObject(pdvstTransferMutex, INFINITE);
|
||
pdvstData->vstParameters[index].type = FLOAT_TYPE;
|
||
pdvstData->vstParameters[index].direction = PD_SEND;
|
||
pdvstData->vstParameters[index].updated = 1;
|
||
pdvstData->vstParameters[index].value.floatData = floatValue;
|
||
ReleaseMutex(pdvstTransferMutex);
|
||
}
|
||
|
||
void sendPdVstChunk(t_vstChunkReceiver *x, t_symbol *sym)
|
||
{
|
||
|
||
WaitForSingleObject(pdvstTransferMutex, INFINITE);
|
||
pdvstData->datachunk.type = STRING_TYPE;
|
||
pdvstData->datachunk.direction = PD_SEND;
|
||
pdvstData->datachunk.updated = 1;
|
||
strcpy(pdvstData->datachunk.value.stringData,sym->s_name);
|
||
ReleaseMutex(pdvstTransferMutex);
|
||
}
|
||
|
||
void sendPdVstGuiName(t_vstGuiNameReceiver *x, t_symbol *symbolValue)
|
||
{
|
||
WaitForSingleObject(pdvstTransferMutex, INFINITE);
|
||
pdvstData->guiName.type = STRING_TYPE;
|
||
pdvstData->guiName.direction = PD_SEND;
|
||
pdvstData->guiName.updated = 1;
|
||
strcpy(pdvstData->guiName.value.stringData,symbolValue->s_name);
|
||
|
||
ReleaseMutex(pdvstTransferMutex);
|
||
|
||
}
|
||
|
||
void makePdvstParameterReceivers()
|
||
{
|
||
int i;
|
||
char string[1024];
|
||
|
||
for (i = 0; i < MAXPARAMETERS; i++)
|
||
{
|
||
vstParameterReceivers[i] = (t_vstParameterReceiver *)pd_new(vstParameterReceiver_class);
|
||
sprintf(string, "svstparameter%d", i);
|
||
vstParameterReceivers[i]->x_sym = gensym(string);
|
||
pd_bind(&vstParameterReceivers[i]->x_obj.ob_pd, gensym(string));
|
||
}
|
||
|
||
}
|
||
|
||
void makePdvstGuiNameReceiver()
|
||
{
|
||
vstGuiNameReceiver = (t_vstGuiNameReceiver *)pd_new(vstGuiNameReceiver_class);
|
||
pd_bind(&vstGuiNameReceiver->x_obj.ob_pd, gensym("guiName"));
|
||
|
||
}
|
||
|
||
void makevstChunkReceiver()
|
||
{
|
||
vstChunkReceiver = (t_vstChunkReceiver *)pd_new(vstChunkReceiver_class);
|
||
pd_bind(&vstChunkReceiver->x_obj.ob_pd, gensym("svstdata"));
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
void send_dacs(void)
|
||
{
|
||
int i, j, sampleCount, nChannels, blockSize;
|
||
t_sample *soundin, *soundout;
|
||
|
||
soundin = get_sys_soundin();
|
||
soundout = get_sys_soundout();
|
||
nChannels = pdvstData->nChannels;
|
||
blockSize = pdvstData->blockSize;
|
||
if (blockSize == *(get_sys_schedblocksize()))
|
||
{
|
||
sampleCount = 0;
|
||
for (i = 0; i < nChannels; i++)
|
||
{
|
||
for (j = 0; j < blockSize; j++)
|
||
{
|
||
soundin[sampleCount] = pdvstData->samples[i][j];
|
||
pdvstData->samples[i][j] = soundout[sampleCount];
|
||
soundout[sampleCount] = 0;
|
||
sampleCount++;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
void scheduler_tick( void)
|
||
{
|
||
//l sys_addhist(0);
|
||
send_dacs();
|
||
//l sys_setmiditimediff(0, 1e-6 * *(get_sys_schedadvance()));
|
||
//l sys_addhist(1);
|
||
/// { JYG
|
||
//sched_tick(*(get_sys_time()) + *(get_sys_time_per_dsp_tick()));
|
||
sched_tick();
|
||
/// JYG }
|
||
//l sys_addhist(2);
|
||
sys_pollmidiqueue();
|
||
sys_pollgui();
|
||
//l sys_addhist(3);
|
||
}
|
||
/*
|
||
int HFClock()
|
||
{
|
||
LARGE_INTEGER freq, now;
|
||
|
||
QueryPerformanceFrequency(&freq);
|
||
QueryPerformanceCounter(&now);
|
||
return (int)((now.QuadPart * 1000) / freq.QuadPart);
|
||
}
|
||
*/
|
||
|
||
int scheduler()
|
||
{
|
||
int i,
|
||
blockTime,
|
||
|
||
active = 1;
|
||
DWORD vstHostProcessStatus = 0;
|
||
|
||
|
||
vstParameterReceiver_class = class_new(gensym("vstParameterReceiver"),
|
||
0,
|
||
0,
|
||
sizeof(t_vstParameterReceiver),
|
||
0,
|
||
0);
|
||
|
||
class_addfloat(vstParameterReceiver_class, (t_method)sendPdVstFloatParameter);
|
||
makePdvstParameterReceivers();
|
||
|
||
|
||
vstChunkReceiver_class = class_new(gensym("vstChunkReceiver"),
|
||
0,
|
||
0,
|
||
sizeof(t_vstChunkReceiver),
|
||
0,
|
||
0);
|
||
|
||
class_addsymbol(vstChunkReceiver_class,(t_method)sendPdVstChunk);
|
||
makevstChunkReceiver();
|
||
|
||
|
||
|
||
vstGuiNameReceiver_class = class_new(gensym("vstGuiNameReceiver"),
|
||
0,
|
||
0,
|
||
sizeof(t_vstGuiNameReceiver),
|
||
0,
|
||
0);
|
||
|
||
class_addsymbol(vstGuiNameReceiver_class,(t_method)sendPdVstGuiName);
|
||
makePdvstGuiNameReceiver();
|
||
|
||
*(get_sys_time_per_dsp_tick()) = (TIMEUNITPERSEC) * \
|
||
((double)*(get_sys_schedblocksize())) / \
|
||
*(get_sys_dacsr());
|
||
//l sys_clearhist();
|
||
//if (*(get_sys_sleepgrain()) < 1000) // JYG
|
||
if (*(get_sys_sleepgrain()) < 100)
|
||
{
|
||
*(get_sys_sleepgrain()) = *(get_sys_schedadvance()) / 4;
|
||
}
|
||
if (*(get_sys_sleepgrain()) < 100)
|
||
{
|
||
*(get_sys_sleepgrain()) = 100;
|
||
}
|
||
else if (*(get_sys_sleepgrain()) > 5000)
|
||
{
|
||
*(get_sys_sleepgrain()) = 5000;
|
||
}
|
||
sys_initmidiqueue();
|
||
|
||
#ifdef VSTMIDIOUTENABLE
|
||
pdvstData->midiOutQueueSize=0;
|
||
#endif // VSTMIDIOUTENABLE
|
||
while (active)
|
||
{
|
||
WaitForSingleObject(pdvstTransferMutex, INFINITE);
|
||
active = pdvstData->active;
|
||
// check sample rate
|
||
if (pdvstData->sampleRate != (int)sys_getsr())
|
||
{
|
||
post("check samplerate");
|
||
sys_setchsr(pdvstData->nChannels,
|
||
pdvstData->nChannels,
|
||
pdvstData->sampleRate);
|
||
}
|
||
// check for vstParameter changed
|
||
if (pdvstData->guiState.direction == PD_RECEIVE && \
|
||
pdvstData->guiState.updated)
|
||
{
|
||
if(setPdvstGuiState((int)pdvstData->guiState.value.floatData))
|
||
pdvstData->guiState.updated=0;
|
||
}
|
||
// JYG { check for vstplug instance name
|
||
if (pdvstData->plugName.direction == PD_RECEIVE && \
|
||
pdvstData->plugName.updated)
|
||
{
|
||
if (setPdvstPlugName((char*)pdvstData->plugName.value.stringData))
|
||
pdvstData->plugName.updated=0;
|
||
}
|
||
|
||
// lucarda get data chunk from file
|
||
if (pdvstData->datachunk.direction == PD_RECEIVE && \
|
||
pdvstData->datachunk.updated)
|
||
{
|
||
if (setPdvstChunk((char*)pdvstData->datachunk.value.stringData))
|
||
pdvstData->datachunk.updated=0;
|
||
}
|
||
|
||
if (pdvstData->hostTimeInfo.updated)
|
||
{
|
||
pdvstData->hostTimeInfo.updated=0;
|
||
t_symbol *tempSym;
|
||
|
||
if (timeInfo.flags!=pdvstData->hostTimeInfo.flags)
|
||
{
|
||
timeInfo.flags=pdvstData->hostTimeInfo.flags;
|
||
|
||
tempSym = gensym("vstTimeInfo.flags");
|
||
if (tempSym->s_thing)
|
||
{
|
||
pd_float(tempSym->s_thing, (float)timeInfo.flags);
|
||
}
|
||
else
|
||
{
|
||
timeInfo.flags=0;
|
||
pdvstData->hostTimeInfo.updated=1; // keep flag as updated
|
||
}
|
||
|
||
}
|
||
|
||
if ((timeInfo.flags&(kVstTransportChanged|kVstTransportPlaying|kVstTransportRecording))||(timeInfo.ppqPos!=(float)pdvstData->hostTimeInfo.ppqPos))
|
||
{
|
||
timeInfo.ppqPos=(float)pdvstData->hostTimeInfo.ppqPos;
|
||
|
||
tempSym = gensym("vstTimeInfo.ppqPos");
|
||
if (tempSym->s_thing)
|
||
{
|
||
pd_float(tempSym->s_thing, timeInfo.ppqPos);
|
||
}
|
||
else
|
||
{
|
||
timeInfo.ppqPos=0.;
|
||
pdvstData->hostTimeInfo.updated=1; // keep flag as updated
|
||
}
|
||
}
|
||
if ((timeInfo.flags&kVstTransportChanged)|(timeInfo.tempo!=(float)pdvstData->hostTimeInfo.tempo))
|
||
{
|
||
timeInfo.tempo=(float)pdvstData->hostTimeInfo.tempo;
|
||
|
||
tempSym = gensym("vstTimeInfo.tempo");
|
||
if (tempSym->s_thing)
|
||
{
|
||
pd_float(tempSym->s_thing, timeInfo.tempo);
|
||
}
|
||
else
|
||
{
|
||
timeInfo.tempo=0.;
|
||
pdvstData->hostTimeInfo.updated=1; // keep flag as updated
|
||
}
|
||
}
|
||
|
||
if ((timeInfo.flags&kVstTransportChanged)|timeInfo.timeSigNumerator!=pdvstData->hostTimeInfo.timeSigNumerator)
|
||
{
|
||
timeInfo.timeSigNumerator=pdvstData->hostTimeInfo.timeSigNumerator;
|
||
|
||
tempSym = gensym("vstTimeInfo.timeSigNumerator");
|
||
if (tempSym->s_thing)
|
||
{
|
||
pd_float(tempSym->s_thing, (float)timeInfo.timeSigNumerator);
|
||
}
|
||
else
|
||
{
|
||
timeInfo.timeSigNumerator=0;
|
||
pdvstData->hostTimeInfo.updated=1; // keep flag as updated
|
||
}
|
||
}
|
||
if ((timeInfo.flags&kVstTransportChanged)| timeInfo.timeSigDenominator!=pdvstData->hostTimeInfo.timeSigDenominator)
|
||
{
|
||
timeInfo.timeSigDenominator=pdvstData->hostTimeInfo.timeSigDenominator;
|
||
|
||
tempSym = gensym("vstTimeInfo.timeSigDenominator");
|
||
if (tempSym->s_thing)
|
||
{
|
||
pd_float(tempSym->s_thing, (float)timeInfo.timeSigDenominator);
|
||
}
|
||
else
|
||
{
|
||
timeInfo.timeSigDenominator=0;
|
||
pdvstData->hostTimeInfo.updated=1; // keep flag as updated
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
|
||
|
||
// JYG }
|
||
for (i = 0; i < pdvstData->nParameters; i++)
|
||
{
|
||
if (pdvstData->vstParameters[i].direction == PD_RECEIVE && \
|
||
pdvstData->vstParameters[i].updated)
|
||
{
|
||
if (pdvstData->vstParameters[i].type == FLOAT_TYPE)
|
||
{
|
||
if (setPdvstFloatParameter(i,
|
||
pdvstData->vstParameters[i].value.floatData))
|
||
{
|
||
pdvstData->vstParameters[i].updated = 0;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
// check for new midi-in message (VSTi)
|
||
if (pdvstData->midiQueueUpdated)
|
||
{
|
||
for (i = 0; i < pdvstData->midiQueueSize; i++)
|
||
{
|
||
if (pdvstData->midiQueue[i].messageType == NOTE_ON)
|
||
{
|
||
inmidi_noteon(0,
|
||
pdvstData->midiQueue[i].channelNumber,
|
||
pdvstData->midiQueue[i].dataByte1,
|
||
pdvstData->midiQueue[i].dataByte2);
|
||
}
|
||
else if (pdvstData->midiQueue[i].messageType == NOTE_OFF)
|
||
{
|
||
inmidi_noteon(0,
|
||
pdvstData->midiQueue[i].channelNumber,
|
||
pdvstData->midiQueue[i].dataByte1,
|
||
0);
|
||
}
|
||
else if (pdvstData->midiQueue[i].messageType == CONTROLLER_CHANGE)
|
||
{
|
||
inmidi_controlchange(0,
|
||
pdvstData->midiQueue[i].channelNumber,
|
||
pdvstData->midiQueue[i].dataByte1,
|
||
pdvstData->midiQueue[i].dataByte2);
|
||
}
|
||
else if (pdvstData->midiQueue[i].messageType == PROGRAM_CHANGE)
|
||
{
|
||
inmidi_programchange(0,
|
||
pdvstData->midiQueue[i].channelNumber,
|
||
pdvstData->midiQueue[i].dataByte1);
|
||
}
|
||
else if (pdvstData->midiQueue[i].messageType == PITCH_BEND)
|
||
{
|
||
int value = (((int)pdvstData->midiQueue[i].dataByte2) * 16) + \
|
||
(int)pdvstData->midiQueue[i].dataByte1;
|
||
|
||
inmidi_pitchbend(0,
|
||
pdvstData->midiQueue[i].channelNumber,
|
||
value);
|
||
}
|
||
else if (pdvstData->midiQueue[i].messageType == CHANNEL_PRESSURE)
|
||
{
|
||
inmidi_aftertouch(0,
|
||
pdvstData->midiQueue[i].channelNumber,
|
||
pdvstData->midiQueue[i].dataByte1);
|
||
}
|
||
else if (pdvstData->midiQueue[i].messageType == KEY_PRESSURE)
|
||
{
|
||
inmidi_polyaftertouch(0,
|
||
pdvstData->midiQueue[i].channelNumber,
|
||
pdvstData->midiQueue[i].dataByte1,
|
||
pdvstData->midiQueue[i].dataByte2);
|
||
}
|
||
else if (pdvstData->midiQueue[i].messageType == OTHER)
|
||
{
|
||
// FIXME: what to do?
|
||
}
|
||
else
|
||
{
|
||
post("pdvstData->midiQueue error"); // FIXME: error?
|
||
}
|
||
}
|
||
pdvstData->midiQueueSize = 0;
|
||
pdvstData->midiQueueUpdated = 0;
|
||
}
|
||
|
||
/// flush vstmidi out messages here
|
||
#ifdef VSTMIDIOUTENABLE
|
||
if (msw_nmidiout==0)
|
||
{
|
||
int i=pdvstData->midiOutQueueSize; // si la midiOutQueue n'a pas <20>t<EFBFBD> vid<69>e, rajouter des <20>l<EFBFBD>ments <20> la fin de celle-ci
|
||
while (midi_outhead != _midi_outtail)
|
||
{
|
||
int statusType = midi_outqueue[_midi_outtail].q_byte1 & 0xF0;
|
||
int statusChannel = midi_outqueue[_midi_outtail].q_byte1 & 0x0F;
|
||
|
||
// faut il g<>rer midi_outqueue[_midi_outtail].q_onebyte ?
|
||
|
||
///copie de la pile midi_outqueue dans la pile vst midiOutQueue
|
||
pdvstData->midiOutQueue[i].channelNumber= statusChannel;
|
||
pdvstData->midiOutQueue[i].statusByte = midi_outqueue[_midi_outtail].q_byte1;
|
||
pdvstData->midiOutQueue[i].dataByte1= midi_outqueue[_midi_outtail].q_byte2;
|
||
pdvstData->midiOutQueue[i].dataByte2= midi_outqueue[_midi_outtail].q_byte3;
|
||
|
||
if (statusType == 0x90)
|
||
if (midi_outqueue[_midi_outtail].q_byte3==0)
|
||
// note off
|
||
{
|
||
pdvstData->midiOutQueue[i].messageType = NOTE_OFF;
|
||
pdvstData->midiOutQueue[i].statusByte = statusChannel|0x80;
|
||
// post("note_off[%d] : %d",i,midi_outqueue[_midi_outtail].q_byte2);
|
||
|
||
}
|
||
|
||
else
|
||
{
|
||
// note on
|
||
pdvstData->midiOutQueue[i].messageType = NOTE_ON;
|
||
//post("note_on[%d] : %d",i,midi_outqueue[_midi_outtail].q_byte2);
|
||
|
||
}
|
||
else if (statusType == 0xA0)
|
||
// key pressure
|
||
pdvstData->midiOutQueue[i].messageType = KEY_PRESSURE;
|
||
else if (statusType == 0xB0)
|
||
// controller change
|
||
pdvstData->midiOutQueue[i].messageType = CONTROLLER_CHANGE;
|
||
else if (statusType == 0xC0)
|
||
// program change
|
||
pdvstData->midiOutQueue[i].messageType = PROGRAM_CHANGE;
|
||
else if (statusType == 0xD0)
|
||
// channel pressure
|
||
pdvstData->midiOutQueue[i].messageType = CHANNEL_PRESSURE;
|
||
else if (statusType == 0xE0)
|
||
// pitch bend
|
||
pdvstData->midiOutQueue[i].messageType = PITCH_BEND;
|
||
else
|
||
// something else
|
||
pdvstData->midiOutQueue[i].messageType = OTHER;
|
||
|
||
|
||
_midi_outtail = (_midi_outtail + 1 == MIDIQSIZE ? 0 : _midi_outtail + 1);
|
||
i = i + 1;
|
||
if (i>= MAXMIDIOUTQUEUESIZE)
|
||
break;
|
||
|
||
}
|
||
if (i>0)
|
||
{
|
||
pdvstData->midiOutQueueSize=i;
|
||
pdvstData->midiOutQueueUpdated=1;
|
||
}
|
||
else
|
||
{
|
||
pdvstData->midiOutQueueSize=0;
|
||
pdvstData->midiOutQueueUpdated=0;
|
||
}
|
||
}
|
||
#endif // VSTMIDIOUTENABLE
|
||
|
||
// run at approx. real-time
|
||
blockTime = (int)((float)(pdvstData->blockSize) / \
|
||
(float)pdvstData->sampleRate * 1000.0);
|
||
if (blockTime < 1)
|
||
{
|
||
blockTime = 1;
|
||
}
|
||
if (pdvstData->syncToVst)
|
||
{
|
||
ReleaseMutex(pdvstTransferMutex);
|
||
if (WaitForSingleObject(vstProcEvent, 1000) == WAIT_TIMEOUT)
|
||
{
|
||
// we have probably lost sync by now (1 sec)
|
||
WaitForSingleObject(pdvstTransferMutex, 100);
|
||
pdvstData->syncToVst = 0;
|
||
ReleaseMutex(pdvstTransferMutex);
|
||
}
|
||
ResetEvent(vstProcEvent);
|
||
scheduler_tick();
|
||
SetEvent(pdProcEvent);
|
||
}
|
||
else
|
||
{
|
||
ReleaseMutex(pdvstTransferMutex);
|
||
scheduler_tick();
|
||
Sleep(blockTime);
|
||
}
|
||
GetExitCodeProcess(vstHostProcess, &vstHostProcessStatus);
|
||
if (vstHostProcessStatus != STILL_ACTIVE)
|
||
{
|
||
active = 0;
|
||
}
|
||
}
|
||
return 1;
|
||
}
|
||
|
||
int pd_extern_sched(char *flags)
|
||
{
|
||
int i, argc;
|
||
char *argv[MAXARGS];
|
||
//l sys_audioapi = API_NONE;
|
||
|
||
|
||
t_audiosettings as;
|
||
|
||
sys_get_audio_settings(&as);
|
||
as.a_api = API_NONE;
|
||
sys_set_audio_settings(&as);
|
||
|
||
//
|
||
for (i = 0; i < MAXARGS; i++)
|
||
{
|
||
argv[i] = (char *)malloc(MAXSTRLEN * sizeof(char));
|
||
}
|
||
argc = tokenizeCommandLineString(flags, argv);
|
||
parseArgs(argc, argv);
|
||
pdvstTransferMutex = OpenMutex(MUTEX_ALL_ACCESS, 0, pdvstTransferMutexName);
|
||
vstProcEvent = OpenEvent(EVENT_ALL_ACCESS, 0, vstProcEventName);
|
||
pdProcEvent = OpenEvent(EVENT_ALL_ACCESS, 0, pdProcEventName);
|
||
pdvstTransferFileMap = OpenFileMapping(FILE_MAP_ALL_ACCESS,
|
||
0,
|
||
pdvstTransferFileMapName);
|
||
pdvstData = (pdvstTransferData *)MapViewOfFile(pdvstTransferFileMap,
|
||
FILE_MAP_ALL_ACCESS,
|
||
0,
|
||
0,
|
||
sizeof(pdvstTransferData));
|
||
WaitForSingleObject(pdvstTransferMutex, INFINITE);
|
||
//l *(get_sys_schedadvance()) = *(get_sys_main_advance()) * 1000;
|
||
//l post("Hello, appel sys_setchsr dans _main. Version 64");
|
||
sys_setchsr(pdvstData->nChannels,
|
||
pdvstData->nChannels,
|
||
pdvstData->sampleRate);
|
||
ReleaseMutex(pdvstTransferMutex);
|
||
//timeBeginPeriod(1);
|
||
scheduler();
|
||
UnmapViewOfFile(pdvstData);
|
||
CloseHandle(pdvstTransferFileMap);
|
||
CloseHandle(pdvstTransferMutex);
|
||
for (i = 0; i < MAXARGS; i++)
|
||
{
|
||
free(argv[i]);
|
||
}
|
||
return (0);
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|