diff --git a/common/jack/jack.h b/common/jack/jack.h index 35f2acc7..74c8b3cb 100644 --- a/common/jack/jack.h +++ b/common/jack/jack.h @@ -48,7 +48,8 @@ extern "C" require linker arguments in the client as well. */ #define JACK_WEAK_EXPORT __attribute__((weak)) -#else +#else +#define JACK_WEAK_EXPORT /* Add other things here for non-gcc platforms */ #endif #endif diff --git a/windows/JackRouter/JackRouter.cpp b/windows/JackRouter/JackRouter.cpp new file mode 100644 index 00000000..47727af7 --- /dev/null +++ b/windows/JackRouter/JackRouter.cpp @@ -0,0 +1,840 @@ +/* +Copyright (C) 2006 Grame + + This program is free software; you can redistribute it and/or 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifdef WIN32 +#pragma warning (disable : 4786) +#endif + +#include +#include +#include +#include +#include "JackRouter.h" +#include "profport.h" + +/* + + 08/07/2007 SL : USe jack_client_open instead of jack_client_new (automatic client renaming). + 09/08/2007 SL : Add JackRouter.ini parameter file. + 09/20/2007 SL : Better error report in DllRegisterServer (for Vista). + 09/27/2007 SL : Add AUDO_CONNECT property in JackRouter.ini file. + 10/10/2007 SL : Use ASIOSTInt32LSB instead of ASIOSTInt16LSB. + + */ + +//------------------------------------------------------------------------------------------ +// extern +void getNanoSeconds(ASIOTimeStamp *time); + +// local +double AsioSamples2double (ASIOSamples* samples); + +static const double twoRaisedTo32 = 4294967296.; +static const double twoRaisedTo32Reciprocal = 1. / twoRaisedTo32; + +//------------------------------------------------------------------------------------------ +// on windows, we do the COM stuff. + +#if WINDOWS +#include "windows.h" +#include "mmsystem.h" +#include "psapi.h" + +using namespace std; + +// class id. +// {838FE50A-C1AB-4b77-B9B6-0A40788B53F3} +CLSID IID_ASIO_DRIVER = { 0x838fe50a, 0xc1ab, 0x4b77, { 0xb9, 0xb6, 0xa, 0x40, 0x78, 0x8b, 0x53, 0xf3 } }; + + +CFactoryTemplate g_Templates[1] = { + {L"ASIOJACK", &IID_ASIO_DRIVER, JackRouter::CreateInstance} +}; +int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]); + +CUnknown* JackRouter::CreateInstance(LPUNKNOWN pUnk, HRESULT *phr) +{ + return (CUnknown*)new JackRouter(pUnk,phr); +}; + +STDMETHODIMP JackRouter::NonDelegatingQueryInterface(REFIID riid, void ** ppv) +{ + if (riid == IID_ASIO_DRIVER) { + return GetInterface(this, ppv); + } + return CUnknown::NonDelegatingQueryInterface(riid, ppv); +} + +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// Register ASIO Driver +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +extern LONG RegisterAsioDriver(CLSID,char *,char *,char *,char *); +extern LONG UnregisterAsioDriver(CLSID,char *,char *); + +// +// Server registration, called on REGSVR32.EXE "the dllname.dll" +// +HRESULT _stdcall DllRegisterServer() +{ + LONG rc; + char errstr[128]; + + rc = RegisterAsioDriver (IID_ASIO_DRIVER,"JackRouter.dll","JackRouter","JackRouter","Apartment"); + + if (rc) { + memset(errstr,0,128); + sprintf(errstr,"Register Server failed ! (%d)",rc); + MessageBox(0,(LPCTSTR)errstr,(LPCTSTR)"JackRouter",MB_OK); + return -1; + } + + return S_OK; +} + +// +// Server unregistration +// +HRESULT _stdcall DllUnregisterServer() +{ + LONG rc; + char errstr[128]; + + rc = UnregisterAsioDriver (IID_ASIO_DRIVER,"JackRouter.dll","JackRouter"); + + if (rc) { + memset(errstr,0,128); + sprintf(errstr,"Unregister Server failed ! (%d)",rc); + MessageBox(0,(LPCTSTR)errstr,(LPCTSTR)"JackRouter",MB_OK); + return -1; + } + + return S_OK; +} + +// Globals + +list > JackRouter::fConnections; +bool JackRouter::fFirstActivate = true; + +//------------------------------------------------------------------------------------------ +//------------------------------------------------------------------------------------------ +JackRouter::JackRouter (LPUNKNOWN pUnk, HRESULT *phr) + : CUnknown("ASIOJACK", pUnk, phr) + +//------------------------------------------------------------------------------------------ + +#else + +// when not on windows, we derive from AsioDriver +JackRouter::JackRouter() : AsioDriver() + +#endif +{ + long i; + + fSamplePosition = 0; + fActive = false; + fStarted = false; + fTimeInfoMode = false; + fTcRead = false; + fClient = NULL; + fAutoConnectIn = true; + fAutoConnectOut = true; + + for (i = 0; i < kNumInputs; i++) { + fInputBuffers[i] = 0; + fInputPorts[i] = 0; + fInMap[i] = 0; + } + for (i = 0; i < kNumOutputs; i++) { + fOutputBuffers[i] = 0; + fOutputPorts[i] = 0; + fOutMap[i] = 0; + } + fCallbacks = 0; + fActiveInputs = fActiveOutputs = 0; + fToggle = 0; + fBufferSize = 512; + fSampleRate = 44100; + printf("Constructor\n"); + + // Use "jackrouter.ini" parameters if available + HMODULE handle = LoadLibrary("JackRouter.dll"); + + if (handle) { + + // Get JackRouter.dll path + char dllName[512]; + string confPath; + DWORD res = GetModuleFileName(handle, dllName, 512); + + // Compute .ini file path + string fullPath = dllName; + int lastPos = fullPath.find_last_of(PATH_SEP); + string dllFolder = fullPath.substr(0, lastPos); + confPath = dllFolder + PATH_SEP + "JackRouter.ini"; + + // Get parameters + kNumInputs = get_private_profile_int("IO", "input", 2, confPath.c_str()); + kNumOutputs = get_private_profile_int("IO", "output", 2, confPath.c_str()); + + fAutoConnectIn = get_private_profile_int("AUTO_CONNECT", "input", 1, confPath.c_str()); + fAutoConnectOut = get_private_profile_int("AUTO_CONNECT", "output", 1, confPath.c_str()); + + FreeLibrary(handle); + + } else { + printf("LoadLibrary error\n"); + } +} + +//------------------------------------------------------------------------------------------ +JackRouter::~JackRouter() +{ + stop (); + disposeBuffers (); + printf("Destructor\n"); + jack_client_close(fClient); +} + +//------------------------------------------------------------------------------------------ +#include +#include +#include +#include "psapi.h" + +static bool GetEXEName(DWORD dwProcessID, char* name) +{ + DWORD aProcesses [1024], cbNeeded, cProcesses; + unsigned int i; + + // Enumerate all processes + if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded)) + return false; + + // Calculate how many process identifiers were returned. + cProcesses = cbNeeded / sizeof(DWORD); + + TCHAR szEXEName[MAX_PATH]; + // Loop through all process to find the one that matches + // the one we are looking for + + for (i = 0; i < cProcesses; i++) { + if (aProcesses [i] == dwProcessID) { + // Get a handle to the process + HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | + PROCESS_VM_READ, FALSE, dwProcessID); + + // Get the process name + if (NULL != hProcess) { + HMODULE hMod; + DWORD cbNeeded; + + if(EnumProcessModules(hProcess, &hMod, + sizeof(hMod), &cbNeeded)) { + //Get the name of the exe file + GetModuleBaseName(hProcess, hMod, szEXEName, + sizeof(szEXEName)/sizeof(TCHAR)); + int len = strlen((char*)szEXEName) - 4; // remove ".exe" + strncpy(name, (char*)szEXEName, len); + name[len] = '\0'; + return true; + } + } + } + } + + return false; +} + + //------------------------------------------------------------------------------------------ +static inline float ClipFloat(float sample) +{ + return (sample < -1.0f) ? -1.0f : (sample > 1.0f) ? 1.0f : sample; +} + +//------------------------------------------------------------------------------------------ +void JackRouter::shutdown(void* arg) +{ + JackRouter* driver = (JackRouter*)arg; + /* + //exit(1); + char errstr[128]; + + memset(errstr,0,128); + sprintf(errstr,"JACK server has quitted"); + MessageBox(0,(LPCTSTR)errstr,(LPCTSTR)"JackRouter",MB_OK); + */ +} + +//------------------------------------------------------------------------------------------ +int JackRouter::process(jack_nframes_t nframes, void* arg) +{ + JackRouter* driver = (JackRouter*)arg; + int i,j; + int pos = (driver->fToggle) ? 0 : driver->fBufferSize ; + + for (i = 0; i < driver->fActiveInputs; i++) { + +#ifdef LONG_SAMPLE + float* buffer = (float*)jack_port_get_buffer(driver->fInputPorts[i], nframes); + long* in = driver->fInputBuffers[i] + pos; + for (j = 0; j < nframes; j++) { + in[j] = buffer[j] * float(0x7fffffff); + } +#else + memcpy(driver->fInputBuffers[i] + pos, + jack_port_get_buffer(driver->fInputPorts[i], nframes), + nframes * sizeof(float)); +#endif + + } + + driver->bufferSwitch(); + + for (i = 0; i < driver->fActiveOutputs; i++) { + +#ifdef LONG_SAMPLE + float* buffer = (float*)jack_port_get_buffer(driver->fOutputPorts[i], nframes); + long* out = driver->fOutputBuffers[i] + pos; + float gain = 1.f/float(0x7fffffff); + for (j = 0; j < nframes; j++) { + buffer[j] = out[j] * gain; + } +#else + memcpy(jack_port_get_buffer(driver->fOutputPorts[i], nframes), + driver->fOutputBuffers[i] + pos, + nframes * sizeof(float)); +#endif + } + + return 0; +} + +//------------------------------------------------------------------------------------------ +void JackRouter::getDriverName(char *name) +{ + strcpy (name, "JackRouter"); +} + +//------------------------------------------------------------------------------------------ +long JackRouter::getDriverVersion() +{ + return 0x00000001L; +} + +//------------------------------------------------------------------------------------------ +void JackRouter::getErrorMessage(char *string) +{ + strcpy (string, fErrorMessage); +} + +//------------------------------------------------------------------------------------------ +ASIOBool JackRouter::init(void* sysRef) +{ + char name[MAX_PATH]; + sysRef = sysRef; + + if (fActive) + return true; + + HANDLE win = (HANDLE)sysRef; + int my_pid = _getpid(); + + if (!GetEXEName(my_pid, name)) { // If getting the .exe name fails, takes a generic one. + _snprintf(name, sizeof(name) - 1, "JackRouter_%d", my_pid); + } + + if (fClient) { + printf("Error: jack client still present...\n"); + return true; + } + + fClient = jack_client_open(name, JackNullOption, NULL); + if (fClient == NULL) { + strcpy (fErrorMessage, "Open error: is jack server running?"); + printf("Open error: is jack server running?\n"); + return false; + } + + fBufferSize = jack_get_buffer_size(fClient); + fSampleRate = jack_get_sample_rate(fClient); + jack_set_process_callback(fClient, process, this); + jack_on_shutdown(fClient, shutdown, this); + + fInputLatency = fBufferSize; // typically + fOutputLatency = fBufferSize * 2; + fMilliSeconds = (long)((double)(fBufferSize * 1000) / fSampleRate); + + // Typically fBufferSize * 2; try to get 1 by offering direct buffer + // access, and using asioPostOutput for lower latency + + printf("Init ASIO Jack\n"); + fActive = true; + return true; +} + +//------------------------------------------------------------------------------------------ +ASIOError JackRouter::start() +{ + if (fCallbacks) { + fSamplePosition = 0; + fTheSystemTime.lo = fTheSystemTime.hi = 0; + fToggle = 0; + fStarted = true; + printf("Start ASIO Jack\n"); + + if (jack_activate(fClient) == 0) { + + if (fFirstActivate) { + AutoConnect(); + fFirstActivate = false; + } else { + RestoreConnections(); + } + + return ASE_OK; + + } else { + return ASE_NotPresent; + } + } + + return ASE_NotPresent; +} + +//------------------------------------------------------------------------------------------ +ASIOError JackRouter::stop() +{ + fStarted = false; + printf("Stop ASIO Jack\n"); + SaveConnections(); + jack_deactivate(fClient); + return ASE_OK; +} + +//------------------------------------------------------------------------------------------ +ASIOError JackRouter::getChannels(long *numInputChannels, long *numOutputChannels) +{ + *numInputChannels = kNumInputs; + *numOutputChannels = kNumOutputs; + return ASE_OK; +} + +//------------------------------------------------------------------------------------------ +ASIOError JackRouter::getLatencies(long *_inputLatency, long *_outputLatency) +{ + *_inputLatency = fInputLatency; + *_outputLatency = fOutputLatency; + return ASE_OK; +} + +//------------------------------------------------------------------------------------------ +ASIOError JackRouter::getBufferSize(long *minSize, long *maxSize, long *preferredSize, long *granularity) +{ + *minSize = *maxSize = *preferredSize = fBufferSize; // allow this size only + *granularity = 0; + return ASE_OK; +} + +//------------------------------------------------------------------------------------------ +ASIOError JackRouter::canSampleRate(ASIOSampleRate sampleRate) +{ + return (sampleRate == fSampleRate) ? ASE_OK : ASE_NoClock; +} + +//------------------------------------------------------------------------------------------ +ASIOError JackRouter::getSampleRate(ASIOSampleRate *sampleRate) +{ + *sampleRate = fSampleRate; + return ASE_OK; +} + +//------------------------------------------------------------------------------------------ +ASIOError JackRouter::setSampleRate(ASIOSampleRate sampleRate) +{ + return (sampleRate == fSampleRate) ? ASE_OK : ASE_NoClock; +} + +//------------------------------------------------------------------------------------------ +ASIOError JackRouter::getClockSources(ASIOClockSource *clocks, long *numSources) +{ + // Internal + if (clocks && numSources) { + clocks->index = 0; + clocks->associatedChannel = -1; + clocks->associatedGroup = -1; + clocks->isCurrentSource = ASIOTrue; + strcpy(clocks->name, "Internal"); + *numSources = 1; + return ASE_OK; + } else { + return ASE_InvalidParameter; + } +} + +//------------------------------------------------------------------------------------------ +ASIOError JackRouter::setClockSource(long index) +{ + if (!index) { + fAsioTime.timeInfo.flags |= kClockSourceChanged; + return ASE_OK; + } else { + return ASE_NotPresent; + } +} + +//------------------------------------------------------------------------------------------ +ASIOError JackRouter::getSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp) +{ + tStamp->lo = fTheSystemTime.lo; + tStamp->hi = fTheSystemTime.hi; + + if (fSamplePosition >= twoRaisedTo32) { + sPos->hi = (unsigned long)(fSamplePosition * twoRaisedTo32Reciprocal); + sPos->lo = (unsigned long)(fSamplePosition - (sPos->hi * twoRaisedTo32)); + } else { + sPos->hi = 0; + sPos->lo = (unsigned long)fSamplePosition; + } + return ASE_OK; +} + +//------------------------------------------------------------------------------------------ +ASIOError JackRouter::getChannelInfo(ASIOChannelInfo *info) +{ + if (info->channel < 0 || (info->isInput ? info->channel >= kNumInputs : info->channel >= kNumOutputs)) + return ASE_InvalidParameter; +#ifdef LONG_SAMPLE + info->type = ASIOSTInt32LSB; +#else + info->type = ASIOSTFloat32LSB; +#endif + + info->channelGroup = 0; + info->isActive = ASIOFalse; + long i; + char buf[32]; + + if (info->isInput) { + for (i = 0; i < fActiveInputs; i++) { + if (fInMap[i] == info->channel) { + info->isActive = ASIOTrue; + //_snprintf(buf, sizeof(buf) - 1, "Jack::In%d ", info->channel); + //strcpy(info->name, buf); + //strcpy(info->name, jack_port_name(fInputPorts[i])); + break; + } + } + _snprintf(buf, sizeof(buf) - 1, "In%d ", info->channel); + strcpy(info->name, buf); + } else { + for (i = 0; i < fActiveOutputs; i++) { + if (fOutMap[i] == info->channel) { //NOT USED !! + info->isActive = ASIOTrue; + //_snprintf(buf, sizeof(buf) - 1, "Jack::Out%d ", info->channel); + //strcpy(info->name, buf); + //strcpy(info->name, jack_port_name(fOutputPorts[i])); + break; + } + } + _snprintf(buf, sizeof(buf) - 1, "Out%d ", info->channel); + strcpy(info->name, buf); + } + return ASE_OK; +} + +//------------------------------------------------------------------------------------------ +ASIOError JackRouter::createBuffers(ASIOBufferInfo *bufferInfos, long numChannels, + long bufferSize, ASIOCallbacks *callbacks) +{ + ASIOBufferInfo *info = bufferInfos; + long i; + bool notEnoughMem = false; + char buf[256]; + fActiveInputs = 0; + fActiveOutputs = 0; + + for (i = 0; i < numChannels; i++, info++) { + if (info->isInput) { + if (info->channelNum < 0 || info->channelNum >= kNumInputs) + goto error; + fInMap[fActiveInputs] = info->channelNum; + #ifdef LONG_SAMPLE + fInputBuffers[fActiveInputs] = new long[fBufferSize * 2]; // double buffer + #else + fInputBuffers[fActiveInputs] = new float[fBufferSize * 2]; // double buffer + #endif + if (fInputBuffers[fActiveInputs]) { + info->buffers[0] = fInputBuffers[fActiveInputs]; + info->buffers[1] = fInputBuffers[fActiveInputs] + fBufferSize; + } else { + info->buffers[0] = info->buffers[1] = 0; + notEnoughMem = true; + } + + _snprintf(buf, sizeof(buf) - 1, "in%d", fActiveInputs + 1); + fInputPorts[fActiveInputs] + = jack_port_register(fClient, buf, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput,0); + if (fInputPorts[fActiveInputs] == NULL) + goto error; + + fActiveInputs++; + if (fActiveInputs > kNumInputs) { +error: + disposeBuffers(); + return ASE_InvalidParameter; + } + } else { // output + if (info->channelNum < 0 || info->channelNum >= kNumOutputs) + goto error; + fOutMap[fActiveOutputs] = info->channelNum; + + #ifdef LONG_SAMPLE + fOutputBuffers[fActiveOutputs] = new long[fBufferSize * 2]; // double buffer + #else + fOutputBuffers[fActiveOutputs] = new float[fBufferSize * 2]; // double buffer + #endif + + if (fOutputBuffers[fActiveOutputs]) { + info->buffers[0] = fOutputBuffers[fActiveOutputs]; + info->buffers[1] = fOutputBuffers[fActiveOutputs] + fBufferSize; + } else { + info->buffers[0] = info->buffers[1] = 0; + notEnoughMem = true; + } + + _snprintf(buf, sizeof(buf) - 1, "out%d", fActiveOutputs + 1); + fOutputPorts[fActiveOutputs] + = jack_port_register(fClient, buf, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput,0); + if (fOutputPorts[fActiveOutputs] == NULL) + goto error; + + fActiveOutputs++; + if (fActiveOutputs > kNumOutputs) { + fActiveOutputs--; + disposeBuffers(); + return ASE_InvalidParameter; + } + } + } + + if (notEnoughMem) { + disposeBuffers(); + return ASE_NoMemory; + } + + this->fCallbacks = callbacks; + if (callbacks->asioMessage (kAsioSupportsTimeInfo, 0, 0, 0)) { + fTimeInfoMode = true; + fAsioTime.timeInfo.speed = 1.; + fAsioTime.timeInfo.systemTime.hi = fAsioTime.timeInfo.systemTime.lo = 0; + fAsioTime.timeInfo.samplePosition.hi = fAsioTime.timeInfo.samplePosition.lo = 0; + fAsioTime.timeInfo.sampleRate = fSampleRate; + fAsioTime.timeInfo.flags = kSystemTimeValid | kSamplePositionValid | kSampleRateValid; + + fAsioTime.timeCode.speed = 1.; + fAsioTime.timeCode.timeCodeSamples.lo = fAsioTime.timeCode.timeCodeSamples.hi = 0; + fAsioTime.timeCode.flags = kTcValid | kTcRunning ; + } else { + fTimeInfoMode = false; + } + + return ASE_OK; +} + +//--------------------------------------------------------------------------------------------- +ASIOError JackRouter::disposeBuffers() +{ + long i; + + fCallbacks = 0; + stop(); + + for (i = 0; i < fActiveInputs; i++) { + delete[] fInputBuffers[i]; + jack_port_unregister(fClient, fInputPorts[i]); + } + fActiveInputs = 0; + + for (i = 0; i < fActiveOutputs; i++) { + delete[] fOutputBuffers[i]; + jack_port_unregister(fClient, fOutputPorts[i]); + } + fActiveOutputs = 0; + + return ASE_OK; +} + +//--------------------------------------------------------------------------------------------- +ASIOError JackRouter::controlPanel() +{ + return ASE_NotPresent; +} + +//--------------------------------------------------------------------------------------------- +ASIOError JackRouter::future(long selector, void* opt) // !!! check properties +{ + ASIOTransportParameters* tp = (ASIOTransportParameters*)opt; + switch (selector) + { + case kAsioEnableTimeCodeRead: fTcRead = true; return ASE_SUCCESS; + case kAsioDisableTimeCodeRead: fTcRead = false; return ASE_SUCCESS; + case kAsioSetInputMonitor: return ASE_SUCCESS; // for testing!!! + case kAsioCanInputMonitor: return ASE_SUCCESS; // for testing!!! + case kAsioCanTimeInfo: return ASE_SUCCESS; + case kAsioCanTimeCode: return ASE_SUCCESS; + } + return ASE_NotPresent; +} + +//-------------------------------------------------------------------------------------------------------- +// private methods +//-------------------------------------------------------------------------------------------------------- + +//--------------------------------------------------------------------------------------------- +void JackRouter::bufferSwitch() +{ + if (fStarted && fCallbacks) { + getNanoSeconds(&fTheSystemTime); // latch system time + fSamplePosition += fBufferSize; + if (fTimeInfoMode) { + bufferSwitchX (); + } else { + fCallbacks->bufferSwitch (fToggle, ASIOFalse); + } + fToggle = fToggle ? 0 : 1; + } +} + +//--------------------------------------------------------------------------------------------- +// asio2 buffer switch +void JackRouter::bufferSwitchX () +{ + getSamplePosition (&fAsioTime.timeInfo.samplePosition, &fAsioTime.timeInfo.systemTime); + long offset = fToggle ? fBufferSize : 0; + if (fTcRead) { + // Create a fake time code, which is 10 minutes ahead of the card's sample position + // Please note that for simplicity here time code will wrap after 32 bit are reached + fAsioTime.timeCode.timeCodeSamples.lo = fAsioTime.timeInfo.samplePosition.lo + 600.0 * fSampleRate; + fAsioTime.timeCode.timeCodeSamples.hi = 0; + } + fCallbacks->bufferSwitchTimeInfo (&fAsioTime, fToggle, ASIOFalse); + fAsioTime.timeInfo.flags &= ~(kSampleRateChanged | kClockSourceChanged); +} + +//--------------------------------------------------------------------------------------------- +ASIOError JackRouter::outputReady() +{ + return ASE_NotPresent; +} + +//--------------------------------------------------------------------------------------------- +double AsioSamples2double(ASIOSamples* samples) +{ + double a = (double)(samples->lo); + if (samples->hi) + a += (double)(samples->hi) * twoRaisedTo32; + return a; +} + +//--------------------------------------------------------------------------------------------- +void getNanoSeconds(ASIOTimeStamp* ts) +{ + double nanoSeconds = (double)((unsigned long)timeGetTime ()) * 1000000.; + ts->hi = (unsigned long)(nanoSeconds / twoRaisedTo32); + ts->lo = (unsigned long)(nanoSeconds - (ts->hi * twoRaisedTo32)); +} + +//------------------------------------------------------------------------ +void JackRouter::SaveConnections() +{ + const char** connections; + int i; + + for (i = 0; i < fActiveInputs; ++i) { + if (fInputPorts[i] && (connections = jack_port_get_connections(fInputPorts[i])) != 0) { + for (int j = 0; connections[j]; j++) { + fConnections.push_back(make_pair(connections[j], jack_port_name(fInputPorts[i]))); + } + jack_free(connections); + } + } + + for (i = 0; i < fActiveOutputs; ++i) { + if (fOutputPorts[i] && (connections = jack_port_get_connections(fOutputPorts[i])) != 0) { + for (int j = 0; connections[j]; j++) { + fConnections.push_back(make_pair(jack_port_name(fOutputPorts[i]), connections[j])); + } + jack_free(connections); + } + } +} + +//------------------------------------------------------------------------ +void JackRouter::RestoreConnections() +{ + list >::const_iterator it; + + for (it = fConnections.begin(); it != fConnections.end(); it++) { + pair connection = *it; + jack_connect(fClient, connection.first.c_str(), connection.second.c_str()); + } + + fConnections.clear(); +} + +//------------------------------------------------------------------------------------------ +void JackRouter::AutoConnect() +{ + const char** ports; + + if ((ports = jack_get_ports(fClient, NULL, NULL, JackPortIsPhysical | JackPortIsOutput)) == NULL) { + printf("Cannot find any physical capture ports\n"); + } else { + if (fAutoConnectIn) { + for (int i = 0; i < fActiveInputs; i++) { + if (!ports[i]) { + printf("source port is null i = %ld\n", i); + break; + } else if (jack_connect(fClient, ports[i], jack_port_name(fInputPorts[i])) != 0) { + printf("Cannot connect input ports\n"); + } + } + } + jack_free(ports); + } + + if ((ports = jack_get_ports(fClient, NULL, NULL, JackPortIsPhysical | JackPortIsInput)) == NULL) { + printf("Cannot find any physical playback ports"); + } else { + if (fAutoConnectOut) { + for (int i = 0; i < fActiveOutputs; i++) { + if (!ports[i]){ + printf("destination port is null i = %ld\n", i); + break; + } else if (jack_connect(fClient, jack_port_name(fOutputPorts[i]), ports[i]) != 0) { + printf("Cannot connect output ports\n"); + } + } + } + jack_free(ports); + } +} + diff --git a/windows/JackRouter/JackRouter.def b/windows/JackRouter/JackRouter.def new file mode 100644 index 00000000..1316d71f --- /dev/null +++ b/windows/JackRouter/JackRouter.def @@ -0,0 +1,9 @@ +LIBRARY JackRouter +DESCRIPTION 'ASIO Jack Driver' +PROTMODE +EXPORTS + DllMain + DllGetClassObject + DllCanUnloadNow + DllRegisterServer + DllUnregisterServer diff --git a/windows/JackRouter/JackRouter.dsp b/windows/JackRouter/JackRouter.dsp new file mode 100644 index 00000000..c92ddf99 --- /dev/null +++ b/windows/JackRouter/JackRouter.dsp @@ -0,0 +1,163 @@ +# Microsoft Developer Studio Project File - Name="JackRouter" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=JackRouter - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "JackRouter.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "JackRouter.mak" CFG="JackRouter - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "JackRouter - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "JackRouter - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "JackRouter - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\..\..\ASIOSDK2\common" /I "..\..\common" /I "..\..\common\jack" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:windows /dll /machine:I386 + +!ELSEIF "$(CFG)" == "JackRouter - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c +# ADD CPP /nologo /G5 /MDd /W3 /Gm /GX /Zi /Od /I "..\..\..\..\..\ASIOSDK2\common" /I "..\..\common" /I "..\..\common\jack" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:"Debug/JackRouter_debug.dll" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "JackRouter - Win32 Release" +# Name "JackRouter - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\..\..\..\ASIOSDK2\common\combase.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\..\ASIOSDK2\common\dllentry.cpp +# End Source File +# Begin Source File + +SOURCE=.\JackRouter.cpp +# End Source File +# Begin Source File + +SOURCE=.\JackRouter.def +# End Source File +# Begin Source File + +SOURCE=.\profport.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\..\ASIOSDK2\common\register.cpp +# End Source File +# Begin Source File + +SOURCE=.\resource.rc +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\..\common\asio.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\Asiodrvr.h +# End Source File +# Begin Source File + +SOURCE=..\asiosmpl.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\common\asiosys.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\common\combase.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\common\iasiodrv.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# Begin Source File + +SOURCE=.\Psapi.Lib +# End Source File +# Begin Source File + +SOURCE=..\Release\bin\libjack.lib +# End Source File +# End Target +# End Project diff --git a/windows/JackRouter/JackRouter.dsw b/windows/JackRouter/JackRouter.dsw new file mode 100644 index 00000000..e26ab1ee --- /dev/null +++ b/windows/JackRouter/JackRouter.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "JackRouter"=".\JackRouter.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/windows/JackRouter/JackRouter.h b/windows/JackRouter/JackRouter.h new file mode 100644 index 00000000..bf5d44c8 --- /dev/null +++ b/windows/JackRouter/JackRouter.h @@ -0,0 +1,174 @@ +/* +Copyright (C) 2006 Grame + + This program is free software; you can redistribute it and/or 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef _asiosmpl_ +#define _asiosmpl_ + +#include "asiosys.h" + + +// Globals +static int kBlockFrames = 256; +static int kNumInputs = 4; +static int kNumOutputs = 4; + + +#if WINDOWS + +#include "jack.h" +#include "rpc.h" +#include "rpcndr.h" +#ifndef COM_NO_WINDOWS_H +#include +#include "ole2.h" + +#endif + +#include "combase.h" +#include "iasiodrv.h" + +#define MAX_PORTS 32 + +#define LONG_SAMPLE 1 + +#define PATH_SEP "\\" + +#include +#include + +class JackRouter : public IASIO, public CUnknown +{ +public: + JackRouter(LPUNKNOWN pUnk, HRESULT *phr); + ~JackRouter(); + + DECLARE_IUNKNOWN + //STDMETHODIMP QueryInterface(REFIID riid, void **ppv) { \ + // return GetOwner()->QueryInterface(riid,ppv); \ + //}; \ + //STDMETHODIMP_(ULONG) AddRef() { \ + // return GetOwner()->AddRef(); \ + //}; \ + //STDMETHODIMP_(ULONG) Release() { \ + // return GetOwner()->Release(); \ + //}; + + // Factory method + static CUnknown *CreateInstance(LPUNKNOWN pUnk, HRESULT *phr); + // IUnknown + virtual HRESULT STDMETHODCALLTYPE NonDelegatingQueryInterface(REFIID riid,void **ppvObject); +#else + +#include "asiodrvr.h" + + +//--------------------------------------------------------------------------------------------- +class JackRouter : public AsioDriver +{ +public: + JackRouter(); + ~JackRouter(); +#endif + + static int process(jack_nframes_t nframes, void* arg); + static void shutdown(void* arg); + + ASIOBool init(void* sysRef); + void getDriverName(char *name); // max 32 bytes incl. terminating zero + long getDriverVersion(); + void getErrorMessage(char *string); // max 128 bytes incl. + + ASIOError start(); + ASIOError stop(); + + ASIOError getChannels(long *numInputChannels, long *numOutputChannels); + ASIOError getLatencies(long *inputLatency, long *outputLatency); + ASIOError getBufferSize(long *minSize, long *maxSize, + long *preferredSize, long *granularity); + + ASIOError canSampleRate(ASIOSampleRate sampleRate); + ASIOError getSampleRate(ASIOSampleRate *sampleRate); + ASIOError setSampleRate(ASIOSampleRate sampleRate); + ASIOError getClockSources(ASIOClockSource *clocks, long *numSources); + ASIOError setClockSource(long index); + + ASIOError getSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp); + ASIOError getChannelInfo(ASIOChannelInfo *info); + + ASIOError createBuffers(ASIOBufferInfo *bufferInfos, long numChannels, + long bufferSize, ASIOCallbacks *callbacks); + ASIOError disposeBuffers(); + + ASIOError controlPanel(); + ASIOError future(long selector, void *opt); + ASIOError outputReady(); + + void bufferSwitch(); + long getMilliSeconds() {return fMilliSeconds;} + + static bool fFirstActivate; + static std::list > fConnections; // Connections list + +private: + + void bufferSwitchX(); + + double fSamplePosition; + ASIOCallbacks* fCallbacks; + ASIOTime fAsioTime; + ASIOTimeStamp fTheSystemTime; + +#ifdef LONG_SAMPLE + long* fInputBuffers[MAX_PORTS * 2]; + long* fOutputBuffers[MAX_PORTS * 2]; +#else + float* fInputBuffers[MAX_PORTS * 2]; + float* fOutputBuffers[MAX_PORTS * 2]; +#endif + long fInMap[MAX_PORTS]; + long fOutMap[MAX_PORTS]; + + long fInputLatency; + long fOutputLatency; + long fActiveInputs; + long fActiveOutputs; + long fToggle; + long fMilliSeconds; + bool fActive, fStarted; + bool fTimeInfoMode, fTcRead; + char fErrorMessage[128]; + + bool fAutoConnectIn; + bool fAutoConnectOut; + + // Jack part + jack_client_t* fClient; + jack_port_t* fInputPorts[MAX_PORTS]; + jack_port_t* fOutputPorts[MAX_PORTS]; + long fBufferSize; + ASIOSampleRate fSampleRate; + + void AutoConnect(); + void SaveConnections(); + void RestoreConnections(); + +}; + +#endif + diff --git a/windows/JackRouter/Psapi.Lib b/windows/JackRouter/Psapi.Lib new file mode 100644 index 00000000..ae896911 Binary files /dev/null and b/windows/JackRouter/Psapi.Lib differ diff --git a/windows/JackRouter/README b/windows/JackRouter/README new file mode 100644 index 00000000..5f2bce1d --- /dev/null +++ b/windows/JackRouter/README @@ -0,0 +1,3 @@ +This folder contains the sources for ASIO/JACK bridge ASIO driver called "JackRouter". The included project is a Microsoft VC++ 6 one. +It requires some files (combase.cpp, dllentry.cpp, register.cpp) that are part on the ASIO driver SDK. The produced "JackRouter.dll" file +has to be registered in the system using the "regsvr32" tool. \ No newline at end of file diff --git a/windows/JackRouter/profport.cpp b/windows/JackRouter/profport.cpp new file mode 100644 index 00000000..eb77937f --- /dev/null +++ b/windows/JackRouter/profport.cpp @@ -0,0 +1,315 @@ +/* +History : +01-28-02 : Change the location of temporary files created in write_private_profile_string + now done in TmpDirectory. +01-29-02 : Correct bug when the '=' character is not present. +06-18-02 : Return default value if file does not exist, new write_private_profile_int function. +*/ + +/***** Routines to read profile strings -- by Joseph J. Graf ******/ +/***** corrections and improvements -- by D. Fober - Grame ******/ +/* + corrections: buffer sizes control + improvements: behavior more similar to windows +*/ + +#include +#include +#include +#include + +#include + +#include +#include "profport.h" /* function prototypes in here */ + +#ifndef WIN32 + +static int read_line (FILE *fp, char *bp, int size); +static int read_section(FILE *fp, char *section); +static int read_entry (FILE *fp, char *entry, char *buff, int size); +static char * read_value (char *buff); +static int read_int_value (char *buff, int def); +static char * read_file (char *file); +static char * str_search (char * buff, char * str, int stopCond); + +/***************************************************************** +* Function: read_line() +* Arguments: fp - a pointer to the file to be read from +* bp - a pointer to the copy buffer +* size - size of the copy buffer +* Returns: the line length if successful -1 otherwise +******************************************************************/ +static int read_line(FILE *fp, char *bp, int size) +{ + char c = '\0'; + int i = 0, limit = size-2; + + /* Read one line from the source file */ + while (((c = getc(fp)) != '\n') && (i < limit)) { + if (c == EOF) { + if (!i) return -1; + else break; + } + bp[i++] = c; + } + bp[i] = '\0'; + return i; +} + +static int read_section (FILE *fp, char *section) +{ + char buff[MAX_LINE_LENGTH]; + char t_section[MAX_LINE_LENGTH]; + int n, slen; + + sprintf(t_section,"[%s]", section); /* Format the section name */ + slen = strlen (t_section); + /* Move through file 1 line at a time until a section is matched or EOF */ + do { + n = read_line(fp, buff, MAX_LINE_LENGTH); + if (n == -1) + return 0; + } while (strncmp (buff,t_section, slen)); + return 1; + } + +static int read_entry (FILE *fp, char *entry, char *buff, int size) +{ + int n, elen = strlen (entry); + + do { + n = read_line(fp, buff, size); + if (n == -1) + return 0; + else if (*buff == '[') + return 0; + } while (strncmp (buff, entry, elen)); + return 1; + } + +#define isBlank(c) ((c == ' ') || (c == '\t')) +static char * read_value (char *buff) +{ + char * eq = strrchr (buff,'='); /* Parse out the equal sign */ + if (eq) { + eq++; + while (*eq && isBlank(*eq)) + eq++; +// return *eq ? eq : 0; + return eq; + } + return eq; + } + +#define isSignedDigit(c) (isdigit(c) || (c == '+') || (c == '-')) +static int read_int_value (char *buff, int def) +{ + char * val = read_value (buff); + char value[20]; int i; + + if (!*val) return def; + + for (i = 0; isSignedDigit(*val) && (i <= 10); i++ ) + value[i] = *val++; + value[i] = '\0'; + return value[0] ? atoi(value) : def; +} + +static char * read_file (char *file) +{ + FILE *fd = fopen (file,"r"); + int size; char * buff = 0; + + if (!fd) return 0; + if (fseek (fd, 0, SEEK_END) == -1) goto err; + size = ftell (fd); + if (size < 0) goto err; + if (fseek (fd, 0, SEEK_SET) == -1) goto err; + buff = (char *) malloc (size+1); + if (buff) { + *buff = 0; + fread (buff, 1, size, fd); + buff[size] = 0; + } +err: + fclose (fd); + return buff; +} + +static char * str_search (char * buff, char * str, int stopCond) +{ + char *ptr = buff; + int len = strlen (str); + while (*ptr && strncmp (ptr, str, len)) { + while (*ptr && (*ptr++ != '\n')) + ; + if (*ptr == stopCond) + return 0; + } + return *ptr ? ptr : 0; +} + +/************************************************************************** +* Function: get_private_profile_int() +* Arguments: section - the name of the section to search for +* entry - the name of the entry to find the value of +* def - the default value in the event of a failed read +* file_name - the name of the .ini file to read from +* Returns: the value located at entry +***************************************************************************/ +int get_private_profile_int(char *section, + char *entry, int def, char *file_name) +{ + FILE *fp = fopen(file_name,"r"); + char buff[MAX_LINE_LENGTH]; + + if( !fp ) return def; /* Return default value if file does not exist */ + if (!read_section (fp, section)) goto err; + if (!read_entry (fp, entry, buff, MAX_LINE_LENGTH)) goto err; + def = read_int_value (buff, def); +err: + fclose (fp); + return def; +} + +/************************************************************************** +* Function: get_private_profile_string() +* Arguments: section - the name of the section to search for +* entry - the name of the entry to find the value of +* def - default string in the event of a failed read +* buffer - a pointer to the buffer to copy into +* buffer_len - the max number of characters to copy +* file_name - the name of the .ini file to read from +* Returns: the number of characters copied into the supplied buffer +***************************************************************************/ + +int get_private_profile_string(char *section, char *entry, char *def, + char *buffer, int buffer_len, char *file_name) +{ + FILE *fp = fopen (file_name,"r"); + char buff[MAX_LINE_LENGTH]; + char *val; + + if( !fp ) goto err; /* Return default value if file does not exist */ + if (!read_section (fp, section)) goto err; + if (!read_entry (fp, entry, buff, MAX_LINE_LENGTH)) goto err; + val = read_value (buff); + if(val) def = val; + +err: + if (fp) fclose (fp); + if (def) { + strncpy (buffer, def, buffer_len - 1); + buffer[buffer_len] = '\0'; + } + else buffer[buffer_len] = '\0'; + return strlen (buffer); +} + + +/*************************************************************************** + * Function: write_private_profile_string() + * Arguments: section - the name of the section to search for + * entry - the name of the entry to find the value of + * buffer - pointer to the buffer that holds the string + * file_name - the name of the .ini file to read from + * Returns: TRUE if successful, otherwise FALSE + ***************************************************************************/ +int write_private_profile_string(char *section, + char *entry, char *buffer, char *file_name) + +{ + char * content = read_file(file_name); + FILE * fd = fopen(file_name,"w"); + char t_section[MAX_LINE_LENGTH], *ptr; + int ret = 0; + + if (!fd) goto end; + if (!content) { + fprintf (fd, "[%s]\n%s = %s\n", section, entry, buffer); + ret = 1; + goto end; + } + sprintf(t_section,"[%s]",section); /* Format the section name */ + ptr = str_search (content, t_section, 0); /* look for the section start */ + if (!ptr) { + /* no such section: add the new section at end of file */ + fprintf (fd, "%s\n[%s]\n%s = %s\n", content, section, entry, buffer); + } + else { + char * eptr; + eptr = str_search (ptr, entry, '['); + if (!eptr) { + /* no such entry: looks for next section */ + eptr = str_search (++ptr, "[", 0); + if (!eptr) { + /* section is the last one */ + fprintf (fd, "%s\n%s = %s\n", content, entry, buffer); + } + else { + while (*ptr && (*ptr != '\n')) ptr++; + *ptr = 0; + fprintf (fd, "%s\n%s = %s", content, entry, buffer); + *ptr = '\n'; + fprintf (fd, "%s", ptr); + } + } + else { + *eptr++ = 0; + fprintf (fd, "%s%s = %s", content, entry, buffer); + while (*eptr && (*eptr != '\n')) eptr++; + if (eptr) fprintf (fd, "%s", eptr); + } + } + ret = 1; + +end: + if (content) free(content); + if (fd) fclose(fd); + return 0; +} + +/*************************************************************************** + * Function: write_private_profile_int() + * Arguments: section - the name of the section to search for + * entry - the name of the entry to find the value of + * buffer - the value to be written + * file_name - the name of the .ini file to read from + * Returns: TRUE if successful, otherwise FALSE + ***************************************************************************/ +int write_private_profile_int(char *section, + char *entry, int val, char *file_name) +{ + char buffer [64]; + sprintf(buffer, "%d", val); + return write_private_profile_string (section,entry, buffer, file_name); +} + +#endif // #ifndef WIN32 + + +/************************************************************************** +* Function: get_private_profile_float() +* Arguments: section - the name of the section to search for +* entry - the name of the entry to find the value of +* def - the default value in the event of a failed read +* file_name - the name of the .ini file to read from +* Returns: the value located at entry +* Warning: The float value to be read must not contain more than 100 digits. +* Author: CD, 15/11/2006. +***************************************************************************/ +#define maxFloatLen 100 +float get_private_profile_float (char * section, char * entry, float def, char * file_name) +{ + float result = def; + char buffer[ maxFloatLen ], *endptr; + + if ( get_private_profile_string(section, entry, "", buffer, maxFloatLen, file_name) > 0 ) + { + result = (float)strtod(buffer, &endptr); + if ((result==0) && (endptr==buffer)) + result = def; + } + return result; +} diff --git a/windows/JackRouter/profport.h b/windows/JackRouter/profport.h new file mode 100644 index 00000000..2f717177 --- /dev/null +++ b/windows/JackRouter/profport.h @@ -0,0 +1,37 @@ + +/****************************************************************************** + PORTABLE ROUTINES FOR WRITING PRIVATE PROFILE STRINGS -- by Joseph J. Graf + Header file containing prototypes and compile-time configuration. + + [09/05/02] D. Fober - Windows definitions added +******************************************************************************/ + +#ifndef __profport__ +#define __profport__ + +#define MAX_LINE_LENGTH 1024 + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef WIN32 +#include "Windows.h" +#define get_private_profile_int GetPrivateProfileInt +#define get_private_profile_string GetPrivateProfileString +#define write_private_profile_string WritePrivateProfileString +#define write_private_profile_int WritePrivateProfileInt +#else +int get_private_profile_int (char * section, char * entry, int def, char * file_name); +int get_private_profile_string (char * section, char * entry, char * def, char * buffer, int buffer_len, char * file_name); +int write_private_profile_string (char * section, char * entry, char * buffer, char * file_name); +int write_private_profile_int (char * section, char * entry, int val, char * file_name); +#endif + +float get_private_profile_float (char * section, char * entry, float def, char * file_name); + +#ifdef __cplusplus +} +#endif + +#endif //__profport__ diff --git a/windows/JackRouter/psapi.dll b/windows/JackRouter/psapi.dll new file mode 100644 index 00000000..ff4c964c Binary files /dev/null and b/windows/JackRouter/psapi.dll differ diff --git a/windows/JackRouter/psapi.h b/windows/JackRouter/psapi.h new file mode 100644 index 00000000..af72931e --- /dev/null +++ b/windows/JackRouter/psapi.h @@ -0,0 +1,95 @@ +/* + psapi.h - Include file for PSAPI.DLL APIs + + Written by Mumit Khan + + This file is part of a free library for the Win32 API. + + NOTE: This strictly does not belong in the Win32 API since it's + really part of Platform SDK. However,GDB needs it and we might + as well provide it here. + + This library 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. + +*/ +#ifndef _PSAPI_H +#define _PSAPI_H +#if __GNUC__ >=3 +#pragma GCC system_header +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef RC_INVOKED + +typedef struct _MODULEINFO { + LPVOID lpBaseOfDll; + DWORD SizeOfImage; + LPVOID EntryPoint; +} MODULEINFO,*LPMODULEINFO; + +typedef struct _PSAPI_WS_WATCH_INFORMATION { + LPVOID FaultingPc; + LPVOID FaultingVa; +} PSAPI_WS_WATCH_INFORMATION,*PPSAPI_WS_WATCH_INFORMATION; + +typedef struct _PROCESS_MEMORY_COUNTERS { + DWORD cb; + DWORD PageFaultCount; + DWORD PeakWorkingSetSize; + DWORD WorkingSetSize; + DWORD QuotaPeakPagedPoolUsage; + DWORD QuotaPagedPoolUsage; + DWORD QuotaPeakNonPagedPoolUsage; + DWORD QuotaNonPagedPoolUsage; + DWORD PagefileUsage; + DWORD PeakPagefileUsage; +} PROCESS_MEMORY_COUNTERS,*PPROCESS_MEMORY_COUNTERS; + +/* Grouped by application,not in alphabetical order. */ +BOOL WINAPI EnumProcesses(DWORD *,DWORD,DWORD *); +BOOL WINAPI EnumProcessModules(HANDLE,HMODULE *,DWORD,LPDWORD); +DWORD WINAPI GetModuleBaseNameA(HANDLE,HMODULE,LPSTR,DWORD); +DWORD WINAPI GetModuleBaseNameW(HANDLE,HMODULE,LPWSTR,DWORD); +DWORD WINAPI GetModuleFileNameExA(HANDLE,HMODULE,LPSTR,DWORD); +DWORD WINAPI GetModuleFileNameExW(HANDLE,HMODULE,LPWSTR,DWORD); +BOOL WINAPI GetModuleInformation(HANDLE,HMODULE,LPMODULEINFO,DWORD); +BOOL WINAPI EmptyWorkingSet(HANDLE); +BOOL WINAPI QueryWorkingSet(HANDLE,PVOID,DWORD); +BOOL WINAPI InitializeProcessForWsWatch(HANDLE); +BOOL WINAPI GetWsChanges(HANDLE,PPSAPI_WS_WATCH_INFORMATION,DWORD); +DWORD WINAPI GetMappedFileNameW(HANDLE,LPVOID,LPWSTR,DWORD); +DWORD WINAPI GetMappedFileNameA(HANDLE,LPVOID,LPSTR,DWORD); +BOOL WINAPI EnumDeviceDrivers(LPVOID *,DWORD,LPDWORD); +DWORD WINAPI GetDeviceDriverBaseNameA(LPVOID,LPSTR,DWORD); +DWORD WINAPI GetDeviceDriverBaseNameW(LPVOID,LPWSTR,DWORD); +DWORD WINAPI GetDeviceDriverFileNameA(LPVOID,LPSTR,DWORD); +DWORD WINAPI GetDeviceDriverFileNameW(LPVOID,LPWSTR,DWORD); +BOOL WINAPI GetProcessMemoryInfo(HANDLE,PPROCESS_MEMORY_COUNTERS,DWORD); + +#endif /* not RC_INVOKED */ + +#ifdef UNICODE +#define GetModuleBaseName GetModuleBaseNameW +#define GetModuleFileNameEx GetModuleFileNameExW +#define GetMappedFilenameEx GetMappedFilenameExW +#define GetDeviceDriverBaseName GetDeviceDriverBaseNameW +#define GetDeviceDriverFileName GetDeviceDriverFileNameW +#else +#define GetModuleBaseName GetModuleBaseNameA +#define GetModuleFileNameEx GetModuleFileNameExA +#define GetMappedFilenameEx GetMappedFilenameExA +#define GetDeviceDriverBaseName GetDeviceDriverBaseNameA +#define GetDeviceDriverFileName GetDeviceDriverFileNameA +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _PSAPI_H */ + diff --git a/windows/JackRouter/resource.h b/windows/JackRouter/resource.h new file mode 100644 index 00000000..673206e6 --- /dev/null +++ b/windows/JackRouter/resource.h @@ -0,0 +1,15 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by resource.rc +// + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/windows/JackRouter/resource.rc b/windows/JackRouter/resource.rc new file mode 100644 index 00000000..4289ddc2 --- /dev/null +++ b/windows/JackRouter/resource.rc @@ -0,0 +1,109 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// French (France) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_FRA) +#ifdef _WIN32 +LANGUAGE LANG_FRENCH, SUBLANG_FRENCH +#pragma code_page(1252) +#endif //_WIN32 + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 0,2,0,0 + PRODUCTVERSION 0,2,0,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040c04b0" + BEGIN + VALUE "Comments", "\0" + VALUE "CompanyName", "Grame\0" + VALUE "FileDescription", "JackRouter ASIO driver\0" + VALUE "FileVersion", "0, 2, 0, 0\0" + VALUE "InternalName", "JackRouter\0" + VALUE "LegalCopyright", "Copyright Grame © 2006-2009\0" + VALUE "LegalTrademarks", "\0" + VALUE "OriginalFilename", "JackRouter.dll\0" + VALUE "PrivateBuild", "\0" + VALUE "ProductName", "JackRouter\0" + VALUE "ProductVersion", "0, 2, 0, 0\0" + VALUE "SpecialBuild", "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x40c, 1200 + END +END + +#endif // !_MAC + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // French (France) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED +