git-svn-id: http://subversion.jackaudio.org/jack/jack2/branches/libjacknet@3503 0c269be4-1314-0410-8aa9-9f06e86f4224tags/1.9.8
@@ -25,6 +25,10 @@ Paul Davis | |||||
Jackdmp changes log | Jackdmp changes log | ||||
--------------------------- | --------------------------- | ||||
2009-04-08 Stephane Letz <letz@grame.fr> | |||||
* Native MIDI backend (JackCoreMidiDriver, JackWinMMEDriver) in progress. | |||||
2009-04-03 Stephane Letz <letz@grame.fr> | 2009-04-03 Stephane Letz <letz@grame.fr> | ||||
* Simplify JackClient RT code, jack_thread_wait API marked deprecated." | * Simplify JackClient RT code, jack_thread_wait API marked deprecated." | ||||
@@ -78,7 +78,8 @@ namespace Jack | |||||
fprintf(file, "set multiplot\n"); | fprintf(file, "set multiplot\n"); | ||||
fprintf(file, "set grid\n"); | fprintf(file, "set grid\n"); | ||||
fprintf(file, "set title \"Audio adapter timing\"\n"); | |||||
fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n" | |||||
,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize); | |||||
fprintf(file, "set xlabel \"audio cycles\"\n"); | fprintf(file, "set xlabel \"audio cycles\"\n"); | ||||
fprintf(file, "set ylabel \"frames\"\n"); | fprintf(file, "set ylabel \"frames\"\n"); | ||||
fprintf(file, "plot "); | fprintf(file, "plot "); | ||||
@@ -109,7 +110,8 @@ namespace Jack | |||||
fprintf(file, "set multiplot\n"); | fprintf(file, "set multiplot\n"); | ||||
fprintf(file, "set grid\n"); | fprintf(file, "set grid\n"); | ||||
fprintf(file, "set title \"Audio adapter timing\"\n"); | |||||
fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n" | |||||
,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize); | |||||
fprintf(file, "set xlabel \"audio cycles\"\n"); | fprintf(file, "set xlabel \"audio cycles\"\n"); | ||||
fprintf(file, "set ylabel \"resampling ratio\"\n"); | fprintf(file, "set ylabel \"resampling ratio\"\n"); | ||||
fprintf(file, "plot "); | fprintf(file, "plot "); | ||||
@@ -140,7 +142,8 @@ namespace Jack | |||||
fprintf(file, "set multiplot\n"); | fprintf(file, "set multiplot\n"); | ||||
fprintf(file, "set grid\n"); | fprintf(file, "set grid\n"); | ||||
fprintf(file, "set title \"Audio adapter timing\"\n"); | |||||
fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n" | |||||
,float(fHostSampleRate)/1000.f, fHostBufferSize, float(fAdaptedSampleRate)/1000.f, fAdaptedBufferSize); | |||||
fprintf(file, "set xlabel \"audio cycles\"\n"); | fprintf(file, "set xlabel \"audio cycles\"\n"); | ||||
fprintf(file, "set ylabel \"frames\"\n"); | fprintf(file, "set ylabel \"frames\"\n"); | ||||
fprintf(file, "plot "); | fprintf(file, "plot "); | ||||
@@ -1,6 +1,6 @@ | |||||
/* | /* | ||||
Copyright (C) 2001 Paul Davis | Copyright (C) 2001 Paul Davis | ||||
Copyright (C) 2004-2008 GramefClientControl. | |||||
Copyright (C) 2004-2008 Grame. | |||||
This program is free software; you can redistribute it and/or modify | 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 | it under the terms of the GNU General Public License as published by | ||||
@@ -120,12 +120,12 @@ void JackClient::SetupDriverSync(bool freewheel) | |||||
jack_log("JackClient::SetupDriverSync driver sem in flush mode"); | jack_log("JackClient::SetupDriverSync driver sem in flush mode"); | ||||
fSynchroTable[AUDIO_DRIVER_REFNUM].SetFlush(true); | fSynchroTable[AUDIO_DRIVER_REFNUM].SetFlush(true); | ||||
fSynchroTable[FREEWHEEL_DRIVER_REFNUM].SetFlush(true); | fSynchroTable[FREEWHEEL_DRIVER_REFNUM].SetFlush(true); | ||||
fSynchroTable[LOOPBACK_DRIVER_REFNUM].SetFlush(true); | |||||
fSynchroTable[MIDI_DRIVER_REFNUM].SetFlush(true); | |||||
} else { | } else { | ||||
jack_log("JackClient::SetupDriverSync driver sem in normal mode"); | jack_log("JackClient::SetupDriverSync driver sem in normal mode"); | ||||
fSynchroTable[AUDIO_DRIVER_REFNUM].SetFlush(false); | fSynchroTable[AUDIO_DRIVER_REFNUM].SetFlush(false); | ||||
fSynchroTable[FREEWHEEL_DRIVER_REFNUM].SetFlush(false); | fSynchroTable[FREEWHEEL_DRIVER_REFNUM].SetFlush(false); | ||||
fSynchroTable[LOOPBACK_DRIVER_REFNUM].SetFlush(false); | |||||
fSynchroTable[MIDI_DRIVER_REFNUM].SetFlush(false); | |||||
} | } | ||||
} | } | ||||
@@ -58,8 +58,8 @@ bool JackConnectionManager::IsLoopPathAux(int ref1, int ref2) const | |||||
|| ref2 == AUDIO_DRIVER_REFNUM | || ref2 == AUDIO_DRIVER_REFNUM | ||||
|| ref1 == FREEWHEEL_DRIVER_REFNUM | || ref1 == FREEWHEEL_DRIVER_REFNUM | ||||
|| ref2 == FREEWHEEL_DRIVER_REFNUM | || ref2 == FREEWHEEL_DRIVER_REFNUM | ||||
|| ref1 == LOOPBACK_DRIVER_REFNUM | |||||
|| ref2 == LOOPBACK_DRIVER_REFNUM) { | |||||
|| ref1 == MIDI_DRIVER_REFNUM | |||||
|| ref2 == MIDI_DRIVER_REFNUM) { | |||||
return false; | return false; | ||||
} else if (ref1 == ref2) { // Same refnum | } else if (ref1 == ref2) { // Same refnum | ||||
return true; | return true; | ||||
@@ -47,10 +47,10 @@ | |||||
#define CLIENT_NUM 64 | #define CLIENT_NUM 64 | ||||
#endif | #endif | ||||
#define AUDIO_DRIVER_REFNUM 0 // Audio driver is initialized first, it will get the refnum 0 | |||||
#define FREEWHEEL_DRIVER_REFNUM 1 // Freewheel driver is initialized second, it will get the refnum 1 | |||||
#define LOOPBACK_DRIVER_REFNUM 2 // Loopback driver is initialized third, it will get the refnum 2 | |||||
#define REAL_REFNUM LOOPBACK_DRIVER_REFNUM + 1 // Real clients start at LOOPBACK_DRIVER_REFNUM + 1 | |||||
#define AUDIO_DRIVER_REFNUM 0 // Audio driver is initialized first, it will get the refnum 0 | |||||
#define FREEWHEEL_DRIVER_REFNUM 1 // Freewheel driver is initialized second, it will get the refnum 1 | |||||
#define MIDI_DRIVER_REFNUM 2 // Loopback driver is initialized third, it will get the refnum 2 | |||||
#define REAL_REFNUM MIDI_DRIVER_REFNUM + 1 // Real clients start at MIDI_DRIVER_REFNUM + 1 | |||||
#define JACK_DEFAULT_SERVER_NAME "default" | #define JACK_DEFAULT_SERVER_NAME "default" | ||||
@@ -42,6 +42,7 @@ | |||||
#include "JackControlAPI.h" | #include "JackControlAPI.h" | ||||
#include "JackLockedEngine.h" | #include "JackLockedEngine.h" | ||||
#include "JackConstants.h" | #include "JackConstants.h" | ||||
#include "JackDriverLoader.h" | |||||
using namespace Jack; | using namespace Jack; | ||||
@@ -95,6 +96,7 @@ struct jackctl_driver | |||||
jack_driver_desc_t * desc_ptr; | jack_driver_desc_t * desc_ptr; | ||||
JSList * parameters; | JSList * parameters; | ||||
JSList * set_parameters; | JSList * set_parameters; | ||||
JackDriverInfo* info; | |||||
}; | }; | ||||
struct jackctl_internal | struct jackctl_internal | ||||
@@ -1161,4 +1163,23 @@ EXPORT bool jackctl_server_unload_internal( | |||||
} | } | ||||
} | } | ||||
EXPORT bool jackctl_server_load_slave(jackctl_server * server_ptr, jackctl_driver * driver_ptr) | |||||
{ | |||||
if (server_ptr->engine != NULL) { | |||||
driver_ptr->info = server_ptr->engine->AddSlave(driver_ptr->desc_ptr, driver_ptr->set_parameters); | |||||
return (driver_ptr->info != 0); | |||||
} else { | |||||
return false; | |||||
} | |||||
} | |||||
EXPORT bool jackctl_server_unload_slave(jackctl_server * server_ptr, jackctl_driver * driver_ptr) | |||||
{ | |||||
if (server_ptr->engine != NULL) { | |||||
server_ptr->engine->RemoveSlave(driver_ptr->info); | |||||
return true; | |||||
} else { | |||||
return false; | |||||
} | |||||
} | |||||
@@ -219,6 +219,13 @@ EXPORT bool jackctl_server_load_internal( | |||||
EXPORT bool jackctl_server_unload_internal( | EXPORT bool jackctl_server_unload_internal( | ||||
jackctl_server * server, | jackctl_server * server, | ||||
jackctl_internal * internal); | jackctl_internal * internal); | ||||
EXPORT bool jackctl_server_load_slave(jackctl_server_t * server, | |||||
jackctl_driver_t * driver); | |||||
EXPORT bool jackctl_server_unload_slave(jackctl_server_t * server, | |||||
jackctl_driver_t * driver); | |||||
#if 0 | #if 0 | ||||
{ /* Adjust editor indent */ | { /* Adjust editor indent */ | ||||
@@ -68,7 +68,7 @@ int JackDriver::Open() | |||||
int refnum = -1; | int refnum = -1; | ||||
if (fEngine->ClientInternalOpen(fClientControl.fName, &refnum, &fEngineControl, &fGraphManager, this, false) != 0) { | if (fEngine->ClientInternalOpen(fClientControl.fName, &refnum, &fEngineControl, &fGraphManager, this, false) != 0) { | ||||
jack_error("Cannot allocate internal client for audio driver"); | |||||
jack_error("Cannot allocate internal client for driver"); | |||||
return -1; | return -1; | ||||
} | } | ||||
@@ -79,6 +79,46 @@ int JackDriver::Open() | |||||
return 0; | return 0; | ||||
} | } | ||||
int JackDriver::Open (bool capturing, | |||||
bool playing, | |||||
int inchannels, | |||||
int outchannels, | |||||
bool monitor, | |||||
const char* capture_driver_name, | |||||
const char* playback_driver_name, | |||||
jack_nframes_t capture_latency, | |||||
jack_nframes_t playback_latency) | |||||
{ | |||||
jack_log("JackDriver::Open capture_driver_name = %s", capture_driver_name); | |||||
jack_log("JackDriver::Open playback_driver_name = %s", playback_driver_name); | |||||
int refnum = -1; | |||||
if (fEngine->ClientInternalOpen(fClientControl.fName, &refnum, &fEngineControl, &fGraphManager, this, false) != 0) { | |||||
jack_error("Cannot allocate internal client for driver"); | |||||
return -1; | |||||
} | |||||
fClientControl.fRefNum = refnum; | |||||
fClientControl.fActive = true; | |||||
fCaptureLatency = capture_latency; | |||||
fPlaybackLatency = playback_latency; | |||||
assert(strlen(capture_driver_name) < JACK_CLIENT_NAME_SIZE); | |||||
assert(strlen(playback_driver_name) < JACK_CLIENT_NAME_SIZE); | |||||
strcpy(fCaptureDriverName, capture_driver_name); | |||||
strcpy(fPlaybackDriverName, playback_driver_name); | |||||
fEngineControl->fPeriodUsecs = jack_time_t(1000000.f / fEngineControl->fSampleRate * fEngineControl->fBufferSize); // in microsec | |||||
if (!fEngineControl->fTimeOut) | |||||
fEngineControl->fTimeOutUsecs = jack_time_t(2.f * fEngineControl->fPeriodUsecs); | |||||
//fGraphManager->SetBufferSize(fEngineControl->fBufferSize); | |||||
fGraphManager->DirectConnect(fClientControl.fRefNum, fClientControl.fRefNum); // Connect driver to itself for "sync" mode | |||||
SetupDriverSync(fClientControl.fRefNum, false); | |||||
return 0; | |||||
} | |||||
int JackDriver::Open(jack_nframes_t buffer_size, | int JackDriver::Open(jack_nframes_t buffer_size, | ||||
jack_nframes_t samplerate, | jack_nframes_t samplerate, | ||||
bool capturing, | bool capturing, | ||||
@@ -96,7 +136,7 @@ int JackDriver::Open(jack_nframes_t buffer_size, | |||||
int refnum = -1; | int refnum = -1; | ||||
if (fEngine->ClientInternalOpen(fClientControl.fName, &refnum, &fEngineControl, &fGraphManager, this, false) != 0) { | if (fEngine->ClientInternalOpen(fClientControl.fName, &refnum, &fEngineControl, &fGraphManager, this, false) != 0) { | ||||
jack_error("Cannot allocate internal client for audio driver"); | |||||
jack_error("Cannot allocate internal client for driver"); | |||||
return -1; | return -1; | ||||
} | } | ||||
@@ -50,6 +50,17 @@ class SERVER_EXPORT JackDriverInterface | |||||
{} | {} | ||||
virtual int Open() = 0; | virtual int Open() = 0; | ||||
virtual int Open (bool capturing, | |||||
bool playing, | |||||
int inchannels, | |||||
int outchannels, | |||||
bool monitor, | |||||
const char* capture_driver_name, | |||||
const char* playback_driver_name, | |||||
jack_nframes_t capture_latency, | |||||
jack_nframes_t playback_latency) = 0; | |||||
virtual int Open(jack_nframes_t buffer_size, | virtual int Open(jack_nframes_t buffer_size, | ||||
jack_nframes_t samplerate, | jack_nframes_t samplerate, | ||||
bool capturing, | bool capturing, | ||||
@@ -142,6 +153,17 @@ class SERVER_EXPORT JackDriver : public JackDriverClientInterface | |||||
int ProcessSlaves(); | int ProcessSlaves(); | ||||
virtual int Open(); | virtual int Open(); | ||||
virtual int Open (bool capturing, | |||||
bool playing, | |||||
int inchannels, | |||||
int outchannels, | |||||
bool monitor, | |||||
const char* capture_driver_name, | |||||
const char* playback_driver_name, | |||||
jack_nframes_t capture_latency, | |||||
jack_nframes_t playback_latency); | |||||
virtual int Open(jack_nframes_t buffer_size, | virtual int Open(jack_nframes_t buffer_size, | ||||
jack_nframes_t samplerate, | jack_nframes_t samplerate, | ||||
bool capturing, | bool capturing, | ||||
@@ -800,7 +800,8 @@ Jack::JackDriverClientInterface* JackDriverInfo::Open(jack_driver_desc_t* driver | |||||
jack_error("no initialize function in shared object %s\n", driver_desc->file); | jack_error("no initialize function in shared object %s\n", driver_desc->file); | ||||
return NULL; | return NULL; | ||||
} | } | ||||
return fInitialize(engine, synchro, params); | |||||
fBackend = fInitialize(engine, synchro, params); | |||||
return fBackend; | |||||
} | } | ||||
@@ -42,6 +42,7 @@ class JackDriverInfo | |||||
driverInitialize fInitialize; | driverInitialize fInitialize; | ||||
DRIVER_HANDLE fHandle; | DRIVER_HANDLE fHandle; | ||||
Jack::JackDriverClientInterface* fBackend; | |||||
public: | public: | ||||
@@ -54,6 +55,11 @@ class JackDriverInfo | |||||
} | } | ||||
Jack::JackDriverClientInterface* Open(jack_driver_desc_t* driver_desc, Jack::JackLockedEngine*, Jack::JackSynchro*, const JSList*); | Jack::JackDriverClientInterface* Open(jack_driver_desc_t* driver_desc, Jack::JackLockedEngine*, Jack::JackSynchro*, const JSList*); | ||||
Jack::JackDriverClientInterface* GetBackend() | |||||
{ | |||||
return fBackend; | |||||
} | |||||
}; | }; | ||||
@@ -0,0 +1,181 @@ | |||||
/* | |||||
Copyright (C) 2009 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 | |||||
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 | |||||
(at your option) any later version. | |||||
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. | |||||
*/ | |||||
#include "JackSystemDeps.h" | |||||
#include "JackMidiDriver.h" | |||||
#include "JackTime.h" | |||||
#include "JackError.h" | |||||
#include "JackEngineControl.h" | |||||
#include "JackPort.h" | |||||
#include "JackGraphManager.h" | |||||
#include "JackException.h" | |||||
#include <assert.h> | |||||
namespace Jack | |||||
{ | |||||
JackMidiDriver::JackMidiDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table) | |||||
: JackDriver(name, alias, engine, table), | |||||
fCaptureChannels(0), | |||||
fPlaybackChannels(0) | |||||
{ | |||||
for (int i = 0; i < DRIVER_PORT_NUM; i++) { | |||||
fRingBuffer[i] = NULL; | |||||
} | |||||
} | |||||
JackMidiDriver::~JackMidiDriver() | |||||
{ | |||||
for (int i = 0; i < fCaptureChannels; i++) { | |||||
if (fRingBuffer[i]) | |||||
jack_ringbuffer_free(fRingBuffer[i]); | |||||
} | |||||
} | |||||
int JackMidiDriver::Open(bool capturing, | |||||
bool playing, | |||||
int inchannels, | |||||
int outchannels, | |||||
bool monitor, | |||||
const char* capture_driver_name, | |||||
const char* playback_driver_name, | |||||
jack_nframes_t capture_latency, | |||||
jack_nframes_t playback_latency) | |||||
{ | |||||
fCaptureChannels = inchannels; | |||||
fPlaybackChannels = outchannels; | |||||
for (int i = 0; i < fCaptureChannels; i++) { | |||||
fRingBuffer[i] = jack_ringbuffer_create(sizeof(float) * BUFFER_SIZE_MAX); | |||||
} | |||||
return JackDriver::Open(capturing, playing, inchannels, outchannels, monitor, capture_driver_name, playback_driver_name, capture_latency, playback_latency); | |||||
} | |||||
int JackMidiDriver::Attach() | |||||
{ | |||||
JackPort* port; | |||||
jack_port_id_t port_index; | |||||
char name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; | |||||
char alias[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; | |||||
unsigned long port_flags = JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal; | |||||
int i; | |||||
jack_log("JackMidiDriver::Attach fBufferSize = %ld fSampleRate = %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate); | |||||
for (i = 0; i < fCaptureChannels; i++) { | |||||
snprintf(alias, sizeof(alias) - 1, "%s:%s:out%d", fAliasName, fCaptureDriverName, i + 1); | |||||
snprintf(name, sizeof(name) - 1, "%s:capture_%d", fClientControl.fName, i + 1); | |||||
if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE, (JackPortFlags)port_flags, fEngineControl->fBufferSize)) == NO_PORT) { | |||||
jack_error("driver: cannot register port for %s", name); | |||||
return -1; | |||||
} | |||||
port = fGraphManager->GetPort(port_index); | |||||
port->SetAlias(alias); | |||||
fCapturePortList[i] = port_index; | |||||
jack_log("JackMidiDriver::Attach fCapturePortList[i] port_index = %ld", port_index); | |||||
} | |||||
port_flags = JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal; | |||||
for (i = 0; i < fPlaybackChannels; i++) { | |||||
snprintf(alias, sizeof(alias) - 1, "%s:%s:in%d", fAliasName, fPlaybackDriverName, i + 1); | |||||
snprintf(name, sizeof(name) - 1, "%s:playback_%d", fClientControl.fName, i + 1); | |||||
if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE, (JackPortFlags)port_flags, fEngineControl->fBufferSize)) == NO_PORT) { | |||||
jack_error("driver: cannot register port for %s", name); | |||||
return -1; | |||||
} | |||||
port = fGraphManager->GetPort(port_index); | |||||
port->SetAlias(alias); | |||||
fPlaybackPortList[i] = port_index; | |||||
jack_log("JackMidiDriver::Attach fPlaybackPortList[i] port_index = %ld", port_index); | |||||
} | |||||
return 0; | |||||
} | |||||
int JackMidiDriver::Detach() | |||||
{ | |||||
int i; | |||||
jack_log("JackMidiDriver::Detach"); | |||||
for (i = 0; i < fCaptureChannels; i++) { | |||||
fGraphManager->ReleasePort(fClientControl.fRefNum, fCapturePortList[i]); | |||||
} | |||||
for (i = 0; i < fPlaybackChannels; i++) { | |||||
fGraphManager->ReleasePort(fClientControl.fRefNum, fPlaybackPortList[i]); | |||||
} | |||||
return 0; | |||||
} | |||||
int JackMidiDriver::Read() | |||||
{ | |||||
return 0; | |||||
} | |||||
int JackMidiDriver::Write() | |||||
{ | |||||
return 0; | |||||
} | |||||
int JackMidiDriver::ProcessNull() | |||||
{ | |||||
return 0; | |||||
} | |||||
int JackMidiDriver::Process() | |||||
{ | |||||
// Read input buffers for the current cycle | |||||
if (Read() < 0) { | |||||
jack_error("JackMidiDriver::Process: read error, skip cycle"); | |||||
return 0; // Skip cycle, but continue processing... | |||||
} | |||||
fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable); | |||||
if (fEngineControl->fSyncMode) { | |||||
if (fGraphManager->SuspendRefNum(&fClientControl, fSynchroTable, fEngineControl->fTimeOutUsecs) < 0) { | |||||
jack_error("JackFreewheelDriver::ProcessSync SuspendRefNum error"); | |||||
return -1; | |||||
} | |||||
} | |||||
// Write output buffers for the current cycle | |||||
if (Write() < 0) { | |||||
jack_error("JackMidiDriver::Process: write error, skip cycle"); | |||||
return 0; // Skip cycle, but continue processing... | |||||
} | |||||
return 0; | |||||
} | |||||
JackMidiBuffer* JackMidiDriver::GetInputBuffer(int port_index) | |||||
{ | |||||
assert(fCapturePortList[port_index]); | |||||
return (JackMidiBuffer*)fGraphManager->GetBuffer(fCapturePortList[port_index], fEngineControl->fBufferSize); | |||||
} | |||||
JackMidiBuffer* JackMidiDriver::GetOutputBuffer(int port_index) | |||||
{ | |||||
assert(fPlaybackPortList[port_index]); | |||||
return (JackMidiBuffer*)fGraphManager->GetBuffer(fPlaybackPortList[port_index], fEngineControl->fBufferSize); | |||||
} | |||||
} // end of namespace |
@@ -0,0 +1,79 @@ | |||||
/* | |||||
Copyright (C) 2009 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 __JackMidiDriver__ | |||||
#define __JackMidiDriver__ | |||||
#include "JackDriver.h" | |||||
#include "JackMidiPort.h" | |||||
#include "JackLockedEngine.h" | |||||
#include "ringbuffer.h" | |||||
namespace Jack | |||||
{ | |||||
/*! | |||||
\brief The base class for MIDI drivers: drivers with MIDI ports. | |||||
*/ | |||||
class SERVER_EXPORT JackMidiDriver : public JackDriver | |||||
{ | |||||
protected: | |||||
int fCaptureChannels; | |||||
int fPlaybackChannels; | |||||
jack_ringbuffer_t* fRingBuffer[DRIVER_PORT_NUM]; | |||||
jack_port_id_t fCapturePortList[DRIVER_PORT_NUM]; | |||||
jack_port_id_t fPlaybackPortList[DRIVER_PORT_NUM]; | |||||
JackMidiBuffer* GetInputBuffer(int port_index); | |||||
JackMidiBuffer* GetOutputBuffer(int port_index); | |||||
public: | |||||
JackMidiDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table); | |||||
virtual ~JackMidiDriver(); | |||||
virtual int Open(bool capturing, | |||||
bool playing, | |||||
int inchannels, | |||||
int outchannels, | |||||
bool monitor, | |||||
const char* capture_driver_name, | |||||
const char* playback_driver_name, | |||||
jack_nframes_t capture_latency, | |||||
jack_nframes_t playback_latency); | |||||
virtual int Process(); | |||||
virtual int ProcessNull(); | |||||
virtual int Attach(); | |||||
virtual int Detach(); | |||||
virtual int Read(); | |||||
virtual int Write(); | |||||
}; | |||||
} // end of namespace | |||||
#endif |
@@ -27,7 +27,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
namespace Jack | namespace Jack | ||||
{ | { | ||||
void JackMidiBuffer::Reset(jack_nframes_t nframes) | |||||
SERVER_EXPORT void JackMidiBuffer::Reset(jack_nframes_t nframes) | |||||
{ | { | ||||
/* This line ate 1 hour of my life... dsbaikov */ | /* This line ate 1 hour of my life... dsbaikov */ | ||||
this->nframes = nframes; | this->nframes = nframes; | ||||
@@ -37,7 +37,7 @@ void JackMidiBuffer::Reset(jack_nframes_t nframes) | |||||
mix_index = 0; | mix_index = 0; | ||||
} | } | ||||
jack_shmsize_t JackMidiBuffer::MaxEventSize() const | |||||
SERVER_EXPORT jack_shmsize_t JackMidiBuffer::MaxEventSize() const | |||||
{ | { | ||||
assert (((jack_shmsize_t) - 1) < 0); // jack_shmsize_t should be signed | assert (((jack_shmsize_t) - 1) < 0); // jack_shmsize_t should be signed | ||||
jack_shmsize_t left = buffer_size - (sizeof(JackMidiBuffer) + sizeof(JackMidiEvent) * (event_count + 1) + write_pos); | jack_shmsize_t left = buffer_size - (sizeof(JackMidiBuffer) + sizeof(JackMidiEvent) * (event_count + 1) + write_pos); | ||||
@@ -48,7 +48,7 @@ jack_shmsize_t JackMidiBuffer::MaxEventSize() const | |||||
return left; | return left; | ||||
} | } | ||||
jack_midi_data_t* JackMidiBuffer::ReserveEvent(jack_nframes_t time, jack_shmsize_t size) | |||||
SERVER_EXPORT jack_midi_data_t* JackMidiBuffer::ReserveEvent(jack_nframes_t time, jack_shmsize_t size) | |||||
{ | { | ||||
jack_shmsize_t space = MaxEventSize(); | jack_shmsize_t space = MaxEventSize(); | ||||
if (space == 0 || size > space) { | if (space == 0 || size > space) { | ||||
@@ -23,6 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
#include "types.h" | #include "types.h" | ||||
#include "JackConstants.h" | #include "JackConstants.h" | ||||
#include "JackPlatformPlug.h" | |||||
#include <stddef.h> | #include <stddef.h> | ||||
/** Type for raw event data contained in @ref jack_midi_event_t. */ | /** Type for raw event data contained in @ref jack_midi_event_t. */ | ||||
@@ -42,7 +43,7 @@ struct jack_midi_event_t | |||||
namespace Jack | namespace Jack | ||||
{ | { | ||||
struct JackMidiEvent | |||||
struct SERVER_EXPORT JackMidiEvent | |||||
{ | { | ||||
// Most MIDI events are < 4 bytes in size, so we can save a lot, storing them inplace. | // Most MIDI events are < 4 bytes in size, so we can save a lot, storing them inplace. | ||||
enum { INLINE_SIZE_MAX = sizeof(jack_shmsize_t) }; | enum { INLINE_SIZE_MAX = sizeof(jack_shmsize_t) }; | ||||
@@ -22,7 +22,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
#include "JackServerGlobals.h" | #include "JackServerGlobals.h" | ||||
#include "JackTime.h" | #include "JackTime.h" | ||||
#include "JackFreewheelDriver.h" | #include "JackFreewheelDriver.h" | ||||
#include "JackLoopbackDriver.h" | |||||
#include "JackThreadedDriver.h" | #include "JackThreadedDriver.h" | ||||
#include "JackGlobals.h" | #include "JackGlobals.h" | ||||
#include "JackLockedEngine.h" | #include "JackLockedEngine.h" | ||||
@@ -50,10 +49,8 @@ JackServer::JackServer(bool sync, bool temporary, long timeout, bool rt, long pr | |||||
fEngineControl = new JackEngineControl(sync, temporary, timeout, rt, priority, verbose, server_name); | fEngineControl = new JackEngineControl(sync, temporary, timeout, rt, priority, verbose, server_name); | ||||
fEngine = new JackLockedEngine(fGraphManager, GetSynchroTable(), fEngineControl); | fEngine = new JackLockedEngine(fGraphManager, GetSynchroTable(), fEngineControl); | ||||
fFreewheelDriver = new JackThreadedDriver(new JackFreewheelDriver(fEngine, GetSynchroTable())); | fFreewheelDriver = new JackThreadedDriver(new JackFreewheelDriver(fEngine, GetSynchroTable())); | ||||
fLoopbackDriver = new JackLoopbackDriver(fEngine, GetSynchroTable()); | |||||
fAudioDriver = NULL; | fAudioDriver = NULL; | ||||
fFreewheel = false; | fFreewheel = false; | ||||
fLoopback = loopback; | |||||
JackServerGlobals::fInstance = this; // Unique instance | JackServerGlobals::fInstance = this; // Unique instance | ||||
JackServerGlobals::fUserCount = 1; // One user | JackServerGlobals::fUserCount = 1; // One user | ||||
jack_verbose = verbose; | jack_verbose = verbose; | ||||
@@ -64,7 +61,6 @@ JackServer::~JackServer() | |||||
delete fGraphManager; | delete fGraphManager; | ||||
delete fAudioDriver; | delete fAudioDriver; | ||||
delete fFreewheelDriver; | delete fFreewheelDriver; | ||||
delete fLoopbackDriver; | |||||
delete fEngine; | delete fEngine; | ||||
delete fEngineControl; | delete fEngineControl; | ||||
} | } | ||||
@@ -94,35 +90,17 @@ int JackServer::Open(jack_driver_desc_t* driver_desc, JSList* driver_params) | |||||
goto fail_close4; | goto fail_close4; | ||||
} | } | ||||
if (fLoopbackDriver->Open(fEngineControl->fBufferSize, fEngineControl->fSampleRate, 1, 1, fLoopback, fLoopback, false, "loopback", "loopback", 0, 0) != 0) { | |||||
jack_error("Cannot open driver"); | |||||
goto fail_close5; | |||||
} | |||||
if (fAudioDriver->Attach() != 0) { | if (fAudioDriver->Attach() != 0) { | ||||
jack_error("Cannot attach audio driver"); | jack_error("Cannot attach audio driver"); | ||||
goto fail_close6; | |||||
} | |||||
if (fLoopback > 0 && fLoopbackDriver->Attach() != 0) { | |||||
jack_error("Cannot attach loopback driver"); | |||||
goto fail_close7; | |||||
goto fail_close5; | |||||
} | } | ||||
fFreewheelDriver->SetMaster(false); | fFreewheelDriver->SetMaster(false); | ||||
fAudioDriver->SetMaster(true); | fAudioDriver->SetMaster(true); | ||||
if (fLoopback > 0) | |||||
fAudioDriver->AddSlave(fLoopbackDriver); | |||||
fAudioDriver->AddSlave(fFreewheelDriver); // After ??? | fAudioDriver->AddSlave(fFreewheelDriver); // After ??? | ||||
InitTime(); | InitTime(); | ||||
return 0; | return 0; | ||||
fail_close7: | |||||
fAudioDriver->Detach(); | |||||
fail_close6: | |||||
fLoopbackDriver->Close(); | |||||
fail_close5: | fail_close5: | ||||
fFreewheelDriver->Close(); | fFreewheelDriver->Close(); | ||||
@@ -145,11 +123,8 @@ int JackServer::Close() | |||||
jack_log("JackServer::Close"); | jack_log("JackServer::Close"); | ||||
fChannel.Close(); | fChannel.Close(); | ||||
fAudioDriver->Detach(); | fAudioDriver->Detach(); | ||||
if (fLoopback > 0) | |||||
fLoopbackDriver->Detach(); | |||||
fAudioDriver->Close(); | fAudioDriver->Close(); | ||||
fFreewheelDriver->Close(); | fFreewheelDriver->Close(); | ||||
fLoopbackDriver->Close(); | |||||
fEngine->Close(); | fEngine->Close(); | ||||
// TODO: move that in reworked JackServerGlobals::Destroy() | // TODO: move that in reworked JackServerGlobals::Destroy() | ||||
JackMessageBuffer::Destroy(); | JackMessageBuffer::Destroy(); | ||||
@@ -305,6 +280,32 @@ void JackServer::ClientKill(int refnum) | |||||
} | } | ||||
} | } | ||||
//---------------------- | |||||
// Backend management | |||||
//---------------------- | |||||
JackDriverInfo* JackServer::AddSlave(jack_driver_desc_t* driver_desc, JSList* driver_params) | |||||
{ | |||||
JackDriverInfo* info = new JackDriverInfo(); | |||||
JackDriverClientInterface* backend = info->Open(driver_desc, fEngine, GetSynchroTable(), driver_params); | |||||
if (backend == NULL) { | |||||
delete info; | |||||
return NULL; | |||||
} else { | |||||
backend->Attach(); | |||||
fAudioDriver->AddSlave(backend); | |||||
return info; | |||||
} | |||||
} | |||||
void JackServer::RemoveSlave(JackDriverInfo* info) | |||||
{ | |||||
JackDriverClientInterface* backend = info->GetBackend(); | |||||
fAudioDriver->RemoveSlave(info->GetBackend()); | |||||
backend->Detach(); | |||||
backend->Close(); | |||||
} | |||||
//---------------------- | //---------------------- | ||||
// Transport management | // Transport management | ||||
//---------------------- | //---------------------- | ||||
@@ -50,7 +50,6 @@ class SERVER_EXPORT JackServer | |||||
JackDriverInfo fDriverInfo; | JackDriverInfo fDriverInfo; | ||||
JackDriverClientInterface* fAudioDriver; | JackDriverClientInterface* fAudioDriver; | ||||
JackDriverClientInterface* fFreewheelDriver; | JackDriverClientInterface* fFreewheelDriver; | ||||
JackDriverClientInterface* fLoopbackDriver; | |||||
JackLockedEngine* fEngine; | JackLockedEngine* fEngine; | ||||
JackEngineControl* fEngineControl; | JackEngineControl* fEngineControl; | ||||
JackGraphManager* fGraphManager; | JackGraphManager* fGraphManager; | ||||
@@ -58,7 +57,6 @@ class SERVER_EXPORT JackServer | |||||
JackConnectionManager fConnectionState; | JackConnectionManager fConnectionState; | ||||
JackSynchro fSynchroTable[CLIENT_NUM]; | JackSynchro fSynchroTable[CLIENT_NUM]; | ||||
bool fFreewheel; | bool fFreewheel; | ||||
long fLoopback; | |||||
int InternalClientLoadAux(JackLoadableInternalClient* client, const char* so_name, const char* client_name, int options, int* int_ref, int* status); | int InternalClientLoadAux(JackLoadableInternalClient* client, const char* so_name, const char* client_name, int options, int* int_ref, int* status); | ||||
@@ -86,6 +84,10 @@ class SERVER_EXPORT JackServer | |||||
// Transport management | // Transport management | ||||
int ReleaseTimebase(int refnum); | int ReleaseTimebase(int refnum); | ||||
int SetTimebaseCallback(int refnum, int conditional); | int SetTimebaseCallback(int refnum, int conditional); | ||||
// Backend management | |||||
JackDriverInfo* AddSlave(jack_driver_desc_t* driver_desc, JSList* driver_params); | |||||
void RemoveSlave(JackDriverInfo* info); | |||||
// Object access | // Object access | ||||
JackLockedEngine* GetEngine(); | JackLockedEngine* GetEngine(); | ||||
@@ -45,6 +45,19 @@ class SERVER_EXPORT JackThreadedDriver : public JackDriverClientInterface, publi | |||||
virtual ~JackThreadedDriver(); | virtual ~JackThreadedDriver(); | ||||
virtual int Open(); | virtual int Open(); | ||||
virtual int Open (bool capturing, | |||||
bool playing, | |||||
int inchannels, | |||||
int outchannels, | |||||
bool monitor, | |||||
const char* capture_driver_name, | |||||
const char* playback_driver_name, | |||||
jack_nframes_t capture_latency, | |||||
jack_nframes_t playback_latency) | |||||
{ | |||||
return -1; | |||||
} | |||||
virtual int Open(jack_nframes_t buffer_size, | virtual int Open(jack_nframes_t buffer_size, | ||||
jack_nframes_t samplerate, | jack_nframes_t samplerate, | ||||
bool capturing, | bool capturing, | ||||
@@ -33,7 +33,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
#include "JackDriverLoader.h" | #include "JackDriverLoader.h" | ||||
/* | /* | ||||
This is a simple port of the old jackdmp.cpp file to use the new Jack 2.0 control API. Available options for the server | |||||
This is a simple port of the old jackdmp.cpp file to use the new Jack 2.0 control API. Available options for the server | |||||
are "hard-coded" in the source. A much better approach would be to use the control API to: | are "hard-coded" in the source. A much better approach would be to use the control API to: | ||||
- dynamically retrieve available server parameters and then prepare to parse them | - dynamically retrieve available server parameters and then prepare to parse them | ||||
- get available drivers and their possible parameters, then prepare to parse them. | - get available drivers and their possible parameters, then prepare to parse them. | ||||
@@ -58,7 +58,7 @@ static void notify_server_start(const char* server_name) | |||||
static void notify_server_stop(const char* server_name) | static void notify_server_stop(const char* server_name) | ||||
{ | { | ||||
// Send notification to be used in the JackRouter plugin | // Send notification to be used in the JackRouter plugin | ||||
CFStringRef ref1 = CFStringCreateWithCString(NULL, server_name, kCFStringEncodingMacRoman); | |||||
CFStringRef ref1 = CFStringCreateWithCString(NULL, server_name, kCFStringEncodingMacRoman); | |||||
CFNotificationCenterPostNotificationWithOptions(CFNotificationCenterGetDistributedCenter(), | CFNotificationCenterPostNotificationWithOptions(CFNotificationCenterGetDistributedCenter(), | ||||
CFSTR("com.grame.jackserver.stop"), | CFSTR("com.grame.jackserver.stop"), | ||||
ref1, | ref1, | ||||
@@ -95,14 +95,14 @@ static void usage(FILE* file) | |||||
"usage: jackdmp [ --realtime OR -R [ --realtime-priority OR -P priority ] ]\n" | "usage: jackdmp [ --realtime OR -R [ --realtime-priority OR -P priority ] ]\n" | ||||
" [ --name OR -n server-name ]\n" | " [ --name OR -n server-name ]\n" | ||||
" [ --timeout OR -t client-timeout-in-msecs ]\n" | " [ --timeout OR -t client-timeout-in-msecs ]\n" | ||||
" [ --loopback OR -L loopback-port-number ]\n" | |||||
" [ --midi OR -X midi-driver ]\n" | |||||
" [ --verbose OR -v ]\n" | " [ --verbose OR -v ]\n" | ||||
" [ --replace-registry OR -r ]\n" | " [ --replace-registry OR -r ]\n" | ||||
" [ --silent OR -s ]\n" | " [ --silent OR -s ]\n" | ||||
" [ --sync OR -S ]\n" | " [ --sync OR -S ]\n" | ||||
" [ --temporary OR -T ]\n" | " [ --temporary OR -T ]\n" | ||||
" [ --version OR -V ]\n" | " [ --version OR -V ]\n" | ||||
" -d driver [ ... driver args ... ]\n" | |||||
" -d audio-driver [ ... driver args ... ]\n" | |||||
" where driver can be `alsa', `coreaudio', 'portaudio' or `dummy'\n" | " where driver can be `alsa', `coreaudio', 'portaudio' or `dummy'\n" | ||||
" jackdmp -d driver --help\n" | " jackdmp -d driver --help\n" | ||||
" to display options for each driver\n\n"); | " to display options for each driver\n\n"); | ||||
@@ -154,10 +154,12 @@ int main(int argc, char* argv[]) | |||||
jackctl_server_t * server_ctl; | jackctl_server_t * server_ctl; | ||||
const JSList * server_parameters; | const JSList * server_parameters; | ||||
const char* server_name = "default"; | const char* server_name = "default"; | ||||
jackctl_driver_t * driver_ctl; | |||||
const char *options = "-ad:P:uvrshVRL:STFl:t:mn:p:"; | |||||
jackctl_driver_t * audio_driver_ctl; | |||||
jackctl_driver_t * midi_driver_ctl; | |||||
const char *options = "-ad:X:P:uvrshVRL:STFl:t:mn:p:"; | |||||
struct option long_options[] = { | struct option long_options[] = { | ||||
{ "driver", 1, 0, 'd' }, | |||||
{ "audio-driver", 1, 0, 'd' }, | |||||
{ "midi-driver", 1, 0, 'X' }, | |||||
{ "verbose", 0, 0, 'v' }, | { "verbose", 0, 0, 'v' }, | ||||
{ "help", 0, 0, 'h' }, | { "help", 0, 0, 'h' }, | ||||
{ "port-max", 1, 0, 'p' }, | { "port-max", 1, 0, 'p' }, | ||||
@@ -177,10 +179,14 @@ int main(int argc, char* argv[]) | |||||
}; | }; | ||||
int i,opt = 0; | int i,opt = 0; | ||||
int option_index = 0; | int option_index = 0; | ||||
bool seen_driver = false; | |||||
char *driver_name = NULL; | |||||
char **driver_args = NULL; | |||||
int driver_nargs = 1; | |||||
bool seen_audio_driver = false; | |||||
bool seen_midi_driver = false; | |||||
char *audio_driver_name = NULL; | |||||
char **audio_driver_args = NULL; | |||||
int audio_driver_nargs = 1; | |||||
char *midi_driver_name = NULL; | |||||
char **midi_driver_args = NULL; | |||||
int midi_driver_nargs = 1; | |||||
int port_max = 512; | int port_max = 512; | ||||
int do_mlock = 1; | int do_mlock = 1; | ||||
int do_unlock = 0; | int do_unlock = 0; | ||||
@@ -190,34 +196,39 @@ int main(int argc, char* argv[]) | |||||
union jackctl_parameter_value value; | union jackctl_parameter_value value; | ||||
copyright(stdout); | copyright(stdout); | ||||
server_ctl = jackctl_server_create(); | server_ctl = jackctl_server_create(); | ||||
if (server_ctl == NULL) { | if (server_ctl == NULL) { | ||||
fprintf(stderr, "Failed to create server object\n"); | fprintf(stderr, "Failed to create server object\n"); | ||||
return -1; | return -1; | ||||
} | } | ||||
server_parameters = jackctl_server_get_parameters(server_ctl); | server_parameters = jackctl_server_get_parameters(server_ctl); | ||||
opterr = 0; | opterr = 0; | ||||
while (!seen_driver && | |||||
while (!seen_audio_driver && | |||||
(opt = getopt_long(argc, argv, options, | (opt = getopt_long(argc, argv, options, | ||||
long_options, &option_index)) != EOF) { | long_options, &option_index)) != EOF) { | ||||
switch (opt) { | switch (opt) { | ||||
case 'd': | case 'd': | ||||
seen_driver = true; | |||||
driver_name = optarg; | |||||
seen_audio_driver = true; | |||||
audio_driver_name = optarg; | |||||
break; | break; | ||||
case 'X': | |||||
seen_midi_driver = true; | |||||
midi_driver_name = optarg; | |||||
break; | |||||
case 'p': | case 'p': | ||||
port_max = (unsigned int)atol(optarg); | port_max = (unsigned int)atol(optarg); | ||||
break; | break; | ||||
case 'm': | case 'm': | ||||
do_mlock = 0; | do_mlock = 0; | ||||
break; | break; | ||||
case 'u': | case 'u': | ||||
do_unlock = 1; | do_unlock = 1; | ||||
break; | break; | ||||
@@ -306,6 +317,7 @@ int main(int argc, char* argv[]) | |||||
default: | default: | ||||
fprintf(stderr, "unknown option character %c\n", optopt); | fprintf(stderr, "unknown option character %c\n", optopt); | ||||
/*fallthru*/ | /*fallthru*/ | ||||
case 'h': | case 'h': | ||||
usage(stdout); | usage(stdout); | ||||
goto fail_free; | goto fail_free; | ||||
@@ -313,61 +325,77 @@ int main(int argc, char* argv[]) | |||||
} | } | ||||
if (show_version) { | if (show_version) { | ||||
printf("jackdmp version" VERSION | |||||
"\n"); | |||||
printf( "jackdmp version " VERSION | |||||
" tmpdir " jack_server_dir | |||||
" protocol %d" | |||||
"\n", JACK_PROTOCOL_VERSION); | |||||
return -1; | return -1; | ||||
} | } | ||||
if (!seen_driver) { | |||||
if (!seen_audio_driver) { | |||||
usage(stderr); | usage(stderr); | ||||
goto fail_free; | goto fail_free; | ||||
} | } | ||||
driver_ctl = jackctl_server_get_driver(server_ctl, driver_name); | |||||
if (driver_ctl == NULL) { | |||||
fprintf(stderr, "Unkown driver \"%s\"\n", driver_name); | |||||
// Audio driver | |||||
audio_driver_ctl = jackctl_server_get_driver(server_ctl, audio_driver_name); | |||||
if (audio_driver_ctl == NULL) { | |||||
fprintf(stderr, "Unkown driver \"%s\"\n", audio_driver_name); | |||||
goto fail_free; | goto fail_free; | ||||
} | } | ||||
if (optind < argc) { | if (optind < argc) { | ||||
driver_nargs = 1 + argc - optind; | |||||
audio_driver_nargs = 1 + argc - optind; | |||||
} else { | } else { | ||||
driver_nargs = 1; | |||||
audio_driver_nargs = 1; | |||||
} | } | ||||
if (driver_nargs == 0) { | |||||
if (audio_driver_nargs == 0) { | |||||
fprintf(stderr, "No driver specified ... hmm. JACK won't do" | fprintf(stderr, "No driver specified ... hmm. JACK won't do" | ||||
" anything when run like this.\n"); | " anything when run like this.\n"); | ||||
goto fail_free; | goto fail_free; | ||||
} | } | ||||
driver_args = (char **) malloc(sizeof(char *) * driver_nargs); | |||||
driver_args[0] = driver_name; | |||||
audio_driver_args = (char **) malloc(sizeof(char *) * audio_driver_nargs); | |||||
audio_driver_args[0] = audio_driver_name; | |||||
for (i = 1; i < driver_nargs; i++) { | |||||
driver_args[i] = argv[optind++]; | |||||
for (i = 1; i < audio_driver_nargs; i++) { | |||||
audio_driver_args[i] = argv[optind++]; | |||||
} | } | ||||
if (jackctl_parse_driver_params(driver_ctl, driver_nargs, driver_args)) { | |||||
if (jackctl_parse_driver_params(audio_driver_ctl, audio_driver_nargs, audio_driver_args)) { | |||||
goto fail_free; | goto fail_free; | ||||
} | } | ||||
if (!jackctl_server_start(server_ctl, driver_ctl)) { | |||||
// Start server | |||||
if (!jackctl_server_start(server_ctl, audio_driver_ctl)) { | |||||
fprintf(stderr, "Failed to start server\n"); | fprintf(stderr, "Failed to start server\n"); | ||||
goto fail_free; | goto fail_free; | ||||
} | } | ||||
// MIDI driver | |||||
if (seen_midi_driver) { | |||||
midi_driver_ctl = jackctl_server_get_driver(server_ctl, midi_driver_name); | |||||
if (midi_driver_ctl == NULL) { | |||||
fprintf(stderr, "Unkown driver \"%s\"\n", midi_driver_name); | |||||
goto fail_free; | |||||
} | |||||
jackctl_server_load_slave(server_ctl, midi_driver_ctl); | |||||
} | |||||
notify_server_start(server_name); | notify_server_start(server_name); | ||||
// Waits for signal | // Waits for signal | ||||
signals = jackctl_setup_signals(0); | signals = jackctl_setup_signals(0); | ||||
jackctl_wait_signals(signals); | jackctl_wait_signals(signals); | ||||
if (!jackctl_server_stop(server_ctl)) | if (!jackctl_server_stop(server_ctl)) | ||||
fprintf(stderr, "Cannot stop server...\n"); | fprintf(stderr, "Cannot stop server...\n"); | ||||
fail_free: | fail_free: | ||||
jackctl_server_destroy(server_ctl); | jackctl_server_destroy(server_ctl); | ||||
notify_server_stop(server_name); | notify_server_stop(server_name); | ||||
return 1; | return 1; | ||||
@@ -510,6 +510,14 @@ jack_log( | |||||
/* @} */ | /* @} */ | ||||
bool | |||||
jackctl_server_load_slave(jackctl_server_t * server, | |||||
jackctl_driver_t * driver); | |||||
bool | |||||
jackctl_server_unload_slave(jackctl_server_t * server, | |||||
jackctl_driver_t * driver); | |||||
#if 0 | #if 0 | ||||
{ /* Adjust editor indent */ | { /* Adjust editor indent */ | ||||
#endif | #endif | ||||
@@ -113,6 +113,7 @@ def build(bld): | |||||
serverlib.source = [] + common_libsources | serverlib.source = [] + common_libsources | ||||
serverlib.source += [ | serverlib.source += [ | ||||
'JackAudioDriver.cpp', | 'JackAudioDriver.cpp', | ||||
'JackMidiDriver.cpp', | |||||
'JackDriver.cpp', | 'JackDriver.cpp', | ||||
'JackEngine.cpp', | 'JackEngine.cpp', | ||||
'JackExternalClient.cpp', | 'JackExternalClient.cpp', | ||||
@@ -170,7 +171,7 @@ def build(bld): | |||||
serverlib.env.append_value("CPPFLAGS", "-fvisibility=hidden") | serverlib.env.append_value("CPPFLAGS", "-fvisibility=hidden") | ||||
serverlib.env.append_value("CPPFLAGS", "-mmacosx-version-min=10.4 -arch i386 -arch ppc") | serverlib.env.append_value("CPPFLAGS", "-mmacosx-version-min=10.4 -arch i386 -arch ppc") | ||||
#serverlib.env.append_value("LINKFLAGS", "-framework CoreAudio -framework vecLib -single_module -arch i386 -arch ppc") | #serverlib.env.append_value("LINKFLAGS", "-framework CoreAudio -framework vecLib -single_module -arch i386 -arch ppc") | ||||
serverlib.env.append_value("LINKFLAGS", "-framework CoreAudio -framework vecLib -single_module") | |||||
serverlib.env.append_value("LINKFLAGS", "-framework CoreAudio -framework CoreFoundation -framework vecLib -single_module") | |||||
serverlib.env.append_value("LINKFLAGS", "-compatibility_version 1 -current_version 1") | serverlib.env.append_value("LINKFLAGS", "-compatibility_version 1 -current_version 1") | ||||
if bld.env['IS_SUN']: | if bld.env['IS_SUN']: | ||||
@@ -71,17 +71,21 @@ static int process(jack_nframes_t nframes, void *arg) | |||||
/* printf("1st byte of 1st event addr is %p\n", in_events[0].buffer);*/ | /* printf("1st byte of 1st event addr is %p\n", in_events[0].buffer);*/ | ||||
} | } | ||||
jack_midi_event_get(&in_event, port_buf, 0); | jack_midi_event_get(&in_event, port_buf, 0); | ||||
for(i=0; i<nframes; i++) | |||||
for(i = 0; i < nframes; i++) | |||||
{ | { | ||||
if((in_event.time == i) && (event_index < event_count)) | |||||
if ((in_event.time == i) && (event_index < event_count)) | |||||
{ | { | ||||
if( ((*(in_event.buffer) & 0xf0)) == 0x90 ) | |||||
{ | |||||
/* note on */ | |||||
note = *(in_event.buffer + 1); | |||||
note_on = 1.0; | |||||
if (((*(in_event.buffer) & 0xf0)) == 0x90) | |||||
{ | |||||
/* note on */ | |||||
note = *(in_event.buffer + 1); | |||||
if (*(in_event.buffer + 2) == 0) { | |||||
note_on = 0.0; | |||||
} else { | |||||
note_on = (float)(*(in_event.buffer + 2)) / 127.f; | |||||
} | |||||
} | } | ||||
else if( ((*(in_event.buffer)) & 0xf0) == 0x80 ) | |||||
else if (((*(in_event.buffer)) & 0xf0) == 0x80) | |||||
{ | { | ||||
/* note off */ | /* note off */ | ||||
note = *(in_event.buffer + 1); | note = *(in_event.buffer + 1); | ||||
@@ -58,6 +58,7 @@ | |||||
4B699DB6097D421700A18468 /* PBXTargetDependency */, | 4B699DB6097D421700A18468 /* PBXTargetDependency */, | ||||
4B699DB8097D421700A18468 /* PBXTargetDependency */, | 4B699DB8097D421700A18468 /* PBXTargetDependency */, | ||||
4B699DBA097D421700A18468 /* PBXTargetDependency */, | 4B699DBA097D421700A18468 /* PBXTargetDependency */, | ||||
4BF339280F8B87800080FB5B /* PBXTargetDependency */, | |||||
4B699DBC097D421700A18468 /* PBXTargetDependency */, | 4B699DBC097D421700A18468 /* PBXTargetDependency */, | ||||
BA222AF20DC883F3001A17F4 /* PBXTargetDependency */, | BA222AF20DC883F3001A17F4 /* PBXTargetDependency */, | ||||
4BD624D30CBCF55700DE782F /* PBXTargetDependency */, | 4BD624D30CBCF55700DE782F /* PBXTargetDependency */, | ||||
@@ -576,6 +577,16 @@ | |||||
4BF284190F31B4BC00B05BE3 /* JackArgParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BF284170F31B4BC00B05BE3 /* JackArgParser.h */; }; | 4BF284190F31B4BC00B05BE3 /* JackArgParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BF284170F31B4BC00B05BE3 /* JackArgParser.h */; }; | ||||
4BF2841A0F31B4BC00B05BE3 /* JackArgParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF284160F31B4BC00B05BE3 /* JackArgParser.cpp */; }; | 4BF2841A0F31B4BC00B05BE3 /* JackArgParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF284160F31B4BC00B05BE3 /* JackArgParser.cpp */; }; | ||||
4BF2841B0F31B4BC00B05BE3 /* JackArgParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BF284170F31B4BC00B05BE3 /* JackArgParser.h */; }; | 4BF2841B0F31B4BC00B05BE3 /* JackArgParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BF284170F31B4BC00B05BE3 /* JackArgParser.h */; }; | ||||
4BF339160F8B86DC0080FB5B /* JackCoreMidiDriver.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BF339140F8B86DC0080FB5B /* JackCoreMidiDriver.h */; }; | |||||
4BF339170F8B86DC0080FB5B /* JackCoreMidiDriver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF339150F8B86DC0080FB5B /* JackCoreMidiDriver.cpp */; }; | |||||
4BF339180F8B86DC0080FB5B /* JackCoreMidiDriver.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BF339140F8B86DC0080FB5B /* JackCoreMidiDriver.h */; }; | |||||
4BF339190F8B86DC0080FB5B /* JackCoreMidiDriver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF339150F8B86DC0080FB5B /* JackCoreMidiDriver.cpp */; }; | |||||
4BF3391A0F8B86DC0080FB5B /* JackCoreMidiDriver.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BF339140F8B86DC0080FB5B /* JackCoreMidiDriver.h */; }; | |||||
4BF3391B0F8B86DC0080FB5B /* JackCoreMidiDriver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF339150F8B86DC0080FB5B /* JackCoreMidiDriver.cpp */; }; | |||||
4BF339210F8B873E0080FB5B /* JackMidiDriver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF3391F0F8B873E0080FB5B /* JackMidiDriver.cpp */; }; | |||||
4BF339220F8B873E0080FB5B /* JackMidiDriver.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BF339200F8B873E0080FB5B /* JackMidiDriver.h */; }; | |||||
4BF339230F8B873E0080FB5B /* JackMidiDriver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF3391F0F8B873E0080FB5B /* JackMidiDriver.cpp */; }; | |||||
4BF339240F8B873E0080FB5B /* JackMidiDriver.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BF339200F8B873E0080FB5B /* JackMidiDriver.h */; }; | |||||
4BF4BAB10E3480AB00403CDF /* JackAudioAdapterFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF4BAB00E3480AB00403CDF /* JackAudioAdapterFactory.cpp */; }; | 4BF4BAB10E3480AB00403CDF /* JackAudioAdapterFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF4BAB00E3480AB00403CDF /* JackAudioAdapterFactory.cpp */; }; | ||||
4BF520530CB8D0E80037470E /* timestamps.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BF520520CB8D0E80037470E /* timestamps.c */; }; | 4BF520530CB8D0E80037470E /* timestamps.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BF520520CB8D0E80037470E /* timestamps.c */; }; | ||||
4BF520540CB8D0E80037470E /* timestamps.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BF520520CB8D0E80037470E /* timestamps.c */; }; | 4BF520540CB8D0E80037470E /* timestamps.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BF520520CB8D0E80037470E /* timestamps.c */; }; | ||||
@@ -963,6 +974,13 @@ | |||||
remoteGlobalIDString = 4BE99D260AD7A04800C59091; | remoteGlobalIDString = 4BE99D260AD7A04800C59091; | ||||
remoteInfo = "jack_cpu Universal"; | remoteInfo = "jack_cpu Universal"; | ||||
}; | }; | ||||
4BF339270F8B87800080FB5B /* PBXContainerItemProxy */ = { | |||||
isa = PBXContainerItemProxy; | |||||
containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; | |||||
proxyType = 1; | |||||
remoteGlobalIDString = 4BF339020F8B864B0080FB5B; | |||||
remoteInfo = jack_coremidi; | |||||
}; | |||||
4BFA83310DF6AB540087B4E1 /* PBXContainerItemProxy */ = { | 4BFA83310DF6AB540087B4E1 /* PBXContainerItemProxy */ = { | ||||
isa = PBXContainerItemProxy; | isa = PBXContainerItemProxy; | ||||
containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; | containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; | ||||
@@ -1345,6 +1363,11 @@ | |||||
4BECB2F40F4451C10091B70A /* JackProcessSync.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackProcessSync.h; path = ../posix/JackProcessSync.h; sourceTree = SOURCE_ROOT; }; | 4BECB2F40F4451C10091B70A /* JackProcessSync.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackProcessSync.h; path = ../posix/JackProcessSync.h; sourceTree = SOURCE_ROOT; }; | ||||
4BF284160F31B4BC00B05BE3 /* JackArgParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackArgParser.cpp; path = ../common/JackArgParser.cpp; sourceTree = SOURCE_ROOT; }; | 4BF284160F31B4BC00B05BE3 /* JackArgParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackArgParser.cpp; path = ../common/JackArgParser.cpp; sourceTree = SOURCE_ROOT; }; | ||||
4BF284170F31B4BC00B05BE3 /* JackArgParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackArgParser.h; path = ../common/JackArgParser.h; sourceTree = SOURCE_ROOT; }; | 4BF284170F31B4BC00B05BE3 /* JackArgParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackArgParser.h; path = ../common/JackArgParser.h; sourceTree = SOURCE_ROOT; }; | ||||
4BF3390C0F8B864B0080FB5B /* jack_coremidi.so */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = jack_coremidi.so; sourceTree = BUILT_PRODUCTS_DIR; }; | |||||
4BF339140F8B86DC0080FB5B /* JackCoreMidiDriver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackCoreMidiDriver.h; path = coremidi/JackCoreMidiDriver.h; sourceTree = SOURCE_ROOT; }; | |||||
4BF339150F8B86DC0080FB5B /* JackCoreMidiDriver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackCoreMidiDriver.cpp; path = coremidi/JackCoreMidiDriver.cpp; sourceTree = SOURCE_ROOT; }; | |||||
4BF3391F0F8B873E0080FB5B /* JackMidiDriver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackMidiDriver.cpp; path = ../common/JackMidiDriver.cpp; sourceTree = SOURCE_ROOT; }; | |||||
4BF339200F8B873E0080FB5B /* JackMidiDriver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackMidiDriver.h; path = ../common/JackMidiDriver.h; sourceTree = SOURCE_ROOT; }; | |||||
4BF3937C0626BF3600CC67FA /* JackMacLibClientRPC.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = JackMacLibClientRPC.cpp; sourceTree = SOURCE_ROOT; }; | 4BF3937C0626BF3600CC67FA /* JackMacLibClientRPC.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = JackMacLibClientRPC.cpp; sourceTree = SOURCE_ROOT; }; | ||||
4BF4BAB00E3480AB00403CDF /* JackAudioAdapterFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackAudioAdapterFactory.cpp; path = ../common/JackAudioAdapterFactory.cpp; sourceTree = SOURCE_ROOT; }; | 4BF4BAB00E3480AB00403CDF /* JackAudioAdapterFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackAudioAdapterFactory.cpp; path = ../common/JackAudioAdapterFactory.cpp; sourceTree = SOURCE_ROOT; }; | ||||
4BF520520CB8D0E80037470E /* timestamps.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = timestamps.c; path = ../common/timestamps.c; sourceTree = SOURCE_ROOT; }; | 4BF520520CB8D0E80037470E /* timestamps.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = timestamps.c; path = ../common/timestamps.c; sourceTree = SOURCE_ROOT; }; | ||||
@@ -1899,6 +1922,13 @@ | |||||
); | ); | ||||
runOnlyForDeploymentPostprocessing = 0; | runOnlyForDeploymentPostprocessing = 0; | ||||
}; | }; | ||||
4BF339070F8B864B0080FB5B /* Frameworks */ = { | |||||
isa = PBXFrameworksBuildPhase; | |||||
buildActionMask = 2147483647; | |||||
files = ( | |||||
); | |||||
runOnlyForDeploymentPostprocessing = 0; | |||||
}; | |||||
4BFA5E910DEC4D9C00FA4CDB /* Frameworks */ = { | 4BFA5E910DEC4D9C00FA4CDB /* Frameworks */ = { | ||||
isa = PBXFrameworksBuildPhase; | isa = PBXFrameworksBuildPhase; | ||||
buildActionMask = 2147483647; | buildActionMask = 2147483647; | ||||
@@ -2094,6 +2124,7 @@ | |||||
4BFA82CF0DF6A9E40087B4E1 /* jack_impulse_grabber */, | 4BFA82CF0DF6A9E40087B4E1 /* jack_impulse_grabber */, | ||||
4B19B3000E23620F00DD4A82 /* audioadapter.so */, | 4B19B3000E23620F00DD4A82 /* audioadapter.so */, | ||||
4B5E08D50E5B66EE00BEE4E0 /* netadapter.so */, | 4B5E08D50E5B66EE00BEE4E0 /* netadapter.so */, | ||||
4BF3390C0F8B864B0080FB5B /* jack_coremidi.so */, | |||||
); | ); | ||||
name = Products; | name = Products; | ||||
sourceTree = "<group>"; | sourceTree = "<group>"; | ||||
@@ -2389,7 +2420,6 @@ | |||||
4BA550F605E241B800569492 /* Driver */ = { | 4BA550F605E241B800569492 /* Driver */ = { | ||||
isa = PBXGroup; | isa = PBXGroup; | ||||
children = ( | children = ( | ||||
4B19B3010E23629800DD4A82 /* Adapter */, | |||||
4B869B3D08C8D21C001CF041 /* driver_interface.h */, | 4B869B3D08C8D21C001CF041 /* driver_interface.h */, | ||||
4B869B4208C8D22F001CF041 /* JackDriverLoader.h */, | 4B869B4208C8D22F001CF041 /* JackDriverLoader.h */, | ||||
4B869D7F08C9CB00001CF041 /* JackDriverLoader.cpp */, | 4B869D7F08C9CB00001CF041 /* JackDriverLoader.cpp */, | ||||
@@ -2399,6 +2429,8 @@ | |||||
4BF70ACA0908EE95008B75AD /* JackLoopbackDriver.cpp */, | 4BF70ACA0908EE95008B75AD /* JackLoopbackDriver.cpp */, | ||||
4BC3988A08B3CF6C00B6F371 /* JackDummyDriver.h */, | 4BC3988A08B3CF6C00B6F371 /* JackDummyDriver.h */, | ||||
4BC3988908B3CF6C00B6F371 /* JackDummyDriver.cpp */, | 4BC3988908B3CF6C00B6F371 /* JackDummyDriver.cpp */, | ||||
4BF3390D0F8B86AF0080FB5B /* MIDI */, | |||||
4B19B3010E23629800DD4A82 /* Adapter */, | |||||
BA222AEA0DC88379001A17F4 /* Net */, | BA222AEA0DC88379001A17F4 /* Net */, | ||||
4BD56D8707968982006D44F9 /* Threaded */, | 4BD56D8707968982006D44F9 /* Threaded */, | ||||
4BD56D8607968979006D44F9 /* Audio */, | 4BD56D8607968979006D44F9 /* Audio */, | ||||
@@ -2539,6 +2571,17 @@ | |||||
name = Threaded; | name = Threaded; | ||||
sourceTree = "<group>"; | sourceTree = "<group>"; | ||||
}; | }; | ||||
4BF3390D0F8B86AF0080FB5B /* MIDI */ = { | |||||
isa = PBXGroup; | |||||
children = ( | |||||
4BF3391F0F8B873E0080FB5B /* JackMidiDriver.cpp */, | |||||
4BF339200F8B873E0080FB5B /* JackMidiDriver.h */, | |||||
4BF339140F8B86DC0080FB5B /* JackCoreMidiDriver.h */, | |||||
4BF339150F8B86DC0080FB5B /* JackCoreMidiDriver.cpp */, | |||||
); | |||||
name = MIDI; | |||||
sourceTree = "<group>"; | |||||
}; | |||||
4BFB299808AF451200D450D4 /* Mach */ = { | 4BFB299808AF451200D450D4 /* Mach */ = { | ||||
isa = PBXGroup; | isa = PBXGroup; | ||||
children = ( | children = ( | ||||
@@ -2684,6 +2727,7 @@ | |||||
4B4F9C910DC20C0400706CB0 /* JackMessageBuffer.h in Headers */, | 4B4F9C910DC20C0400706CB0 /* JackMessageBuffer.h in Headers */, | ||||
4B93F19E0E87998400E4ECCD /* JackPosixThread.h in Headers */, | 4B93F19E0E87998400E4ECCD /* JackPosixThread.h in Headers */, | ||||
4BECB2FA0F4451C10091B70A /* JackProcessSync.h in Headers */, | 4BECB2FA0F4451C10091B70A /* JackProcessSync.h in Headers */, | ||||
4BF339160F8B86DC0080FB5B /* JackCoreMidiDriver.h in Headers */, | |||||
); | ); | ||||
runOnlyForDeploymentPostprocessing = 0; | runOnlyForDeploymentPostprocessing = 0; | ||||
}; | }; | ||||
@@ -2748,6 +2792,8 @@ | |||||
4B93F19A0E87992200E4ECCD /* JackPosixThread.h in Headers */, | 4B93F19A0E87992200E4ECCD /* JackPosixThread.h in Headers */, | ||||
4BBAE4120F42FA6100B8BD3F /* JackEngineProfiling.h in Headers */, | 4BBAE4120F42FA6100B8BD3F /* JackEngineProfiling.h in Headers */, | ||||
4BECB2FC0F4451C10091B70A /* JackProcessSync.h in Headers */, | 4BECB2FC0F4451C10091B70A /* JackProcessSync.h in Headers */, | ||||
4BF339180F8B86DC0080FB5B /* JackCoreMidiDriver.h in Headers */, | |||||
4BF339220F8B873E0080FB5B /* JackMidiDriver.h in Headers */, | |||||
); | ); | ||||
runOnlyForDeploymentPostprocessing = 0; | runOnlyForDeploymentPostprocessing = 0; | ||||
}; | }; | ||||
@@ -3116,6 +3162,7 @@ | |||||
4BF2841B0F31B4BC00B05BE3 /* JackArgParser.h in Headers */, | 4BF2841B0F31B4BC00B05BE3 /* JackArgParser.h in Headers */, | ||||
4BBAE4100F42FA6100B8BD3F /* JackEngineProfiling.h in Headers */, | 4BBAE4100F42FA6100B8BD3F /* JackEngineProfiling.h in Headers */, | ||||
4BECB2F60F4451C10091B70A /* JackProcessSync.h in Headers */, | 4BECB2F60F4451C10091B70A /* JackProcessSync.h in Headers */, | ||||
4BF339240F8B873E0080FB5B /* JackMidiDriver.h in Headers */, | |||||
); | ); | ||||
runOnlyForDeploymentPostprocessing = 0; | runOnlyForDeploymentPostprocessing = 0; | ||||
}; | }; | ||||
@@ -3270,6 +3317,14 @@ | |||||
); | ); | ||||
runOnlyForDeploymentPostprocessing = 0; | runOnlyForDeploymentPostprocessing = 0; | ||||
}; | }; | ||||
4BF339030F8B864B0080FB5B /* Headers */ = { | |||||
isa = PBXHeadersBuildPhase; | |||||
buildActionMask = 2147483647; | |||||
files = ( | |||||
4BF3391A0F8B86DC0080FB5B /* JackCoreMidiDriver.h in Headers */, | |||||
); | |||||
runOnlyForDeploymentPostprocessing = 0; | |||||
}; | |||||
4BFA5E8C0DEC4D9C00FA4CDB /* Headers */ = { | 4BFA5E8C0DEC4D9C00FA4CDB /* Headers */ = { | ||||
isa = PBXHeadersBuildPhase; | isa = PBXHeadersBuildPhase; | ||||
buildActionMask = 2147483647; | buildActionMask = 2147483647; | ||||
@@ -4529,6 +4584,23 @@ | |||||
productReference = 4BE99D300AD7A04800C59091 /* jack_cpu */; | productReference = 4BE99D300AD7A04800C59091 /* jack_cpu */; | ||||
productType = "com.apple.product-type.tool"; | productType = "com.apple.product-type.tool"; | ||||
}; | }; | ||||
4BF339020F8B864B0080FB5B /* jack_coremidi Universal */ = { | |||||
isa = PBXNativeTarget; | |||||
buildConfigurationList = 4BF339080F8B864B0080FB5B /* Build configuration list for PBXNativeTarget "jack_coremidi Universal" */; | |||||
buildPhases = ( | |||||
4BF339030F8B864B0080FB5B /* Headers */, | |||||
4BF339050F8B864B0080FB5B /* Sources */, | |||||
4BF339070F8B864B0080FB5B /* Frameworks */, | |||||
); | |||||
buildRules = ( | |||||
); | |||||
dependencies = ( | |||||
); | |||||
name = "jack_coremidi Universal"; | |||||
productName = jack_coreaudio; | |||||
productReference = 4BF3390C0F8B864B0080FB5B /* jack_coremidi.so */; | |||||
productType = "com.apple.product-type.library.dynamic"; | |||||
}; | |||||
4BFA5E8B0DEC4D9C00FA4CDB /* testMutex Universal */ = { | 4BFA5E8B0DEC4D9C00FA4CDB /* testMutex Universal */ = { | ||||
isa = PBXNativeTarget; | isa = PBXNativeTarget; | ||||
buildConfigurationList = 4BFA5E940DEC4D9C00FA4CDB /* Build configuration list for PBXNativeTarget "testMutex Universal" */; | buildConfigurationList = 4BFA5E940DEC4D9C00FA4CDB /* Build configuration list for PBXNativeTarget "testMutex Universal" */; | ||||
@@ -4763,6 +4835,7 @@ | |||||
4B699D7F097D421700A18468 /* synchroServerClient Universal */, | 4B699D7F097D421700A18468 /* synchroServerClient Universal */, | ||||
4B699D97097D421700A18468 /* jack_coreaudio Universal */, | 4B699D97097D421700A18468 /* jack_coreaudio Universal */, | ||||
4B978DB10A31CF4A009E2DD1 /* jack_portaudio Universal */, | 4B978DB10A31CF4A009E2DD1 /* jack_portaudio Universal */, | ||||
4BF339020F8B864B0080FB5B /* jack_coremidi Universal */, | |||||
4B699DA6097D421700A18468 /* jack_dummy Universal */, | 4B699DA6097D421700A18468 /* jack_dummy Universal */, | ||||
BA222AC50DC88132001A17F4 /* jack_net Universal */, | BA222AC50DC88132001A17F4 /* jack_net Universal */, | ||||
4BD623ED0CBCF0F000DE782F /* inprocess */, | 4BD623ED0CBCF0F000DE782F /* inprocess */, | ||||
@@ -5343,6 +5416,7 @@ | |||||
4B93F19D0E87998400E4ECCD /* JackPosixThread.cpp in Sources */, | 4B93F19D0E87998400E4ECCD /* JackPosixThread.cpp in Sources */, | ||||
4B93F1C00E87A35400E4ECCD /* JackMachTime.c in Sources */, | 4B93F1C00E87A35400E4ECCD /* JackMachTime.c in Sources */, | ||||
4BECB2F90F4451C10091B70A /* JackProcessSync.cpp in Sources */, | 4BECB2F90F4451C10091B70A /* JackProcessSync.cpp in Sources */, | ||||
4BF339170F8B86DC0080FB5B /* JackCoreMidiDriver.cpp in Sources */, | |||||
); | ); | ||||
runOnlyForDeploymentPostprocessing = 0; | runOnlyForDeploymentPostprocessing = 0; | ||||
}; | }; | ||||
@@ -5399,6 +5473,8 @@ | |||||
4B93F22B0E87A72500E4ECCD /* JackMachTime.c in Sources */, | 4B93F22B0E87A72500E4ECCD /* JackMachTime.c in Sources */, | ||||
4BBAE4130F42FA6100B8BD3F /* JackEngineProfiling.cpp in Sources */, | 4BBAE4130F42FA6100B8BD3F /* JackEngineProfiling.cpp in Sources */, | ||||
4BECB2FB0F4451C10091B70A /* JackProcessSync.cpp in Sources */, | 4BECB2FB0F4451C10091B70A /* JackProcessSync.cpp in Sources */, | ||||
4BF339190F8B86DC0080FB5B /* JackCoreMidiDriver.cpp in Sources */, | |||||
4BF339210F8B873E0080FB5B /* JackMidiDriver.cpp in Sources */, | |||||
); | ); | ||||
runOnlyForDeploymentPostprocessing = 0; | runOnlyForDeploymentPostprocessing = 0; | ||||
}; | }; | ||||
@@ -5778,6 +5854,7 @@ | |||||
4BF2841A0F31B4BC00B05BE3 /* JackArgParser.cpp in Sources */, | 4BF2841A0F31B4BC00B05BE3 /* JackArgParser.cpp in Sources */, | ||||
4BBAE4110F42FA6100B8BD3F /* JackEngineProfiling.cpp in Sources */, | 4BBAE4110F42FA6100B8BD3F /* JackEngineProfiling.cpp in Sources */, | ||||
4BECB2F50F4451C10091B70A /* JackProcessSync.cpp in Sources */, | 4BECB2F50F4451C10091B70A /* JackProcessSync.cpp in Sources */, | ||||
4BF339230F8B873E0080FB5B /* JackMidiDriver.cpp in Sources */, | |||||
); | ); | ||||
runOnlyForDeploymentPostprocessing = 0; | runOnlyForDeploymentPostprocessing = 0; | ||||
}; | }; | ||||
@@ -5949,6 +6026,14 @@ | |||||
); | ); | ||||
runOnlyForDeploymentPostprocessing = 0; | runOnlyForDeploymentPostprocessing = 0; | ||||
}; | }; | ||||
4BF339050F8B864B0080FB5B /* Sources */ = { | |||||
isa = PBXSourcesBuildPhase; | |||||
buildActionMask = 2147483647; | |||||
files = ( | |||||
4BF3391B0F8B86DC0080FB5B /* JackCoreMidiDriver.cpp in Sources */, | |||||
); | |||||
runOnlyForDeploymentPostprocessing = 0; | |||||
}; | |||||
4BFA5E8D0DEC4D9C00FA4CDB /* Sources */ = { | 4BFA5E8D0DEC4D9C00FA4CDB /* Sources */ = { | ||||
isa = PBXSourcesBuildPhase; | isa = PBXSourcesBuildPhase; | ||||
buildActionMask = 2147483647; | buildActionMask = 2147483647; | ||||
@@ -6293,6 +6378,11 @@ | |||||
target = 4BE99D260AD7A04800C59091 /* jack_cpu Universal */; | target = 4BE99D260AD7A04800C59091 /* jack_cpu Universal */; | ||||
targetProxy = 4BE99D620AD7A19100C59091 /* PBXContainerItemProxy */; | targetProxy = 4BE99D620AD7A19100C59091 /* PBXContainerItemProxy */; | ||||
}; | }; | ||||
4BF339280F8B87800080FB5B /* PBXTargetDependency */ = { | |||||
isa = PBXTargetDependency; | |||||
target = 4BF339020F8B864B0080FB5B /* jack_coremidi Universal */; | |||||
targetProxy = 4BF339270F8B87800080FB5B /* PBXContainerItemProxy */; | |||||
}; | |||||
4BFA83320DF6AB540087B4E1 /* PBXTargetDependency */ = { | 4BFA83320DF6AB540087B4E1 /* PBXTargetDependency */ = { | ||||
isa = PBXTargetDependency; | isa = PBXTargetDependency; | ||||
target = 4BFA82820DF6A9E40087B4E1 /* jack_evmon 64 bits */; | target = 4BFA82820DF6A9E40087B4E1 /* jack_evmon 64 bits */; | ||||
@@ -13852,6 +13942,153 @@ | |||||
}; | }; | ||||
name = Default; | name = Default; | ||||
}; | }; | ||||
4BF339090F8B864B0080FB5B /* Development */ = { | |||||
isa = XCBuildConfiguration; | |||||
buildSettings = { | |||||
ARCHS = ( | |||||
i386, | |||||
ppc, | |||||
); | |||||
COPY_PHASE_STRIP = NO; | |||||
DEBUGGING_SYMBOLS = YES; | |||||
DYLIB_COMPATIBILITY_VERSION = 1; | |||||
DYLIB_CURRENT_VERSION = 1; | |||||
EXECUTABLE_EXTENSION = so; | |||||
FRAMEWORK_SEARCH_PATHS = ""; | |||||
GCC_DYNAMIC_NO_PIC = NO; | |||||
GCC_ENABLE_FIX_AND_CONTINUE = YES; | |||||
GCC_GENERATE_DEBUGGING_SYMBOLS = YES; | |||||
GCC_MODEL_TUNING = G4; | |||||
GCC_OPTIMIZATION_LEVEL = 0; | |||||
GCC_PREPROCESSOR_DEFINITIONS = ""; | |||||
HEADER_SEARCH_PATHS = ( | |||||
., | |||||
../common/jack, | |||||
../posix, | |||||
../common, | |||||
); | |||||
INSTALL_PATH = /usr/local/lib; | |||||
LIBRARY_STYLE = DYNAMIC; | |||||
MACH_O_TYPE = mh_dylib; | |||||
OTHER_CFLAGS = ""; | |||||
OTHER_CPLUSPLUSFLAGS = "-DMACH_RPC_MACH_SEMA"; | |||||
OTHER_LDFLAGS = ( | |||||
"-framework", | |||||
Jackservermp, | |||||
"-framework", | |||||
CoreMIDI, | |||||
"-framework", | |||||
CoreServices, | |||||
); | |||||
OTHER_REZFLAGS = ""; | |||||
PREBINDING = NO; | |||||
PRODUCT_NAME = jack_coremidi; | |||||
SDKROOT = ""; | |||||
SECTORDER_FLAGS = ""; | |||||
WARNING_CFLAGS = ( | |||||
"-Wmost", | |||||
"-Wno-four-char-constants", | |||||
"-Wno-unknown-pragmas", | |||||
); | |||||
ZERO_LINK = YES; | |||||
}; | |||||
name = Development; | |||||
}; | |||||
4BF3390A0F8B864B0080FB5B /* Deployment */ = { | |||||
isa = XCBuildConfiguration; | |||||
buildSettings = { | |||||
ARCHS = ( | |||||
i386, | |||||
ppc, | |||||
); | |||||
COPY_PHASE_STRIP = YES; | |||||
DYLIB_COMPATIBILITY_VERSION = 1; | |||||
DYLIB_CURRENT_VERSION = 1; | |||||
EXECUTABLE_EXTENSION = so; | |||||
FRAMEWORK_SEARCH_PATHS = ""; | |||||
GCC_ENABLE_FIX_AND_CONTINUE = NO; | |||||
GCC_GENERATE_DEBUGGING_SYMBOLS = NO; | |||||
GCC_MODEL_TUNING = G4; | |||||
GCC_PREPROCESSOR_DEFINITIONS = ""; | |||||
HEADER_SEARCH_PATHS = ( | |||||
., | |||||
../common/jack, | |||||
../posix, | |||||
../common, | |||||
); | |||||
INSTALL_PATH = /usr/local/lib; | |||||
LIBRARY_STYLE = DYNAMIC; | |||||
MACH_O_TYPE = mh_dylib; | |||||
MACOSX_DEPLOYMENT_TARGET = 10.4; | |||||
OTHER_CFLAGS = ""; | |||||
OTHER_CPLUSPLUSFLAGS = "-DMACH_RPC_MACH_SEMA"; | |||||
OTHER_LDFLAGS = ( | |||||
"-framework", | |||||
Jackservermp, | |||||
"-framework", | |||||
CoreMIDI, | |||||
"-framework", | |||||
CoreServices, | |||||
); | |||||
OTHER_REZFLAGS = ""; | |||||
PREBINDING = NO; | |||||
PRODUCT_NAME = jack_coremidi; | |||||
SDKROOT = ""; | |||||
SECTORDER_FLAGS = ""; | |||||
WARNING_CFLAGS = ( | |||||
"-Wmost", | |||||
"-Wno-four-char-constants", | |||||
"-Wno-unknown-pragmas", | |||||
); | |||||
ZERO_LINK = NO; | |||||
}; | |||||
name = Deployment; | |||||
}; | |||||
4BF3390B0F8B864B0080FB5B /* Default */ = { | |||||
isa = XCBuildConfiguration; | |||||
buildSettings = { | |||||
ARCHS = ( | |||||
i386, | |||||
ppc, | |||||
); | |||||
DYLIB_COMPATIBILITY_VERSION = 1; | |||||
DYLIB_CURRENT_VERSION = 1; | |||||
EXECUTABLE_EXTENSION = so; | |||||
FRAMEWORK_SEARCH_PATHS = ""; | |||||
GCC_GENERATE_DEBUGGING_SYMBOLS = NO; | |||||
GCC_MODEL_TUNING = G4; | |||||
GCC_PREPROCESSOR_DEFINITIONS = ""; | |||||
HEADER_SEARCH_PATHS = ../common; | |||||
INSTALL_PATH = /usr/local/lib; | |||||
LIBRARY_STYLE = DYNAMIC; | |||||
MACH_O_TYPE = mh_dylib; | |||||
OTHER_CFLAGS = ""; | |||||
OTHER_CPLUSPLUSFLAGS = "-DMACH_RPC_MACH_SEMA"; | |||||
OTHER_LDFLAGS = ( | |||||
"-framework", | |||||
Jackdmp, | |||||
"-framework", | |||||
AudioToolBox, | |||||
"-framework", | |||||
CoreAudio, | |||||
"-framework", | |||||
CoreServices, | |||||
"-framework", | |||||
AudioUnit, | |||||
); | |||||
OTHER_REZFLAGS = ""; | |||||
PREBINDING = NO; | |||||
PRODUCT_NAME = jack_coreaudio; | |||||
SDKROOT = ""; | |||||
SECTORDER_FLAGS = ""; | |||||
WARNING_CFLAGS = ( | |||||
"-Wmost", | |||||
"-Wno-four-char-constants", | |||||
"-Wno-unknown-pragmas", | |||||
); | |||||
}; | |||||
name = Default; | |||||
}; | |||||
4BFA5E950DEC4D9C00FA4CDB /* Development */ = { | 4BFA5E950DEC4D9C00FA4CDB /* Development */ = { | ||||
isa = XCBuildConfiguration; | isa = XCBuildConfiguration; | ||||
buildSettings = { | buildSettings = { | ||||
@@ -15635,6 +15872,16 @@ | |||||
defaultConfigurationIsVisible = 0; | defaultConfigurationIsVisible = 0; | ||||
defaultConfigurationName = Default; | defaultConfigurationName = Default; | ||||
}; | }; | ||||
4BF339080F8B864B0080FB5B /* Build configuration list for PBXNativeTarget "jack_coremidi Universal" */ = { | |||||
isa = XCConfigurationList; | |||||
buildConfigurations = ( | |||||
4BF339090F8B864B0080FB5B /* Development */, | |||||
4BF3390A0F8B864B0080FB5B /* Deployment */, | |||||
4BF3390B0F8B864B0080FB5B /* Default */, | |||||
); | |||||
defaultConfigurationIsVisible = 0; | |||||
defaultConfigurationName = Default; | |||||
}; | |||||
4BFA5E940DEC4D9C00FA4CDB /* Build configuration list for PBXNativeTarget "testMutex Universal" */ = { | 4BFA5E940DEC4D9C00FA4CDB /* Build configuration list for PBXNativeTarget "testMutex Universal" */ = { | ||||
isa = XCConfigurationList; | isa = XCConfigurationList; | ||||
buildConfigurations = ( | buildConfigurations = ( | ||||
@@ -0,0 +1,426 @@ | |||||
/* | |||||
Copyright (C) 2009 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. | |||||
*/ | |||||
#include "JackCoreMidiDriver.h" | |||||
#include "JackGraphManager.h" | |||||
#include "JackServer.h" | |||||
#include "JackEngineControl.h" | |||||
#include "JackDriverLoader.h" | |||||
#include <mach/mach_time.h> | |||||
#include <assert.h> | |||||
#include <iostream> | |||||
#include <sstream> | |||||
#include <string> | |||||
namespace Jack | |||||
{ | |||||
static MIDITimeStamp MIDIGetCurrentHostTime() | |||||
{ | |||||
return mach_absolute_time(); | |||||
} | |||||
void JackCoreMidiDriver::ReadProcAux(const MIDIPacketList *pktlist, jack_ringbuffer_t* ringbuffer) | |||||
{ | |||||
// Write the number of packets | |||||
size_t size = jack_ringbuffer_write(ringbuffer, (char*)&pktlist->numPackets, sizeof(UInt32)); | |||||
if (size != sizeof(UInt32)) { | |||||
jack_error("ReadProc : ring buffer is full, skip events..."); | |||||
return; | |||||
} | |||||
for (unsigned int i = 0; i < pktlist->numPackets; ++i) { | |||||
MIDIPacket *packet = (MIDIPacket *)pktlist->packet; | |||||
// TODO : use timestamp | |||||
// Write length of each packet first | |||||
size = jack_ringbuffer_write(ringbuffer, (char*)&packet->length, sizeof(UInt16)); | |||||
if (size != sizeof(UInt16)) { | |||||
jack_error("ReadProc : ring buffer is full, skip events..."); | |||||
return; | |||||
} | |||||
// Write event actual data | |||||
size = jack_ringbuffer_write(ringbuffer, (char*)packet->data, packet->length); | |||||
if (size != packet->length) { | |||||
jack_error("ReadProc : ring buffer is full, skip events..."); | |||||
return; | |||||
} | |||||
packet = MIDIPacketNext(packet); | |||||
} | |||||
} | |||||
void JackCoreMidiDriver::ReadProc(const MIDIPacketList *pktlist, void *refCon, void *connRefCon) | |||||
{ | |||||
jack_ringbuffer_t* ringbuffer = (jack_ringbuffer_t*)connRefCon; | |||||
ReadProcAux(pktlist, ringbuffer); | |||||
} | |||||
void JackCoreMidiDriver::ReadVirtualProc(const MIDIPacketList *pktlist, void *refCon, void *connRefCon) | |||||
{ | |||||
jack_ringbuffer_t* ringbuffer = (jack_ringbuffer_t*)refCon; | |||||
ReadProcAux(pktlist, ringbuffer); | |||||
} | |||||
void JackCoreMidiDriver::NotifyProc(const MIDINotification *message, void *refCon) | |||||
{ | |||||
jack_info("NotifyProc %d", message->messageID); | |||||
} | |||||
JackCoreMidiDriver::JackCoreMidiDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table) | |||||
: JackMidiDriver(name, alias, engine, table), fMidiClient(NULL), fInputPort(NULL), fOutputPort(NULL), fRealCaptureChannels(0), fRealPlaybackChannels(0) | |||||
{} | |||||
JackCoreMidiDriver::~JackCoreMidiDriver() | |||||
{} | |||||
int JackCoreMidiDriver::Open(bool capturing, | |||||
bool playing, | |||||
int inchannels, | |||||
int outchannels, | |||||
bool monitor, | |||||
const char* capture_driver_name, | |||||
const char* playback_driver_name, | |||||
jack_nframes_t capture_latency, | |||||
jack_nframes_t playback_latency) | |||||
{ | |||||
OSStatus err; | |||||
CFStringRef coutputStr; | |||||
std::string str; | |||||
// Get real input/output number | |||||
fRealCaptureChannels = MIDIGetNumberOfSources(); | |||||
fRealPlaybackChannels = MIDIGetNumberOfDestinations(); | |||||
// Generic JackMidiDriver Open | |||||
if (JackMidiDriver::Open(capturing, playing, inchannels + fRealCaptureChannels, outchannels + fRealPlaybackChannels, monitor, capture_driver_name, playback_driver_name, capture_latency, playback_latency) != 0) | |||||
return -1; | |||||
coutputStr = CFStringCreateWithCString(0, "JackMidi", CFStringGetSystemEncoding()); | |||||
err = MIDIClientCreate(coutputStr, NotifyProc, this, &fMidiClient); | |||||
CFRelease(coutputStr); | |||||
if (!fMidiClient) { | |||||
jack_error("Cannot create CoreMidi client"); | |||||
goto error; | |||||
} | |||||
err = MIDIInputPortCreate(fMidiClient, CFSTR("Input port"), ReadProc, this, &fInputPort); | |||||
if (!fInputPort) { | |||||
jack_error("Cannot open CoreMidi in port\n"); | |||||
goto error; | |||||
} | |||||
err = MIDIOutputPortCreate(fMidiClient, CFSTR("Output port"), &fOutputPort); | |||||
if (!fOutputPort) { | |||||
jack_error("Cannot open CoreMidi out port\n"); | |||||
goto error; | |||||
} | |||||
fMidiDestination = new MIDIEndpointRef[inchannels + fRealCaptureChannels]; | |||||
assert(fMidiDestination); | |||||
// Virtual input | |||||
for (int i = 0; i < inchannels; i++) { | |||||
std::stringstream num; | |||||
num << i; | |||||
str = "JackMidi" + num.str(); | |||||
coutputStr = CFStringCreateWithCString(0, str.c_str(), CFStringGetSystemEncoding()); | |||||
err = MIDIDestinationCreate(fMidiClient, coutputStr, ReadVirtualProc, fRingBuffer[i], &fMidiDestination[i]); | |||||
CFRelease(coutputStr); | |||||
if (!fMidiDestination[i]) { | |||||
jack_error("Cannot create CoreMidi destination"); | |||||
goto error; | |||||
} | |||||
} | |||||
// Real input | |||||
for (int i = 0; i < fRealCaptureChannels; i++) { | |||||
fMidiDestination[i + inchannels] = MIDIGetSource(i); | |||||
MIDIPortConnectSource(fInputPort, fMidiDestination[i + inchannels], fRingBuffer[i + inchannels]); | |||||
} | |||||
fMidiSource = new MIDIEndpointRef[outchannels + fRealPlaybackChannels]; | |||||
assert(fMidiSource); | |||||
// Virtual output | |||||
for (int i = 0; i < outchannels; i++) { | |||||
std::stringstream num; | |||||
num << i; | |||||
str = "JackMidi" + num.str(); | |||||
coutputStr = CFStringCreateWithCString(0, str.c_str(), CFStringGetSystemEncoding()); | |||||
err = MIDISourceCreate(fMidiClient, coutputStr, &fMidiSource[i]); | |||||
CFRelease(coutputStr); | |||||
if (!fMidiSource[i]) { | |||||
jack_error("Cannot create CoreMidi source"); | |||||
goto error; | |||||
} | |||||
} | |||||
// Real output | |||||
for (int i = 0; i < fRealPlaybackChannels; i++) { | |||||
fMidiSource[i + outchannels] = MIDIGetDestination(i); | |||||
} | |||||
return 0; | |||||
error: | |||||
Close(); | |||||
return -1; | |||||
} | |||||
int JackCoreMidiDriver::Close() | |||||
{ | |||||
if (fInputPort) | |||||
MIDIPortDispose(fInputPort); | |||||
if (fOutputPort) | |||||
MIDIPortDispose(fOutputPort); | |||||
// Only dispose "virtual" endpoints | |||||
for (int i = 0; i < fCaptureChannels - fRealCaptureChannels; i++) { | |||||
if (fMidiDestination) | |||||
MIDIEndpointDispose(fMidiDestination[i]); | |||||
} | |||||
delete[] fMidiDestination; | |||||
// Only dispose "virtual" endpoints | |||||
for (int i = 0; i < fPlaybackChannels - fRealPlaybackChannels; i++) { | |||||
if (fMidiSource[i]) | |||||
MIDIEndpointDispose(fMidiSource[i]); | |||||
} | |||||
delete[] fMidiSource; | |||||
if (fMidiClient) | |||||
MIDIClientDispose(fMidiClient); | |||||
return 0; | |||||
} | |||||
int JackCoreMidiDriver::Attach() | |||||
{ | |||||
OSStatus err; | |||||
JackPort* port; | |||||
CFStringRef pname; | |||||
jack_port_id_t port_index; | |||||
char name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; | |||||
char endpoint_name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; | |||||
char alias[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; | |||||
unsigned long port_flags = JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal; | |||||
int i; | |||||
jack_log("JackCoreMidiDriver::Attach fBufferSize = %ld fSampleRate = %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate); | |||||
for (i = 0; i < fCaptureChannels; i++) { | |||||
err = MIDIObjectGetStringProperty(fMidiDestination[i], kMIDIPropertyName, &pname); | |||||
if (err == noErr) { | |||||
CFStringGetCString(pname, endpoint_name, sizeof(endpoint_name), 0); | |||||
CFRelease(pname); | |||||
snprintf(alias, sizeof(alias) - 1, "%s:%s:out%d", fAliasName, endpoint_name, i + 1); | |||||
} else { | |||||
snprintf(alias, sizeof(alias) - 1, "%s:%s:out%d", fAliasName, fCaptureDriverName, i + 1); | |||||
} | |||||
snprintf(name, sizeof(name) - 1, "%s:capture_%d", fClientControl.fName, i + 1); | |||||
if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE, (JackPortFlags)port_flags, fEngineControl->fBufferSize)) == NO_PORT) { | |||||
jack_error("driver: cannot register port for %s", name); | |||||
return -1; | |||||
} | |||||
port = fGraphManager->GetPort(port_index); | |||||
port->SetAlias(alias); | |||||
fCapturePortList[i] = port_index; | |||||
jack_log("JackCoreMidiDriver::Attach fCapturePortList[i] port_index = %ld", port_index); | |||||
} | |||||
port_flags = JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal; | |||||
for (i = 0; i < fPlaybackChannels; i++) { | |||||
err = MIDIObjectGetStringProperty(fMidiSource[i], kMIDIPropertyName, &pname); | |||||
if (err == noErr) { | |||||
CFStringGetCString(pname, endpoint_name, sizeof(endpoint_name), 0); | |||||
CFRelease(pname); | |||||
snprintf(alias, sizeof(alias) - 1, "%s:%s:in%d", fAliasName, endpoint_name, i + 1); | |||||
} else { | |||||
snprintf(alias, sizeof(alias) - 1, "%s:%s:in%d", fAliasName, fPlaybackDriverName, i + 1); | |||||
} | |||||
snprintf(name, sizeof(name) - 1, "%s:playback_%d", fClientControl.fName, i + 1); | |||||
if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE, (JackPortFlags)port_flags, fEngineControl->fBufferSize)) == NO_PORT) { | |||||
jack_error("driver: cannot register port for %s", name); | |||||
return -1; | |||||
} | |||||
port = fGraphManager->GetPort(port_index); | |||||
port->SetAlias(alias); | |||||
fPlaybackPortList[i] = port_index; | |||||
jack_log("JackCoreMidiDriver::Attach fPlaybackPortList[i] port_index = %ld", port_index); | |||||
} | |||||
return 0; | |||||
} | |||||
int JackCoreMidiDriver::Read() | |||||
{ | |||||
for (int chan = 0; chan < fCaptureChannels; chan++) { | |||||
if (fGraphManager->GetConnectionsNum(fCapturePortList[chan]) > 0) { | |||||
// Get JACK port | |||||
JackMidiBuffer* midi_buffer = GetInputBuffer(chan); | |||||
if (jack_ringbuffer_read_space(fRingBuffer[chan]) == 0) { | |||||
// Reset buffer | |||||
midi_buffer->Reset(midi_buffer->nframes); | |||||
} else { | |||||
while (jack_ringbuffer_read_space(fRingBuffer[chan]) > 0) { | |||||
// Read event number | |||||
int ev_count = 0; | |||||
jack_ringbuffer_read(fRingBuffer[chan], (char*)&ev_count, sizeof(int)); | |||||
for (int j = 0; j < ev_count; j++) { | |||||
// Read event length | |||||
UInt16 event_len; | |||||
jack_ringbuffer_read(fRingBuffer[chan], (char*)&event_len, sizeof(UInt16)); | |||||
// Read event actual data | |||||
jack_midi_data_t* dest = midi_buffer->ReserveEvent(0, event_len); | |||||
jack_ringbuffer_read(fRingBuffer[chan], (char*)dest, event_len); | |||||
} | |||||
} | |||||
} | |||||
} else { | |||||
// Consume ring buffer | |||||
jack_ringbuffer_read_advance(fRingBuffer[chan], jack_ringbuffer_read_space(fRingBuffer[chan])); | |||||
} | |||||
} | |||||
return 0; | |||||
} | |||||
int JackCoreMidiDriver::Write() | |||||
{ | |||||
MIDIPacketList* pktlist = (MIDIPacketList*)fMIDIBuffer; | |||||
for (int chan = 0; chan < fPlaybackChannels; chan++) { | |||||
if (fGraphManager->GetConnectionsNum(fPlaybackPortList[chan]) > 0) { | |||||
MIDIPacket* packet = MIDIPacketListInit(pktlist); | |||||
JackMidiBuffer* midi_buffer = GetOutputBuffer(chan); | |||||
// TODO : use timestamp | |||||
for (unsigned int j = 0; j < midi_buffer->event_count; j++) { | |||||
JackMidiEvent* ev = &midi_buffer->events[j]; | |||||
packet = MIDIPacketListAdd(pktlist, sizeof(fMIDIBuffer), packet, MIDIGetCurrentHostTime(), ev->size, ev->GetData(midi_buffer)); | |||||
} | |||||
if (packet) { | |||||
if (chan < fPlaybackChannels - fRealPlaybackChannels) { | |||||
OSStatus err = MIDIReceived(fMidiSource[chan], pktlist); | |||||
if (err != noErr) | |||||
jack_error("MIDIReceived error"); | |||||
} else { | |||||
OSStatus err = MIDISend(fOutputPort, fMidiSource[chan], pktlist); | |||||
if (err != noErr) | |||||
jack_error("MIDISend error"); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
return 0; | |||||
} | |||||
} // end of namespace | |||||
#ifdef __cplusplus | |||||
extern "C" | |||||
{ | |||||
#endif | |||||
SERVER_EXPORT jack_driver_desc_t * driver_get_descriptor() | |||||
{ | |||||
jack_driver_desc_t * desc; | |||||
unsigned int i; | |||||
desc = (jack_driver_desc_t*)calloc (1, sizeof (jack_driver_desc_t)); | |||||
strcpy(desc->name, "coremidi"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1 | |||||
strcpy(desc->desc, "Apple CoreMIDI API based MIDI backend"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1 | |||||
desc->nparams = 2; | |||||
desc->params = (jack_driver_param_desc_t*)calloc (desc->nparams, sizeof (jack_driver_param_desc_t)); | |||||
i = 0; | |||||
strcpy(desc->params[i].name, "inchannels"); | |||||
desc->params[i].character = 'i'; | |||||
desc->params[i].type = JackDriverParamInt; | |||||
desc->params[i].value.ui = 0; | |||||
strcpy(desc->params[i].short_desc, "CoreMIDI virtual bus"); | |||||
strcpy(desc->params[i].long_desc, desc->params[i].short_desc); | |||||
i++; | |||||
strcpy(desc->params[i].name, "outchannels"); | |||||
desc->params[i].character = 'o'; | |||||
desc->params[i].type = JackDriverParamInt; | |||||
desc->params[i].value.ui = 0; | |||||
strcpy(desc->params[i].short_desc, "CoreMIDI virtual bus"); | |||||
strcpy(desc->params[i].long_desc, desc->params[i].short_desc); | |||||
return desc; | |||||
} | |||||
SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params) | |||||
{ | |||||
const JSList * node; | |||||
const jack_driver_param_t * param; | |||||
int virtual_in = 0; | |||||
int virtual_out = 0; | |||||
for (node = params; node; node = jack_slist_next (node)) { | |||||
param = (const jack_driver_param_t *) node->data; | |||||
switch (param->character) { | |||||
case 'i': | |||||
virtual_in = param->value.ui; | |||||
break; | |||||
case 'o': | |||||
virtual_out = param->value.ui; | |||||
break; | |||||
} | |||||
} | |||||
Jack::JackDriverClientInterface* driver = new Jack::JackCoreMidiDriver("system_midi", "coremidi", engine, table); | |||||
if (driver->Open(1, 1, virtual_in, virtual_out, false, "in", "out", 0, 0) == 0) { | |||||
return driver; | |||||
} else { | |||||
delete driver; | |||||
return NULL; | |||||
} | |||||
} | |||||
#ifdef __cplusplus | |||||
} | |||||
#endif | |||||
@@ -0,0 +1,80 @@ | |||||
/* | |||||
Copyright (C) 2009 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 __JackCoreMidiDriver__ | |||||
#define __JackCoreMidiDriver__ | |||||
#include <CoreMIDI/CoreMIDI.h> | |||||
#include "JackMidiDriver.h" | |||||
#include "JackTime.h" | |||||
namespace Jack | |||||
{ | |||||
/*! | |||||
\brief The CoreMidi driver. | |||||
*/ | |||||
class JackCoreMidiDriver : public JackMidiDriver | |||||
{ | |||||
private: | |||||
MIDIClientRef fMidiClient; | |||||
MIDIPortRef fInputPort; | |||||
MIDIPortRef fOutputPort; | |||||
MIDIEndpointRef* fMidiDestination; | |||||
MIDIEndpointRef* fMidiSource; | |||||
char fMIDIBuffer[BUFFER_SIZE_MAX * sizeof(float)]; | |||||
int fRealCaptureChannels; | |||||
int fRealPlaybackChannels; | |||||
static void ReadProcAux(const MIDIPacketList *pktlist, jack_ringbuffer_t* ringbuffer); | |||||
static void ReadProc(const MIDIPacketList *pktlist, void *refCon, void *connRefCon); | |||||
static void ReadVirtualProc(const MIDIPacketList *pktlist, void *refCon, void *connRefCon); | |||||
static void NotifyProc(const MIDINotification *message, void *refCon); | |||||
public: | |||||
JackCoreMidiDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table); | |||||
virtual ~JackCoreMidiDriver(); | |||||
int Open( bool capturing, | |||||
bool playing, | |||||
int chan_in, | |||||
int chan_out, | |||||
bool monitor, | |||||
const char* capture_driver_name, | |||||
const char* playback_driver_name, | |||||
jack_nframes_t capture_latency, | |||||
jack_nframes_t playback_latency); | |||||
int Close(); | |||||
int Attach(); | |||||
int Read(); | |||||
int Write(); | |||||
}; | |||||
} // end of namespace | |||||
#endif |
@@ -30,6 +30,21 @@ def create_jack_audio_driver_obj(bld, target, sources, uselib = None): | |||||
driver.uselib = uselib | driver.uselib = uselib | ||||
return driver | return driver | ||||
def create_jack_midi_driver_obj(bld, target, sources, uselib = None): | |||||
driver = bld.new_task_gen('cxx', 'shlib') | |||||
driver.features.append('cc') | |||||
driver.env['shlib_PATTERN'] = 'jack_%s.so' | |||||
driver.defines = 'HAVE_CONFIG_H' | |||||
driver.includes = ['.', '../macosx', '../posix', '../common', '../common/jack'] | |||||
driver.target = target | |||||
driver.source = sources | |||||
driver.install_path = '${ADDON_DIR}/' | |||||
driver.uselib_local = 'serverlib' | |||||
driver.env.append_value("LINKFLAGS", "-framework CoreMIDI -framework CoreServices -framework AudioUnit") | |||||
if uselib: | |||||
driver.uselib = uselib | |||||
return driver | |||||
def build(bld): | def build(bld): | ||||
jackd = bld.new_task_gen('cxx', 'program') | jackd = bld.new_task_gen('cxx', 'program') | ||||
jackd.includes = ['.', '../macosx', '../posix', '../common', '../common/jack'] | jackd.includes = ['.', '../macosx', '../posix', '../common', '../common/jack'] | ||||
@@ -43,6 +58,8 @@ def build(bld): | |||||
create_jack_driver_obj(bld, 'dummy', '../common/JackDummyDriver.cpp') | create_jack_driver_obj(bld, 'dummy', '../common/JackDummyDriver.cpp') | ||||
create_jack_audio_driver_obj(bld, 'coreaudio', 'coreaudio/JackCoreAudioDriver.cpp') | create_jack_audio_driver_obj(bld, 'coreaudio', 'coreaudio/JackCoreAudioDriver.cpp') | ||||
create_jack_midi_driver_obj(bld, 'coremidi', 'coremidi/JackCoreMidiDriver.cpp') | |||||
portaudio_src = [ | portaudio_src = [ | ||||
'../windows/JackPortAudioDriver.cpp', | '../windows/JackPortAudioDriver.cpp', | ||||
@@ -0,0 +1,121 @@ | |||||
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> | |||||
<CodeBlocks_project_file> | |||||
<FileVersion major="1" minor="6" /> | |||||
<Project> | |||||
<Option title="jack_winmme" /> | |||||
<Option pch_mode="2" /> | |||||
<Option compiler="gcc" /> | |||||
<Build> | |||||
<Target title="Win32 Release"> | |||||
<Option output="Release\bin\jack\jack_winmme" prefix_auto="1" extension_auto="1" /> | |||||
<Option object_output="Release" /> | |||||
<Option type="3" /> | |||||
<Option compiler="gcc" /> | |||||
<Compiler> | |||||
<Add option="-O2" /> | |||||
<Add option="-Wall" /> | |||||
<Add option="-DWIN32" /> | |||||
<Add option="-DNDEBUG" /> | |||||
<Add option="-D_WINDOWS" /> | |||||
<Add option="-D_MBCS" /> | |||||
<Add option="-D_USRDLL" /> | |||||
<Add option="-DSERVER_SIDE" /> | |||||
<Add directory="." /> | |||||
<Add directory="..\windows" /> | |||||
<Add directory="..\common\jack" /> | |||||
<Add directory="..\common" /> | |||||
<Add directory="winmme" /> | |||||
</Compiler> | |||||
<Linker> | |||||
<Add directory="..\windows" /> | |||||
<Add directory="Release\bin" /> | |||||
</Linker> | |||||
</Target> | |||||
<Target title="Win32 Debug"> | |||||
<Option output="Debug\bin\jack\jack_winmme" prefix_auto="1" extension_auto="1" /> | |||||
<Option object_output="Debug" /> | |||||
<Option type="3" /> | |||||
<Option compiler="gcc" /> | |||||
<Compiler> | |||||
<Add option="-W" /> | |||||
<Add option="-g" /> | |||||
<Add option="-DWIN32" /> | |||||
<Add option="-D_DEBUG" /> | |||||
<Add option="-D_WINDOWS" /> | |||||
<Add option="-D_MBCS" /> | |||||
<Add option="-D_USRDLL" /> | |||||
<Add option="-DSERVER_SIDE" /> | |||||
<Add directory="." /> | |||||
<Add directory="..\windows" /> | |||||
<Add directory="..\common\jack" /> | |||||
<Add directory="..\common" /> | |||||
<Add directory="winmme" /> | |||||
</Compiler> | |||||
<Linker> | |||||
<Add directory="Debug\bin" /> | |||||
<Add directory="..\windows" /> | |||||
</Linker> | |||||
</Target> | |||||
<Target title="Win32 Profiling"> | |||||
<Option output="Release\bin\jack\jack_winmme" prefix_auto="1" extension_auto="1" /> | |||||
<Option object_output="Release" /> | |||||
<Option type="3" /> | |||||
<Option compiler="gcc" /> | |||||
<Compiler> | |||||
<Add option="-O2" /> | |||||
<Add option="-Wall" /> | |||||
<Add option="-DWIN32" /> | |||||
<Add option="-DNDEBUG" /> | |||||
<Add option="-D_WINDOWS" /> | |||||
<Add option="-D_MBCS" /> | |||||
<Add option="-D_USRDLL" /> | |||||
<Add option="-DJACK_MONITOR" /> | |||||
<Add option="-DSERVER_SIDE" /> | |||||
<Add directory="." /> | |||||
<Add directory="..\windows" /> | |||||
<Add directory="..\common\jack" /> | |||||
<Add directory="..\common" /> | |||||
<Add directory="winmme" /> | |||||
</Compiler> | |||||
<Linker> | |||||
<Add directory="Release\bin" /> | |||||
<Add directory="..\windows" /> | |||||
</Linker> | |||||
</Target> | |||||
</Build> | |||||
<Compiler> | |||||
<Add option="-Wall" /> | |||||
</Compiler> | |||||
<Linker> | |||||
<Add library="kernel32" /> | |||||
<Add library="user32" /> | |||||
<Add library="gdi32" /> | |||||
<Add library="winspool" /> | |||||
<Add library="comdlg32" /> | |||||
<Add library="advapi32" /> | |||||
<Add library="shell32" /> | |||||
<Add library="ole32" /> | |||||
<Add library="oleaut32" /> | |||||
<Add library="uuid" /> | |||||
<Add library="odbc32" /> | |||||
<Add library="odbccp32" /> | |||||
<Add library="libjackserver" /> | |||||
<Add library="winmm" /> | |||||
</Linker> | |||||
<Unit filename="jackwinmme.rc"> | |||||
<Option compilerVar="WINDRES" /> | |||||
</Unit> | |||||
<Unit filename="winmme\JackWinMMEDriver.cpp" /> | |||||
<Extensions> | |||||
<code_completion /> | |||||
<envvars /> | |||||
<debugger /> | |||||
<lib_finder disable_auto="1" /> | |||||
<AutoVersioning> | |||||
<Scheme minor_max="10" build_max="0" rev_max="0" rev_rand_max="10" build_times_to_increment_minor="100" /> | |||||
<Settings autoincrement="1" date_declarations="1" do_auto_increment="0" ask_to_increment="0" language="C++" svn="0" svn_directory="" header_path="version.h" /> | |||||
<Changes_Log show_changes_editor="0" app_title="released version %M.%m.%b of %p" changeslog_path="ChangesLog.txt" /> | |||||
</AutoVersioning> | |||||
</Extensions> | |||||
</Project> | |||||
</CodeBlocks_project_file> |
@@ -1,7 +1,7 @@ | |||||
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> | <?xml version="1.0" encoding="UTF-8" standalone="yes" ?> | ||||
<CodeBlocks_workspace_file> | <CodeBlocks_workspace_file> | ||||
<Workspace title="jack"> | <Workspace title="jack"> | ||||
<Project filename="libjackserver.cbp" active="1" /> | |||||
<Project filename="libjackserver.cbp" /> | |||||
<Project filename="jackd.cbp"> | <Project filename="jackd.cbp"> | ||||
<Depends filename="libjackserver.cbp" /> | <Depends filename="libjackserver.cbp" /> | ||||
</Project> | </Project> | ||||
@@ -46,5 +46,6 @@ | |||||
<Project filename="multiple_metro.cbp"> | <Project filename="multiple_metro.cbp"> | ||||
<Depends filename="libjack.cbp" /> | <Depends filename="libjack.cbp" /> | ||||
</Project> | </Project> | ||||
<Project filename="jack_winmme.cbp" active="1" /> | |||||
</Workspace> | </Workspace> | ||||
</CodeBlocks_workspace_file> | </CodeBlocks_workspace_file> |
@@ -0,0 +1,41 @@ | |||||
// Generated by ResEdit 1.4.3 | |||||
// Copyright (C) 2006-2008 | |||||
// http://www.resedit.net | |||||
#include "resource.h" | |||||
#include "afxres.h" | |||||
// | |||||
// Version Information resources | |||||
// | |||||
LANGUAGE LANG_FRENCH, SUBLANG_DEFAULT | |||||
1 VERSIONINFO | |||||
FILEVERSION 1,9,3,0 | |||||
PRODUCTVERSION 1,9,3,0 | |||||
FILEOS VOS_UNKNOWN | |||||
FILETYPE VFT_DLL | |||||
BEGIN | |||||
BLOCK "StringFileInfo" | |||||
BEGIN | |||||
BLOCK "040c04b0" | |||||
BEGIN | |||||
VALUE "Comments", "\0" | |||||
VALUE "CompanyName", "Grame\0" | |||||
VALUE "FileDescription", "Jackmp WinMMEo Driver for Windows\0" | |||||
VALUE "FileVersion", "1, 9, 3, 0\0" | |||||
VALUE "InternalName", "jack_portaudio\0" | |||||
VALUE "LegalCopyright", "Copyright Grame © 2006-2009\0" | |||||
VALUE "LegalTrademarks", "\0" | |||||
VALUE "OriginalFilename", "jack_winmme.dll\0" | |||||
VALUE "PrivateBuild", "\0" | |||||
VALUE "ProductName", "jack_winmme\0" | |||||
VALUE "ProductVersion", "1, 9, 3, 0\0" | |||||
VALUE "SpecialBuild", "\0" | |||||
END | |||||
END | |||||
BLOCK "VarFileInfo" | |||||
BEGIN | |||||
VALUE "Translation", 1036, 1200 | |||||
END | |||||
END |
@@ -1,199 +1,200 @@ | |||||
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> | |||||
<CodeBlocks_project_file> | |||||
<FileVersion major="1" minor="6" /> | |||||
<Project> | |||||
<Option title="libjackserver" /> | |||||
<Option pch_mode="2" /> | |||||
<Option compiler="gcc" /> | |||||
<Build> | |||||
<Target title="Win32 Release"> | |||||
<Option output="Release\bin\libjackserver" prefix_auto="1" extension_auto="1" /> | |||||
<Option object_output="Release" /> | |||||
<Option type="3" /> | |||||
<Option compiler="gcc" /> | |||||
<Option createDefFile="1" /> | |||||
<Option createStaticLib="1" /> | |||||
<Compiler> | |||||
<Add option="-O2" /> | |||||
<Add option="-Wall" /> | |||||
<Add option="-DWIN32" /> | |||||
<Add option="-DNDEBUG" /> | |||||
<Add option="-D_WINDOWS" /> | |||||
<Add option="-D_MBCS" /> | |||||
<Add option="-D_USRDLL" /> | |||||
<Add option="-DLIBJACKDMP_EXPORTS" /> | |||||
<Add option="-DREGEX_MALLOC" /> | |||||
<Add option="-DSTDC_HEADERS" /> | |||||
<Add option="-DSERVER_SIDE" /> | |||||
<Add option="-D__SMP__" /> | |||||
<Add directory="." /> | |||||
<Add directory="..\windows" /> | |||||
<Add directory="..\common\jack" /> | |||||
<Add directory="..\common" /> | |||||
</Compiler> | |||||
<Linker> | |||||
<Add directory="Release\bin" /> | |||||
</Linker> | |||||
</Target> | |||||
<Target title="Win32 Debug"> | |||||
<Option output="Debug\bin\libjackserver" prefix_auto="1" extension_auto="1" /> | |||||
<Option object_output="Debug" /> | |||||
<Option type="3" /> | |||||
<Option compiler="gcc" /> | |||||
<Option createDefFile="1" /> | |||||
<Option createStaticLib="1" /> | |||||
<Compiler> | |||||
<Add option="-Wall" /> | |||||
<Add option="-g" /> | |||||
<Add option="-DWIN32" /> | |||||
<Add option="-D_DEBUG" /> | |||||
<Add option="-D_WINDOWS" /> | |||||
<Add option="-D_MBCS" /> | |||||
<Add option="-D_USRDLL" /> | |||||
<Add option="-DLIBJACKDMP_EXPORTS" /> | |||||
<Add option="-DREGEX_MALLOC" /> | |||||
<Add option="-DSTDC_HEADERS" /> | |||||
<Add option="-DSERVER_SIDE" /> | |||||
<Add option="-D__SMP__" /> | |||||
<Add directory="." /> | |||||
<Add directory="..\windows" /> | |||||
<Add directory="..\common\jack" /> | |||||
<Add directory="..\common" /> | |||||
</Compiler> | |||||
<Linker> | |||||
<Add directory="Debug\bin" /> | |||||
</Linker> | |||||
</Target> | |||||
<Target title="Win32 Profiling"> | |||||
<Option output="Release\bin\libjackserver" prefix_auto="1" extension_auto="1" /> | |||||
<Option object_output="Release" /> | |||||
<Option type="3" /> | |||||
<Option compiler="gcc" /> | |||||
<Option createDefFile="1" /> | |||||
<Option createStaticLib="1" /> | |||||
<Compiler> | |||||
<Add option="-O2" /> | |||||
<Add option="-Wall" /> | |||||
<Add option="-DWIN32" /> | |||||
<Add option="-DNDEBUG" /> | |||||
<Add option="-D_WINDOWS" /> | |||||
<Add option="-D_MBCS" /> | |||||
<Add option="-D_USRDLL" /> | |||||
<Add option="-DLIBJACKDMP_EXPORTS" /> | |||||
<Add option="-DREGEX_MALLOC" /> | |||||
<Add option="-DSTDC_HEADERS" /> | |||||
<Add option="-DSERVER_SIDE" /> | |||||
<Add option="-D__SMP__" /> | |||||
<Add option="-DJACK_MONITOR" /> | |||||
<Add directory="." /> | |||||
<Add directory="..\windows" /> | |||||
<Add directory="..\common\jack" /> | |||||
<Add directory="..\common" /> | |||||
</Compiler> | |||||
<Linker> | |||||
<Add directory="Release\bin" /> | |||||
</Linker> | |||||
</Target> | |||||
</Build> | |||||
<Compiler> | |||||
<Add option="-Wall" /> | |||||
<Add directory="." /> | |||||
<Add directory="..\common" /> | |||||
<Add directory="..\common\jack" /> | |||||
</Compiler> | |||||
<Linker> | |||||
<Add library="kernel32" /> | |||||
<Add library="user32" /> | |||||
<Add library="gdi32" /> | |||||
<Add library="winspool" /> | |||||
<Add library="comdlg32" /> | |||||
<Add library="advapi32" /> | |||||
<Add library="shell32" /> | |||||
<Add library="ole32" /> | |||||
<Add library="oleaut32" /> | |||||
<Add library="uuid" /> | |||||
<Add library="odbc32" /> | |||||
<Add library="odbccp32" /> | |||||
<Add library="ws2_32" /> | |||||
</Linker> | |||||
<Unit filename="..\common\JackAPI.cpp" /> | |||||
<Unit filename="..\common\JackActivationCount.cpp" /> | |||||
<Unit filename="..\common\JackArgParser.cpp" /> | |||||
<Unit filename="..\common\JackAudioDriver.cpp" /> | |||||
<Unit filename="..\common\JackAudioPort.cpp" /> | |||||
<Unit filename="..\common\JackClient.cpp" /> | |||||
<Unit filename="..\common\JackConnectionManager.cpp" /> | |||||
<Unit filename="..\common\JackControlAPI.cpp" /> | |||||
<Unit filename="..\common\JackDriver.cpp" /> | |||||
<Unit filename="..\common\JackDriverLoader.cpp" /> | |||||
<Unit filename="..\common\JackEngine.cpp" /> | |||||
<Unit filename="..\common\JackEngineControl.cpp" /> | |||||
<Unit filename="..\common\JackEngineProfiling.cpp"> | |||||
<Option target="Win32 Profiling" /> | |||||
</Unit> | |||||
<Unit filename="..\common\JackError.cpp" /> | |||||
<Unit filename="..\common\JackExternalClient.cpp" /> | |||||
<Unit filename="..\common\JackFrameTimer.cpp" /> | |||||
<Unit filename="..\common\JackFreewheelDriver.cpp" /> | |||||
<Unit filename="..\common\JackGlobals.cpp" /> | |||||
<Unit filename="..\common\JackGraphManager.cpp" /> | |||||
<Unit filename="..\common\JackInternalClient.cpp" /> | |||||
<Unit filename="..\common\JackLoopbackDriver.cpp" /> | |||||
<Unit filename="..\common\JackMessageBuffer.cpp" /> | |||||
<Unit filename="..\common\JackMidiAPI.cpp" /> | |||||
<Unit filename="..\common\JackMidiPort.cpp" /> | |||||
<Unit filename="..\common\JackNetInterface.cpp" /> | |||||
<Unit filename="..\common\JackNetTool.cpp" /> | |||||
<Unit filename="..\common\JackPort.cpp" /> | |||||
<Unit filename="..\common\JackPortType.cpp" /> | |||||
<Unit filename="..\common\JackRestartThreadedDriver.cpp" /> | |||||
<Unit filename="..\common\JackServer.cpp" /> | |||||
<Unit filename="..\common\JackServerAPI.cpp" /> | |||||
<Unit filename="..\common\JackServerGlobals.cpp" /> | |||||
<Unit filename="..\common\JackShmMem.cpp" /> | |||||
<Unit filename="..\common\JackThreadedDriver.cpp" /> | |||||
<Unit filename="..\common\JackTools.cpp" /> | |||||
<Unit filename="..\common\JackTransportEngine.cpp" /> | |||||
<Unit filename="..\common\JackWaitThreadedDriver.cpp" /> | |||||
<Unit filename="..\common\ringbuffer.c"> | |||||
<Option compilerVar="CC" /> | |||||
</Unit> | |||||
<Unit filename="..\common\shm.c"> | |||||
<Option compilerVar="CC" /> | |||||
</Unit> | |||||
<Unit filename="JackNetWinSocket.cpp" /> | |||||
<Unit filename="JackWinNamedPipe.cpp" /> | |||||
<Unit filename="JackWinNamedPipeClientChannel.cpp" /> | |||||
<Unit filename="JackWinNamedPipeNotifyChannel.cpp" /> | |||||
<Unit filename="JackWinNamedPipeServerChannel.cpp" /> | |||||
<Unit filename="JackWinNamedPipeServerNotifyChannel.cpp" /> | |||||
<Unit filename="JackWinProcessSync.cpp" /> | |||||
<Unit filename="JackWinSemaphore.cpp" /> | |||||
<Unit filename="JackWinThread.cpp" /> | |||||
<Unit filename="JackWinTime.c"> | |||||
<Option compilerVar="CC" /> | |||||
</Unit> | |||||
<Unit filename="getopt.c"> | |||||
<Option compilerVar="CC" /> | |||||
</Unit> | |||||
<Unit filename="getopt1.c"> | |||||
<Option compilerVar="CC" /> | |||||
</Unit> | |||||
<Unit filename="libjackserver.rc"> | |||||
<Option compilerVar="WINDRES" /> | |||||
</Unit> | |||||
<Unit filename="regex.c"> | |||||
<Option compilerVar="CC" /> | |||||
</Unit> | |||||
<Extensions> | |||||
<code_completion /> | |||||
<envvars /> | |||||
<debugger /> | |||||
<AutoVersioning> | |||||
<Scheme minor_max="10" build_max="0" rev_max="0" rev_rand_max="10" build_times_to_increment_minor="100" /> | |||||
<Settings autoincrement="0" date_declarations="0" do_auto_increment="0" ask_to_increment="0" language="C++" svn="0" svn_directory="" header_path="version.h" /> | |||||
<Changes_Log show_changes_editor="0" app_title="released version %M.%m.%b of %p" changeslog_path="ChangesLog.txt" /> | |||||
</AutoVersioning> | |||||
</Extensions> | |||||
</Project> | |||||
</CodeBlocks_project_file> | |||||
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> | |||||
<CodeBlocks_project_file> | |||||
<FileVersion major="1" minor="6" /> | |||||
<Project> | |||||
<Option title="libjackserver" /> | |||||
<Option pch_mode="2" /> | |||||
<Option compiler="gcc" /> | |||||
<Build> | |||||
<Target title="Win32 Release"> | |||||
<Option output="Release\bin\libjackserver" prefix_auto="1" extension_auto="1" /> | |||||
<Option object_output="Release" /> | |||||
<Option type="3" /> | |||||
<Option compiler="gcc" /> | |||||
<Option createDefFile="1" /> | |||||
<Option createStaticLib="1" /> | |||||
<Compiler> | |||||
<Add option="-O2" /> | |||||
<Add option="-Wall" /> | |||||
<Add option="-DWIN32" /> | |||||
<Add option="-DNDEBUG" /> | |||||
<Add option="-D_WINDOWS" /> | |||||
<Add option="-D_MBCS" /> | |||||
<Add option="-D_USRDLL" /> | |||||
<Add option="-DLIBJACKDMP_EXPORTS" /> | |||||
<Add option="-DREGEX_MALLOC" /> | |||||
<Add option="-DSTDC_HEADERS" /> | |||||
<Add option="-DSERVER_SIDE" /> | |||||
<Add option="-D__SMP__" /> | |||||
<Add directory="." /> | |||||
<Add directory="..\windows" /> | |||||
<Add directory="..\common\jack" /> | |||||
<Add directory="..\common" /> | |||||
</Compiler> | |||||
<Linker> | |||||
<Add directory="Release\bin" /> | |||||
</Linker> | |||||
</Target> | |||||
<Target title="Win32 Debug"> | |||||
<Option output="Debug\bin\libjackserver" prefix_auto="1" extension_auto="1" /> | |||||
<Option object_output="Debug" /> | |||||
<Option type="3" /> | |||||
<Option compiler="gcc" /> | |||||
<Option createDefFile="1" /> | |||||
<Option createStaticLib="1" /> | |||||
<Compiler> | |||||
<Add option="-Wall" /> | |||||
<Add option="-g" /> | |||||
<Add option="-DWIN32" /> | |||||
<Add option="-D_DEBUG" /> | |||||
<Add option="-D_WINDOWS" /> | |||||
<Add option="-D_MBCS" /> | |||||
<Add option="-D_USRDLL" /> | |||||
<Add option="-DLIBJACKDMP_EXPORTS" /> | |||||
<Add option="-DREGEX_MALLOC" /> | |||||
<Add option="-DSTDC_HEADERS" /> | |||||
<Add option="-DSERVER_SIDE" /> | |||||
<Add option="-D__SMP__" /> | |||||
<Add directory="." /> | |||||
<Add directory="..\windows" /> | |||||
<Add directory="..\common\jack" /> | |||||
<Add directory="..\common" /> | |||||
</Compiler> | |||||
<Linker> | |||||
<Add directory="Debug\bin" /> | |||||
</Linker> | |||||
</Target> | |||||
<Target title="Win32 Profiling"> | |||||
<Option output="Release\bin\libjackserver" prefix_auto="1" extension_auto="1" /> | |||||
<Option object_output="Release" /> | |||||
<Option type="3" /> | |||||
<Option compiler="gcc" /> | |||||
<Option createDefFile="1" /> | |||||
<Option createStaticLib="1" /> | |||||
<Compiler> | |||||
<Add option="-O2" /> | |||||
<Add option="-Wall" /> | |||||
<Add option="-DWIN32" /> | |||||
<Add option="-DNDEBUG" /> | |||||
<Add option="-D_WINDOWS" /> | |||||
<Add option="-D_MBCS" /> | |||||
<Add option="-D_USRDLL" /> | |||||
<Add option="-DLIBJACKDMP_EXPORTS" /> | |||||
<Add option="-DREGEX_MALLOC" /> | |||||
<Add option="-DSTDC_HEADERS" /> | |||||
<Add option="-DSERVER_SIDE" /> | |||||
<Add option="-D__SMP__" /> | |||||
<Add option="-DJACK_MONITOR" /> | |||||
<Add directory="." /> | |||||
<Add directory="..\windows" /> | |||||
<Add directory="..\common\jack" /> | |||||
<Add directory="..\common" /> | |||||
</Compiler> | |||||
<Linker> | |||||
<Add directory="Release\bin" /> | |||||
</Linker> | |||||
</Target> | |||||
</Build> | |||||
<Compiler> | |||||
<Add option="-Wall" /> | |||||
<Add directory="." /> | |||||
<Add directory="..\common" /> | |||||
<Add directory="..\common\jack" /> | |||||
</Compiler> | |||||
<Linker> | |||||
<Add library="kernel32" /> | |||||
<Add library="user32" /> | |||||
<Add library="gdi32" /> | |||||
<Add library="winspool" /> | |||||
<Add library="comdlg32" /> | |||||
<Add library="advapi32" /> | |||||
<Add library="shell32" /> | |||||
<Add library="ole32" /> | |||||
<Add library="oleaut32" /> | |||||
<Add library="uuid" /> | |||||
<Add library="odbc32" /> | |||||
<Add library="odbccp32" /> | |||||
<Add library="ws2_32" /> | |||||
</Linker> | |||||
<Unit filename="..\common\JackAPI.cpp" /> | |||||
<Unit filename="..\common\JackActivationCount.cpp" /> | |||||
<Unit filename="..\common\JackArgParser.cpp" /> | |||||
<Unit filename="..\common\JackAudioDriver.cpp" /> | |||||
<Unit filename="..\common\JackAudioPort.cpp" /> | |||||
<Unit filename="..\common\JackClient.cpp" /> | |||||
<Unit filename="..\common\JackConnectionManager.cpp" /> | |||||
<Unit filename="..\common\JackControlAPI.cpp" /> | |||||
<Unit filename="..\common\JackDriver.cpp" /> | |||||
<Unit filename="..\common\JackDriverLoader.cpp" /> | |||||
<Unit filename="..\common\JackEngine.cpp" /> | |||||
<Unit filename="..\common\JackEngineControl.cpp" /> | |||||
<Unit filename="..\common\JackEngineProfiling.cpp"> | |||||
<Option target="Win32 Profiling" /> | |||||
</Unit> | |||||
<Unit filename="..\common\JackError.cpp" /> | |||||
<Unit filename="..\common\JackExternalClient.cpp" /> | |||||
<Unit filename="..\common\JackFrameTimer.cpp" /> | |||||
<Unit filename="..\common\JackFreewheelDriver.cpp" /> | |||||
<Unit filename="..\common\JackGlobals.cpp" /> | |||||
<Unit filename="..\common\JackGraphManager.cpp" /> | |||||
<Unit filename="..\common\JackInternalClient.cpp" /> | |||||
<Unit filename="..\common\JackLoopbackDriver.cpp" /> | |||||
<Unit filename="..\common\JackMessageBuffer.cpp" /> | |||||
<Unit filename="..\common\JackMidiAPI.cpp" /> | |||||
<Unit filename="..\common\JackMidiDriver.cpp" /> | |||||
<Unit filename="..\common\JackMidiPort.cpp" /> | |||||
<Unit filename="..\common\JackNetInterface.cpp" /> | |||||
<Unit filename="..\common\JackNetTool.cpp" /> | |||||
<Unit filename="..\common\JackPort.cpp" /> | |||||
<Unit filename="..\common\JackPortType.cpp" /> | |||||
<Unit filename="..\common\JackRestartThreadedDriver.cpp" /> | |||||
<Unit filename="..\common\JackServer.cpp" /> | |||||
<Unit filename="..\common\JackServerAPI.cpp" /> | |||||
<Unit filename="..\common\JackServerGlobals.cpp" /> | |||||
<Unit filename="..\common\JackShmMem.cpp" /> | |||||
<Unit filename="..\common\JackThreadedDriver.cpp" /> | |||||
<Unit filename="..\common\JackTools.cpp" /> | |||||
<Unit filename="..\common\JackTransportEngine.cpp" /> | |||||
<Unit filename="..\common\JackWaitThreadedDriver.cpp" /> | |||||
<Unit filename="..\common\ringbuffer.c"> | |||||
<Option compilerVar="CC" /> | |||||
</Unit> | |||||
<Unit filename="..\common\shm.c"> | |||||
<Option compilerVar="CC" /> | |||||
</Unit> | |||||
<Unit filename="JackNetWinSocket.cpp" /> | |||||
<Unit filename="JackWinNamedPipe.cpp" /> | |||||
<Unit filename="JackWinNamedPipeClientChannel.cpp" /> | |||||
<Unit filename="JackWinNamedPipeNotifyChannel.cpp" /> | |||||
<Unit filename="JackWinNamedPipeServerChannel.cpp" /> | |||||
<Unit filename="JackWinNamedPipeServerNotifyChannel.cpp" /> | |||||
<Unit filename="JackWinProcessSync.cpp" /> | |||||
<Unit filename="JackWinSemaphore.cpp" /> | |||||
<Unit filename="JackWinThread.cpp" /> | |||||
<Unit filename="JackWinTime.c"> | |||||
<Option compilerVar="CC" /> | |||||
</Unit> | |||||
<Unit filename="getopt.c"> | |||||
<Option compilerVar="CC" /> | |||||
</Unit> | |||||
<Unit filename="getopt1.c"> | |||||
<Option compilerVar="CC" /> | |||||
</Unit> | |||||
<Unit filename="libjackserver.rc"> | |||||
<Option compilerVar="WINDRES" /> | |||||
</Unit> | |||||
<Unit filename="regex.c"> | |||||
<Option compilerVar="CC" /> | |||||
</Unit> | |||||
<Extensions> | |||||
<code_completion /> | |||||
<envvars /> | |||||
<debugger /> | |||||
<AutoVersioning> | |||||
<Scheme minor_max="10" build_max="0" rev_max="0" rev_rand_max="10" build_times_to_increment_minor="100" /> | |||||
<Settings autoincrement="0" date_declarations="0" do_auto_increment="0" ask_to_increment="0" language="C++" svn="0" svn_directory="" header_path="version.h" /> | |||||
<Changes_Log show_changes_editor="0" app_title="released version %M.%m.%b of %p" changeslog_path="ChangesLog.txt" /> | |||||
</AutoVersioning> | |||||
</Extensions> | |||||
</Project> | |||||
</CodeBlocks_project_file> |
@@ -0,0 +1,501 @@ | |||||
/* | |||||
Copyright (C) 2009 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. | |||||
*/ | |||||
#include "JackWinMMEDriver.h" | |||||
#include "JackGraphManager.h" | |||||
#include "JackEngineControl.h" | |||||
#include "JackDriverLoader.h" | |||||
#include <assert.h> | |||||
#include <iostream> | |||||
#include <sstream> | |||||
#include <string> | |||||
#include <windows.h> | |||||
#include <windowsx.h> | |||||
#include <mmsystem.h> | |||||
namespace Jack | |||||
{ | |||||
static bool InitHeaders(MidiSlot* slot) | |||||
{ | |||||
slot->fHeader = (LPMIDIHDR)GlobalAllocPtr(GMEM_MOVEABLE|GMEM_SHARE|GMEM_ZEROINIT, sizeof(MIDIHDR) + kBuffSize); | |||||
if (!slot->fHeader) | |||||
return false; | |||||
slot->fHeader->lpData = (LPSTR)((LPBYTE)slot->fHeader + sizeof(MIDIHDR)); | |||||
slot->fHeader->dwBufferLength = kBuffSize; | |||||
slot->fHeader->dwFlags = 0; | |||||
slot->fHeader->dwUser = 0; | |||||
slot->fHeader->lpNext = 0; | |||||
slot->fHeader->dwBytesRecorded = 0; | |||||
return true; | |||||
} | |||||
void CALLBACK JackWinMMEDriver::MidiInProc(HMIDIIN hMidiIn, UINT wMsg, DWORD userData, DWORD dwParam1, DWORD dwParam2) | |||||
{ | |||||
jack_ringbuffer_t* ringbuffer = (jack_ringbuffer_t*)userData; | |||||
//jack_info("JackWinMMEDriver::MidiInProc 0\n"); | |||||
switch (wMsg) { | |||||
case MIM_OPEN: | |||||
break; | |||||
case MIM_ERROR: | |||||
case MIM_DATA: { | |||||
//jack_info("JackWinMMEDriver::MidiInProc"); | |||||
// One event | |||||
unsigned int num_packet = 1; | |||||
jack_ringbuffer_write(ringbuffer, (char*)&num_packet, sizeof(unsigned int)); | |||||
// Write event actual data | |||||
jack_ringbuffer_write(ringbuffer, (char*)&dwParam1, 3); | |||||
break; | |||||
} | |||||
case MIM_LONGERROR: | |||||
case MIM_LONGDATA: | |||||
/* | |||||
Nothing for now | |||||
*/ | |||||
break; | |||||
} | |||||
} | |||||
JackWinMMEDriver::JackWinMMEDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table) | |||||
: JackMidiDriver(name, alias, engine, table), | |||||
fRealCaptureChannels(0), | |||||
fRealPlaybackChannels(0), | |||||
fMidiSource(NULL), | |||||
fMidiDestination(NULL) | |||||
{} | |||||
JackWinMMEDriver::~JackWinMMEDriver() | |||||
{} | |||||
int JackWinMMEDriver::Open(bool capturing, | |||||
bool playing, | |||||
int inchannels, | |||||
int outchannels, | |||||
bool monitor, | |||||
const char* capture_driver_name, | |||||
const char* playback_driver_name, | |||||
jack_nframes_t capture_latency, | |||||
jack_nframes_t playback_latency) | |||||
{ | |||||
jack_log("JackWinMMEDriver::Open"); | |||||
fRealCaptureChannels = midiInGetNumDevs(); | |||||
fRealPlaybackChannels = midiOutGetNumDevs (); | |||||
// Generic JackMidiDriver Open | |||||
if (JackMidiDriver::Open(capturing, playing, inchannels + fRealCaptureChannels, outchannels + fRealPlaybackChannels, monitor, capture_driver_name, playback_driver_name, capture_latency, playback_latency) != 0) | |||||
return -1; | |||||
fMidiDestination = new MidiSlot[fRealCaptureChannels]; | |||||
assert(fMidiDestination); | |||||
// Real input | |||||
for (int i = 0; i < fRealCaptureChannels; i++) { | |||||
HMIDIIN handle; | |||||
fMidiDestination[i].fIndex = i; | |||||
MMRESULT ret = midiInOpen(&handle, fMidiDestination[i].fIndex, (DWORD)MidiInProc, (DWORD)fRingBuffer[i], CALLBACK_FUNCTION); | |||||
if (ret == MMSYSERR_NOERROR) { | |||||
fMidiDestination[i].fHandle = handle; | |||||
if (!InitHeaders(&fMidiDestination[i])) { | |||||
jack_error("memory allocation failed"); | |||||
midiInClose(handle); | |||||
goto error; | |||||
//continue; | |||||
} | |||||
ret = midiInPrepareHeader(handle, fMidiDestination[i].fHeader, sizeof(MIDIHDR)); | |||||
if (ret == MMSYSERR_NOERROR) { | |||||
fMidiDestination[i].fHeader->dwUser = 1; | |||||
ret = midiInAddBuffer(handle, fMidiDestination[i].fHeader, sizeof(MIDIHDR)); | |||||
if (ret == MMSYSERR_NOERROR) { | |||||
ret = midiInStart(handle); | |||||
if (ret != MMSYSERR_NOERROR) { | |||||
jack_error("midiInStart error"); | |||||
CloseInput(&fMidiDestination[i]); | |||||
goto error; | |||||
} | |||||
} else { | |||||
jack_error ("midiInAddBuffer error"); | |||||
CloseInput(&fMidiDestination[i]); | |||||
goto error; | |||||
} | |||||
} else { | |||||
jack_error("midiInPrepareHeader error"); | |||||
midiInClose(handle); | |||||
goto error; | |||||
} | |||||
} else { | |||||
jack_error ("midiInOpen error"); | |||||
goto error; | |||||
} | |||||
} | |||||
fMidiSource = new MidiSlot[fRealPlaybackChannels]; | |||||
assert(fMidiSource); | |||||
// Real output | |||||
for (int i = 0; i < fRealPlaybackChannels; i++) { | |||||
MMRESULT res; | |||||
HMIDIOUT handle; | |||||
fMidiSource[i].fIndex = i; | |||||
UINT ret = midiOutOpen(&handle, fMidiSource[i].fIndex, 0L, 0L, CALLBACK_NULL); | |||||
if (ret == MMSYSERR_NOERROR) { | |||||
fMidiSource[i].fHandle = handle; | |||||
if (!InitHeaders(&fMidiSource[i])) { | |||||
jack_error("memory allocation failed"); | |||||
midiOutClose(handle); | |||||
//continue; | |||||
goto error; | |||||
} | |||||
res = midiOutPrepareHeader(handle, fMidiSource[i].fHeader, sizeof(MIDIHDR)); | |||||
if (res != MMSYSERR_NOERROR) { | |||||
jack_error("midiOutPrepareHeader error %d %d %d", i, handle, res); | |||||
//continue; | |||||
goto error; | |||||
} else { | |||||
fMidiSource[i].fHeader->dwUser = 1; | |||||
} | |||||
} else { | |||||
jack_error("midiOutOpen error"); | |||||
goto error; | |||||
} | |||||
} | |||||
return 0; | |||||
error: | |||||
Close(); | |||||
return -1; | |||||
} | |||||
void JackWinMMEDriver::CloseInput(MidiSlot* slot) | |||||
{ | |||||
MMRESULT res; | |||||
int retry = 0; | |||||
if (slot->fHandle == 0) | |||||
return; | |||||
HMIDIIN handle = (HMIDIIN)slot->fHandle; | |||||
slot->fHeader->dwUser = 0; | |||||
res = midiInStop(handle); | |||||
if (res != MMSYSERR_NOERROR) { | |||||
jack_error("midiInStop error"); | |||||
} | |||||
res = midiInReset(handle); | |||||
if (res != MMSYSERR_NOERROR) { | |||||
jack_error("midiInReset error"); | |||||
} | |||||
res = midiInUnprepareHeader(handle, slot->fHeader, sizeof(MIDIHDR)); | |||||
if (res != MMSYSERR_NOERROR) { | |||||
jack_error("midiInUnprepareHeader error"); | |||||
} | |||||
do { | |||||
res = midiInClose(handle); | |||||
if (res != MMSYSERR_NOERROR) { | |||||
jack_error("midiInClose error"); | |||||
} | |||||
if (res == MIDIERR_STILLPLAYING) | |||||
midiInReset(handle); | |||||
Sleep (10); | |||||
retry++; | |||||
} while ((res == MIDIERR_STILLPLAYING) && (retry < 10)); | |||||
if (slot->fHeader) { | |||||
GlobalFreePtr(slot->fHeader); | |||||
} | |||||
} | |||||
void JackWinMMEDriver::CloseOutput(MidiSlot* slot) | |||||
{ | |||||
MMRESULT res; | |||||
int retry = 0; | |||||
if (slot->fHandle == 0) | |||||
return; | |||||
HMIDIOUT handle = (HMIDIOUT)slot->fHandle; | |||||
res = midiOutReset(handle); | |||||
if (res != MMSYSERR_NOERROR) | |||||
jack_error("midiOutReset error"); | |||||
midiOutUnprepareHeader(handle, slot->fHeader, sizeof(MIDIHDR)); | |||||
do { | |||||
res = midiOutClose(handle); | |||||
if (res != MMSYSERR_NOERROR) | |||||
jack_error("midiOutClose error"); | |||||
Sleep(10); | |||||
retry++; | |||||
} while ((res == MIDIERR_STILLPLAYING) && (retry < 10)); | |||||
if (slot->fHeader) { | |||||
GlobalFreePtr(slot->fHeader); | |||||
} | |||||
} | |||||
int JackWinMMEDriver::Close() | |||||
{ | |||||
jack_log("JackWinMMEDriver::Close"); | |||||
// Close input | |||||
if (fMidiDestination) { | |||||
for (int i = 0; i < fRealCaptureChannels; i++) { | |||||
CloseInput(&fMidiDestination[i]); | |||||
} | |||||
delete[] fMidiDestination; | |||||
} | |||||
// Close output | |||||
if (fMidiSource) { | |||||
for (int i = 0; i < fRealPlaybackChannels; i++) { | |||||
CloseOutput(&fMidiSource[i]); | |||||
} | |||||
delete[] fMidiSource; | |||||
} | |||||
return 0; | |||||
} | |||||
int JackWinMMEDriver::Attach() | |||||
{ | |||||
JackPort* port; | |||||
jack_port_id_t port_index; | |||||
char name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; | |||||
char alias[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; | |||||
unsigned long port_flags = JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal; | |||||
MMRESULT res; | |||||
int i; | |||||
jack_log("JackMidiDriver::Attach fBufferSize = %ld fSampleRate = %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate); | |||||
for (i = 0; i < fCaptureChannels; i++) { | |||||
MIDIINCAPS caps; | |||||
res = midiInGetDevCaps(i, &caps, sizeof(caps)); | |||||
if (res == MMSYSERR_NOERROR) { | |||||
snprintf(alias, sizeof(alias) - 1, "%s:%s:out%d", fAliasName, caps.szPname, i + 1); | |||||
} else { | |||||
snprintf(alias, sizeof(alias) - 1, "%s:%s:out%d", fAliasName, fCaptureDriverName, i + 1); | |||||
} | |||||
snprintf(name, sizeof(name) - 1, "%s:capture_%d", fClientControl.fName, i + 1); | |||||
if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE, (JackPortFlags)port_flags, fEngineControl->fBufferSize)) == NO_PORT) { | |||||
jack_error("driver: cannot register port for %s", name); | |||||
return -1; | |||||
} | |||||
port = fGraphManager->GetPort(port_index); | |||||
port->SetAlias(alias); | |||||
fCapturePortList[i] = port_index; | |||||
jack_log("JackMidiDriver::Attach fCapturePortList[i] port_index = %ld", port_index); | |||||
} | |||||
port_flags = JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal; | |||||
for (i = 0; i < fPlaybackChannels; i++) { | |||||
MIDIOUTCAPS caps; | |||||
res = midiOutGetDevCaps(i, &caps, sizeof(caps)); | |||||
if (res == MMSYSERR_NOERROR) { | |||||
snprintf(alias, sizeof(alias) - 1, "%s:%s:out%d", fAliasName, caps.szPname, i + 1); | |||||
} else { | |||||
snprintf(alias, sizeof(alias) - 1, "%s:%s:out%d", fAliasName, fPlaybackDriverName, i + 1); | |||||
} | |||||
snprintf(name, sizeof(name) - 1, "%s:playback_%d", fClientControl.fName, i + 1); | |||||
if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE, (JackPortFlags)port_flags, fEngineControl->fBufferSize)) == NO_PORT) { | |||||
jack_error("driver: cannot register port for %s", name); | |||||
return -1; | |||||
} | |||||
port = fGraphManager->GetPort(port_index); | |||||
port->SetAlias(alias); | |||||
fPlaybackPortList[i] = port_index; | |||||
jack_log("JackMidiDriver::Attach fPlaybackPortList[i] port_index = %ld", port_index); | |||||
} | |||||
return 0; | |||||
} | |||||
int JackWinMMEDriver::Read() | |||||
{ | |||||
size_t size; | |||||
for (int chan = 0; chan < fCaptureChannels; chan++) { | |||||
if (fGraphManager->GetConnectionsNum(fCapturePortList[chan]) > 0) { | |||||
JackMidiBuffer* midi_buffer = GetInputBuffer(chan); | |||||
if (jack_ringbuffer_read_space (fRingBuffer[chan]) == 0) { | |||||
// Reset buffer | |||||
midi_buffer->Reset(midi_buffer->nframes); | |||||
} else { | |||||
while ((size = jack_ringbuffer_read_space (fRingBuffer[chan])) > 0) { | |||||
//jack_info("jack_ringbuffer_read_space %d", size); | |||||
int ev_count = 0; | |||||
jack_ringbuffer_read(fRingBuffer[chan], (char*)&ev_count, sizeof(int)); | |||||
if (ev_count > 0) { | |||||
for (int j = 0; j < ev_count; j++) { | |||||
unsigned int event_len = 3; | |||||
// Read event actual data | |||||
jack_midi_data_t* dest = midi_buffer->ReserveEvent(0, event_len); | |||||
jack_ringbuffer_read(fRingBuffer[chan], (char*)dest, event_len); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} else { | |||||
//jack_info("Consume ring buffer"); | |||||
jack_ringbuffer_read_advance(fRingBuffer[chan], jack_ringbuffer_read_space(fRingBuffer[chan])); | |||||
} | |||||
} | |||||
return 0; | |||||
} | |||||
int JackWinMMEDriver::Write() | |||||
{ | |||||
for (int chan = 0; chan < fPlaybackChannels; chan++) { | |||||
if (fGraphManager->GetConnectionsNum(fPlaybackPortList[chan]) > 0) { | |||||
JackMidiBuffer* midi_buffer = GetOutputBuffer(chan); | |||||
// TODO : use timestamp | |||||
for (unsigned int j = 0; j < midi_buffer->event_count; j++) { | |||||
JackMidiEvent* ev = &midi_buffer->events[j]; | |||||
if (ev->size <= 3) { | |||||
MMRESULT res = midiOutShortMsg((HMIDIOUT)fMidiSource[chan].fHandle, *((DWORD*)ev->GetData(midi_buffer))); | |||||
if (res != MMSYSERR_NOERROR) | |||||
jack_error ("midiOutShortMsg error res %d", res); | |||||
} else { | |||||
} | |||||
} | |||||
} | |||||
} | |||||
return 0; | |||||
} | |||||
} // end of namespace | |||||
#ifdef __cplusplus | |||||
extern "C" | |||||
{ | |||||
#endif | |||||
SERVER_EXPORT jack_driver_desc_t * driver_get_descriptor() | |||||
{ | |||||
jack_driver_desc_t * desc; | |||||
unsigned int i; | |||||
desc = (jack_driver_desc_t*)calloc (1, sizeof (jack_driver_desc_t)); | |||||
strcpy(desc->name, "winmme"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1 | |||||
strcpy(desc->desc, "WinMME API based MIDI backend"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1 | |||||
desc->nparams = 0; | |||||
desc->params = (jack_driver_param_desc_t*)calloc (desc->nparams, sizeof (jack_driver_param_desc_t)); | |||||
return desc; | |||||
} | |||||
SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params) | |||||
{ | |||||
/* | |||||
unsigned int capture_ports = 2; | |||||
unsigned int playback_ports = 2; | |||||
unsigned long wait_time = 0; | |||||
const JSList * node; | |||||
const jack_driver_param_t * param; | |||||
bool monitor = false; | |||||
for (node = params; node; node = jack_slist_next (node)) { | |||||
param = (const jack_driver_param_t *) node->data; | |||||
switch (param->character) { | |||||
case 'C': | |||||
capture_ports = param->value.ui; | |||||
break; | |||||
case 'P': | |||||
playback_ports = param->value.ui; | |||||
break; | |||||
case 'r': | |||||
sample_rate = param->value.ui; | |||||
break; | |||||
case 'p': | |||||
period_size = param->value.ui; | |||||
break; | |||||
case 'w': | |||||
wait_time = param->value.ui; | |||||
break; | |||||
case 'm': | |||||
monitor = param->value.i; | |||||
break; | |||||
} | |||||
} | |||||
*/ | |||||
Jack::JackDriverClientInterface* driver = new Jack::JackWinMMEDriver("system_midi", "winmme", engine, table); | |||||
if (driver->Open(1, 1, 0, 0, false, "in", "out", 0, 0) == 0) { | |||||
return driver; | |||||
} else { | |||||
delete driver; | |||||
return NULL; | |||||
} | |||||
} | |||||
#ifdef __cplusplus | |||||
} | |||||
#endif | |||||
/* | |||||
jack_connect system:midi_capture_1 system_midi:playback_1 | |||||
jack_connect system:midi_capture_1 system_midi:playback_2 | |||||
jack_connect system:midi_capture_1 system_midi:playback_1 | |||||
jack_connect system:midi_capture_1 system_midi:playback_1 | |||||
jack_connect system:midi_capture_1 system_midi:playback_1 | |||||
jack_connect system_midi:capture_1 system:midi_playback_1 | |||||
jack_connect system_midi:capture_2 system:midi_playback_1 | |||||
jack_connect system_midi:capture_1 system_midi:playback_1 | |||||
*/ |
@@ -0,0 +1,87 @@ | |||||
/* | |||||
Copyright (C) 2009 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 __JackWinMMEDriver__ | |||||
#define __JackWinMMEDriver__ | |||||
#include "JackMidiDriver.h" | |||||
#include "JackTime.h" | |||||
namespace Jack | |||||
{ | |||||
/*! | |||||
\brief The WinMME driver. | |||||
*/ | |||||
#define kBuffSize 512 | |||||
struct MidiSlot { | |||||
LPVOID fHandle; // MMSystem handler | |||||
short fIndex; // MMSystem dev index | |||||
LPMIDIHDR fHeader; // for long msg output | |||||
MidiSlot():fHandle(0),fIndex(0) | |||||
{} | |||||
}; | |||||
class JackWinMMEDriver : public JackMidiDriver | |||||
{ | |||||
private: | |||||
int fRealCaptureChannels; | |||||
int fRealPlaybackChannels; | |||||
MidiSlot* fMidiSource; | |||||
MidiSlot* fMidiDestination; | |||||
void CloseInput(MidiSlot* slot); | |||||
void CloseOutput(MidiSlot* slot); | |||||
static void CALLBACK MidiInProc(HMIDIIN hMidiIn, UINT wMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2); | |||||
public: | |||||
JackWinMMEDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table); | |||||
virtual ~JackWinMMEDriver(); | |||||
int Open(bool capturing, | |||||
bool playing, | |||||
int chan_in, | |||||
int chan_out, | |||||
bool monitor, | |||||
const char* capture_driver_name, | |||||
const char* playback_driver_name, | |||||
jack_nframes_t capture_latency, | |||||
jack_nframes_t playback_latency); | |||||
int Close(); | |||||
int Attach(); | |||||
int Read(); | |||||
int Write(); | |||||
}; | |||||
} // end of namespace | |||||
#endif |