git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@4184 0c269be4-1314-0410-8aa9-9f06e86f4224tags/1.9.7
@@ -34,6 +34,10 @@ Valerio Pilo | |||||
Jackdmp changes log | Jackdmp changes log | ||||
--------------------------- | --------------------------- | ||||
2011-03-13 Stephane Letz <letz@grame.fr> | |||||
* Correct JackNetMaster::SetBufferSize. | |||||
2011-03-11 Stephane Letz <letz@grame.fr> | 2011-03-11 Stephane Letz <letz@grame.fr> | ||||
* Correct JackNetMaster::SetBufferSize. | * Correct JackNetMaster::SetBufferSize. | ||||
@@ -78,15 +78,15 @@ struct jackctl_server | |||||
/* int32_t, msecs; if zero, use period size. */ | /* int32_t, msecs; if zero, use period size. */ | ||||
union jackctl_parameter_value client_timeout; | union jackctl_parameter_value client_timeout; | ||||
union jackctl_parameter_value default_client_timeout; | union jackctl_parameter_value default_client_timeout; | ||||
/* uint32_t, clock source type */ | /* uint32_t, clock source type */ | ||||
union jackctl_parameter_value clock_source; | union jackctl_parameter_value clock_source; | ||||
union jackctl_parameter_value default_clock_source; | union jackctl_parameter_value default_clock_source; | ||||
/* uint32_t, max port number */ | /* uint32_t, max port number */ | ||||
union jackctl_parameter_value port_max; | union jackctl_parameter_value port_max; | ||||
union jackctl_parameter_value default_port_max; | union jackctl_parameter_value default_port_max; | ||||
/* bool */ | /* bool */ | ||||
union jackctl_parameter_value replace_registry; | union jackctl_parameter_value replace_registry; | ||||
union jackctl_parameter_value default_replace_registry; | union jackctl_parameter_value default_replace_registry; | ||||
@@ -366,7 +366,7 @@ jackctl_internals_load( | |||||
} | } | ||||
while (descriptor_node_ptr != NULL) | while (descriptor_node_ptr != NULL) | ||||
{ | |||||
{ | |||||
internal_ptr = (struct jackctl_internal *)malloc(sizeof(struct jackctl_internal)); | internal_ptr = (struct jackctl_internal *)malloc(sizeof(struct jackctl_internal)); | ||||
if (internal_ptr == NULL) | if (internal_ptr == NULL) | ||||
{ | { | ||||
@@ -745,7 +745,7 @@ EXPORT jackctl_server_t * jackctl_server_create( | |||||
{ | { | ||||
goto fail_free_parameters; | goto fail_free_parameters; | ||||
} | } | ||||
value.ui = PORT_NUM; | value.ui = PORT_NUM; | ||||
if (jackctl_add_parameter( | if (jackctl_add_parameter( | ||||
&server_ptr->parameters, | &server_ptr->parameters, | ||||
@@ -795,7 +795,7 @@ EXPORT jackctl_server_t * jackctl_server_create( | |||||
{ | { | ||||
goto fail_free_parameters; | goto fail_free_parameters; | ||||
} | } | ||||
/* Allowed to fail */ | /* Allowed to fail */ | ||||
jackctl_internals_load(server_ptr); | jackctl_internals_load(server_ptr); | ||||
@@ -882,7 +882,7 @@ jackctl_server_start( | |||||
if (!server_ptr->realtime.b && server_ptr->client_timeout.i == 0) | if (!server_ptr->realtime.b && server_ptr->client_timeout.i == 0) | ||||
server_ptr->client_timeout.i = 500; /* 0.5 sec; usable when non realtime. */ | server_ptr->client_timeout.i = 500; /* 0.5 sec; usable when non realtime. */ | ||||
/* check port max value before allocating server */ | /* check port max value before allocating server */ | ||||
if (server_ptr->port_max.ui > PORT_NUM_MAX) { | if (server_ptr->port_max.ui > PORT_NUM_MAX) { | ||||
jack_error("JACK server started with too much ports %d (when port max can be %d)", server_ptr->port_max.ui, PORT_NUM_MAX); | jack_error("JACK server started with too much ports %d (when port max can be %d)", server_ptr->port_max.ui, PORT_NUM_MAX); | ||||
@@ -896,7 +896,7 @@ jackctl_server_start( | |||||
server_ptr->client_timeout.i, | server_ptr->client_timeout.i, | ||||
server_ptr->realtime.b, | server_ptr->realtime.b, | ||||
server_ptr->realtime_priority.i, | server_ptr->realtime_priority.i, | ||||
server_ptr->port_max.ui, | |||||
server_ptr->port_max.ui, | |||||
server_ptr->verbose.b, | server_ptr->verbose.b, | ||||
(jack_timer_type_t)server_ptr->clock_source.ui, | (jack_timer_type_t)server_ptr->clock_source.ui, | ||||
server_ptr->name.str); | server_ptr->name.str); | ||||
@@ -1179,7 +1179,7 @@ EXPORT bool jackctl_server_load_internal( | |||||
{ | { | ||||
int status; | int status; | ||||
if (server_ptr->engine != NULL) { | if (server_ptr->engine != NULL) { | ||||
server_ptr->engine->InternalClientLoad(internal->desc_ptr->name, internal->desc_ptr->name, internal->set_parameters, JackNullOption, &internal->refnum, -1, &status); | |||||
server_ptr->engine->InternalClientLoad2(internal->desc_ptr->name, internal->desc_ptr->name, internal->set_parameters, JackNullOption, &internal->refnum, -1, &status); | |||||
return (internal->refnum > 0); | return (internal->refnum > 0); | ||||
} else { | } else { | ||||
return false; | return false; | ||||
@@ -1192,6 +1192,7 @@ EXPORT bool jackctl_server_unload_internal( | |||||
{ | { | ||||
int status; | int status; | ||||
if (server_ptr->engine != NULL && internal->refnum > 0) { | if (server_ptr->engine != NULL && internal->refnum > 0) { | ||||
// Client object is internally kept in JackEngine, and will be desallocated in InternalClientUnload | |||||
return ((server_ptr->engine->GetEngine()->InternalClientUnload(internal->refnum, &status)) == 0); | return ((server_ptr->engine->GetEngine()->InternalClientUnload(internal->refnum, &status)) == 0); | ||||
} else { | } else { | ||||
return false; | return false; | ||||
@@ -446,7 +446,7 @@ jack_get_descriptor (JSList * drivers, const char * sofile, const char * symbol) | |||||
free(filename); | free(filename); | ||||
return NULL; | return NULL; | ||||
} | } | ||||
if ((descriptor = so_get_descriptor ()) == NULL) { | if ((descriptor = so_get_descriptor ()) == NULL) { | ||||
jack_error("driver from '%s' returned NULL descriptor", filename); | jack_error("driver from '%s' returned NULL descriptor", filename); | ||||
UnloadDriverModule(dlhandle); | UnloadDriverModule(dlhandle); | ||||
@@ -467,7 +467,7 @@ jack_get_descriptor (JSList * drivers, const char * sofile, const char * symbol) | |||||
/* check it doesn't exist already */ | /* check it doesn't exist already */ | ||||
for (node = drivers; node; node = jack_slist_next (node)) { | for (node = drivers; node; node = jack_slist_next (node)) { | ||||
other_descriptor = (jack_driver_desc_t *) node->data; | other_descriptor = (jack_driver_desc_t *) node->data; | ||||
if (strcmp(descriptor->name, other_descriptor->name) == 0) { | if (strcmp(descriptor->name, other_descriptor->name) == 0) { | ||||
jack_error("the drivers in '%s' and '%s' both have the name '%s'; using the first", | jack_error("the drivers in '%s' and '%s' both have the name '%s'; using the first", | ||||
other_descriptor->file, filename, other_descriptor->name); | other_descriptor->file, filename, other_descriptor->name); | ||||
@@ -603,7 +603,7 @@ jack_drivers_load (JSList * drivers) { | |||||
} | } | ||||
while ((dir_entry = readdir(dir_stream))) { | while ((dir_entry = readdir(dir_stream))) { | ||||
/* check the filename is of the right format */ | /* check the filename is of the right format */ | ||||
if (strncmp ("jack_", dir_entry->d_name, 5) != 0) { | if (strncmp ("jack_", dir_entry->d_name, 5) != 0) { | ||||
continue; | continue; | ||||
@@ -619,7 +619,7 @@ jack_drivers_load (JSList * drivers) { | |||||
} | } | ||||
desc = jack_get_descriptor (drivers, dir_entry->d_name, "driver_get_descriptor"); | desc = jack_get_descriptor (drivers, dir_entry->d_name, "driver_get_descriptor"); | ||||
if (desc) { | if (desc) { | ||||
driver_list = jack_slist_append (driver_list, desc); | driver_list = jack_slist_append (driver_list, desc); | ||||
} else { | } else { | ||||
@@ -771,9 +771,9 @@ jack_internals_load (JSList * internals) { | |||||
#endif | #endif | ||||
Jack::JackDriverClientInterface* JackDriverInfo::Open(jack_driver_desc_t* driver_desc, | |||||
Jack::JackLockedEngine* engine, | |||||
Jack::JackSynchro* synchro, | |||||
Jack::JackDriverClientInterface* JackDriverInfo::Open(jack_driver_desc_t* driver_desc, | |||||
Jack::JackLockedEngine* engine, | |||||
Jack::JackSynchro* synchro, | |||||
const JSList* params) | const JSList* params) | ||||
{ | { | ||||
#ifdef WIN32 | #ifdef WIN32 | ||||
@@ -783,7 +783,7 @@ Jack::JackDriverClientInterface* JackDriverInfo::Open(jack_driver_desc_t* driver | |||||
#endif | #endif | ||||
fHandle = LoadDriverModule (driver_desc->file); | fHandle = LoadDriverModule (driver_desc->file); | ||||
if (fHandle == NULL) { | if (fHandle == NULL) { | ||||
#ifdef WIN32 | #ifdef WIN32 | ||||
if ((errstr = GetLastError ()) != 0) { | if ((errstr = GetLastError ()) != 0) { | ||||
@@ -809,8 +809,14 @@ 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; | ||||
} | } | ||||
fBackend = fInitialize(engine, synchro, params); | fBackend = fInitialize(engine, synchro, params); | ||||
return fBackend; | return fBackend; | ||||
} | } | ||||
JackDriverInfo::~JackDriverInfo() | |||||
{ | |||||
delete fBackend; | |||||
if (fHandle) | |||||
UnloadDriverModule(fHandle); | |||||
} |
@@ -24,14 +24,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
#include "driver_interface.h" | #include "driver_interface.h" | ||||
#include "JackControlAPI.h" | #include "JackControlAPI.h" | ||||
#include "JackPlatformPlug.h" | #include "JackPlatformPlug.h" | ||||
#include "JackDriver.h" | |||||
#include "JackSystemDeps.h" | #include "JackSystemDeps.h" | ||||
namespace Jack | |||||
{ | |||||
class JackDriverClientInterface; | |||||
class JackLockedEngine; | |||||
}; | |||||
typedef jack_driver_desc_t * (*JackDriverDescFunction) (); | typedef jack_driver_desc_t * (*JackDriverDescFunction) (); | ||||
typedef Jack::JackDriverClientInterface* (*driverInitialize) (Jack::JackLockedEngine*, Jack::JackSynchro*, const JSList*); | typedef Jack::JackDriverClientInterface* (*driverInitialize) (Jack::JackLockedEngine*, Jack::JackSynchro*, const JSList*); | ||||
@@ -39,34 +34,30 @@ class JackDriverInfo | |||||
{ | { | ||||
private: | private: | ||||
driverInitialize fInitialize; | driverInitialize fInitialize; | ||||
DRIVER_HANDLE fHandle; | DRIVER_HANDLE fHandle; | ||||
Jack::JackDriverClientInterface* fBackend; | Jack::JackDriverClientInterface* fBackend; | ||||
public: | public: | ||||
JackDriverInfo():fInitialize(NULL),fHandle(NULL) | |||||
JackDriverInfo():fInitialize(NULL),fHandle(NULL),fBackend(NULL) | |||||
{} | {} | ||||
~JackDriverInfo() | |||||
{ | |||||
if (fHandle) | |||||
UnloadDriverModule(fHandle); | |||||
} | |||||
~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() | Jack::JackDriverClientInterface* GetBackend() | ||||
{ | { | ||||
return fBackend; | return fBackend; | ||||
} | } | ||||
}; | }; | ||||
jack_driver_desc_t * jack_find_driver_descriptor (JSList * drivers, const char * name); | |||||
jack_driver_desc_t * jack_find_driver_descriptor(JSList * drivers, const char * name); | |||||
JSList * jack_drivers_load (JSList * drivers); | |||||
JSList * jack_internals_load (JSList * internals); | |||||
JSList * jack_drivers_load(JSList * drivers); | |||||
JSList * jack_internals_load(JSList * internals); | |||||
EXPORT int jackctl_parse_driver_params (jackctl_driver * driver_ptr, int argc, char* argv[]); | EXPORT int jackctl_parse_driver_params (jackctl_driver * driver_ptr, int argc, char* argv[]); | ||||
EXPORT void jack_free_driver_params(JSList * param_ptr); | EXPORT void jack_free_driver_params(JSList * param_ptr); | ||||
@@ -136,7 +136,7 @@ class JackInternalClientChannel : public detail::JackClientChannelInterface | |||||
void InternalClientLoad(int refnum, const char* client_name, const char* so_name, const char* objet_data, int options, int* status, int* int_ref, int uuid, int* result) | void InternalClientLoad(int refnum, const char* client_name, const char* so_name, const char* objet_data, int options, int* status, int* int_ref, int uuid, int* result) | ||||
{ | { | ||||
*result = fServer->InternalClientLoad(client_name, so_name, objet_data, options, int_ref, uuid, status); | |||||
*result = fServer->InternalClientLoad1(client_name, so_name, objet_data, options, int_ref, uuid, status); | |||||
} | } | ||||
void InternalClientUnload(int refnum, int int_ref, int* status, int* result) | void InternalClientUnload(int refnum, int int_ref, int* status, int* result) | ||||
@@ -61,7 +61,6 @@ JackServer::JackServer(bool sync, bool temporary, int timeout, bool rt, int prio | |||||
JackServer::~JackServer() | JackServer::~JackServer() | ||||
{ | { | ||||
JackGraphManager::Destroy(fGraphManager); | JackGraphManager::Destroy(fGraphManager); | ||||
delete fAudioDriver; | |||||
delete fDriverInfo; | delete fDriverInfo; | ||||
delete fFreewheelDriver; | delete fFreewheelDriver; | ||||
delete fEngine; | delete fEngine; | ||||
@@ -136,14 +135,14 @@ int JackServer::Close() | |||||
return 0; | return 0; | ||||
} | } | ||||
int JackServer::InternalClientLoad(const char* client_name, const char* so_name, const char* objet_data, int options, int* int_ref, int uuid, int* status) | |||||
int JackServer::InternalClientLoad1(const char* client_name, const char* so_name, const char* objet_data, int options, int* int_ref, int uuid, int* status) | |||||
{ | { | ||||
JackLoadableInternalClient* client = new JackLoadableInternalClient1(JackServerGlobals::fInstance, GetSynchroTable(), objet_data); | JackLoadableInternalClient* client = new JackLoadableInternalClient1(JackServerGlobals::fInstance, GetSynchroTable(), objet_data); | ||||
assert(client); | assert(client); | ||||
return InternalClientLoadAux(client, so_name, client_name, options, int_ref, uuid, status); | return InternalClientLoadAux(client, so_name, client_name, options, int_ref, uuid, status); | ||||
} | } | ||||
int JackServer::InternalClientLoad(const char* client_name, const char* so_name, const JSList * parameters, int options, int* int_ref, int uuid, int* status) | |||||
int JackServer::InternalClientLoad2(const char* client_name, const char* so_name, const JSList * parameters, int options, int* int_ref, int uuid, int* status) | |||||
{ | { | ||||
JackLoadableInternalClient* client = new JackLoadableInternalClient2(JackServerGlobals::fInstance, GetSynchroTable(), parameters); | JackLoadableInternalClient* client = new JackLoadableInternalClient2(JackServerGlobals::fInstance, GetSynchroTable(), parameters); | ||||
assert(client); | assert(client); | ||||
@@ -154,6 +153,8 @@ int JackServer::InternalClientLoadAux(JackLoadableInternalClient* client, const | |||||
{ | { | ||||
// Clear status | // Clear status | ||||
*status = 0; | *status = 0; | ||||
// Client object is internally kept in JackEngine | |||||
if ((client->Init(so_name) < 0) || (client->Open(JACK_DEFAULT_SERVER_NAME, client_name, uuid, (jack_options_t)options, (jack_status_t*)status) < 0)) { | if ((client->Init(so_name) < 0) || (client->Open(JACK_DEFAULT_SERVER_NAME, client_name, uuid, (jack_options_t)options, (jack_status_t*)status) < 0)) { | ||||
delete client; | delete client; | ||||
int my_status1 = *status | JackFailure; | int my_status1 = *status | JackFailure; | ||||
@@ -338,7 +339,6 @@ int JackServer::SwitchMaster(jack_driver_desc_t* driver_desc, JSList* driver_par | |||||
} | } | ||||
// Delete old master | // Delete old master | ||||
delete fAudioDriver; | |||||
delete fDriverInfo; | delete fDriverInfo; | ||||
// Activate master | // Activate master | ||||
@@ -57,7 +57,7 @@ class SERVER_EXPORT JackServer | |||||
JackConnectionManager fConnectionState; | JackConnectionManager fConnectionState; | ||||
JackSynchro fSynchroTable[CLIENT_NUM]; | JackSynchro fSynchroTable[CLIENT_NUM]; | ||||
bool fFreewheel; | bool fFreewheel; | ||||
int InternalClientLoadAux(JackLoadableInternalClient* client, const char* so_name, const char* client_name, int options, int* int_ref, int uuid, int* status); | int InternalClientLoadAux(JackLoadableInternalClient* client, const char* so_name, const char* client_name, int options, int* int_ref, int uuid, int* status); | ||||
public: | public: | ||||
@@ -77,19 +77,19 @@ class SERVER_EXPORT JackServer | |||||
// Command thread : API | // Command thread : API | ||||
int SetBufferSize(jack_nframes_t buffer_size); | int SetBufferSize(jack_nframes_t buffer_size); | ||||
int SetFreewheel(bool onoff); | int SetFreewheel(bool onoff); | ||||
int InternalClientLoad(const char* client_name, const char* so_name, const char* objet_data, int options, int* int_ref, int uuid, int* status); | |||||
int InternalClientLoad(const char* client_name, const char* so_name, const JSList * parameters, int options, int* int_ref, int uuid, int* status); | |||||
int InternalClientLoad1(const char* client_name, const char* so_name, const char* objet_data, int options, int* int_ref, int uuid, int* status); | |||||
int InternalClientLoad2(const char* client_name, const char* so_name, const JSList * parameters, int options, int* int_ref, int uuid, int* status); | |||||
void ClientKill(int refnum); | void ClientKill(int refnum); | ||||
// 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 | // Backend management | ||||
JackDriverInfo* AddSlave(jack_driver_desc_t* driver_desc, JSList* driver_params); | JackDriverInfo* AddSlave(jack_driver_desc_t* driver_desc, JSList* driver_params); | ||||
void RemoveSlave(JackDriverInfo* info); | void RemoveSlave(JackDriverInfo* info); | ||||
int SwitchMaster(jack_driver_desc_t* driver_desc, JSList* driver_params); | int SwitchMaster(jack_driver_desc_t* driver_desc, JSList* driver_params); | ||||
// Object access | // Object access | ||||
JackLockedEngine* GetEngine(); | JackLockedEngine* GetEngine(); | ||||
JackEngineControl* GetEngineControl(); | JackEngineControl* GetEngineControl(); | ||||
@@ -63,7 +63,7 @@ jack_client_t* jack_client_new_aux(const char* client_name, jack_options_t optio | |||||
} | } | ||||
jack_log("jack_client_new %s", client_name); | jack_log("jack_client_new %s", client_name); | ||||
if (status == NULL) /* no status from caller? */ | if (status == NULL) /* no status from caller? */ | ||||
status = &my_status; /* use local status word */ | status = &my_status; /* use local status word */ | ||||
*status = (jack_status_t)0; | *status = (jack_status_t)0; | ||||
@@ -77,13 +77,13 @@ jack_client_t* jack_client_new_aux(const char* client_name, jack_options_t optio | |||||
/* parse variable arguments */ | /* parse variable arguments */ | ||||
jack_varargs_init(&va); | jack_varargs_init(&va); | ||||
if (!JackServerGlobals::Init()) { // jack server initialisation | if (!JackServerGlobals::Init()) { // jack server initialisation | ||||
int my_status1 = (JackFailure | JackServerError); | int my_status1 = (JackFailure | JackServerError); | ||||
*status = (jack_status_t)my_status1; | *status = (jack_status_t)my_status1; | ||||
return NULL; | return NULL; | ||||
} | } | ||||
if (JACK_DEBUG) { | if (JACK_DEBUG) { | ||||
client = new JackDebugClient(new JackInternalClient(JackServerGlobals::fInstance, GetSynchroTable())); // Debug mode | client = new JackDebugClient(new JackInternalClient(JackServerGlobals::fInstance, GetSynchroTable())); // Debug mode | ||||
} else { | } else { | ||||
@@ -114,7 +114,7 @@ jack_client_t* jack_client_open_aux(const char* client_name, jack_options_t opti | |||||
} | } | ||||
jack_log("jack_client_open %s", client_name); | jack_log("jack_client_open %s", client_name); | ||||
if (status == NULL) /* no status from caller? */ | if (status == NULL) /* no status from caller? */ | ||||
status = &my_status; /* use local status word */ | status = &my_status; /* use local status word */ | ||||
*status = (jack_status_t)0; | *status = (jack_status_t)0; | ||||
@@ -128,13 +128,13 @@ jack_client_t* jack_client_open_aux(const char* client_name, jack_options_t opti | |||||
/* parse variable arguments */ | /* parse variable arguments */ | ||||
jack_varargs_parse(options, ap, &va); | jack_varargs_parse(options, ap, &va); | ||||
if (!JackServerGlobals::Init()) { // jack server initialisation | if (!JackServerGlobals::Init()) { // jack server initialisation | ||||
int my_status1 = (JackFailure | JackServerError); | int my_status1 = (JackFailure | JackServerError); | ||||
*status = (jack_status_t)my_status1; | *status = (jack_status_t)my_status1; | ||||
return NULL; | return NULL; | ||||
} | } | ||||
if (JACK_DEBUG) { | if (JACK_DEBUG) { | ||||
client = new JackDebugClient(new JackInternalClient(JackServerGlobals::fInstance, GetSynchroTable())); // Debug mode | client = new JackDebugClient(new JackInternalClient(JackServerGlobals::fInstance, GetSynchroTable())); // Debug mode | ||||
} else { | } else { | ||||
@@ -180,7 +180,7 @@ EXPORT int jack_client_close(jack_client_t* ext_client) | |||||
{ | { | ||||
#ifdef __CLIENTDEBUG__ | #ifdef __CLIENTDEBUG__ | ||||
JackGlobals::CheckContext("jack_client_close"); | JackGlobals::CheckContext("jack_client_close"); | ||||
#endif | |||||
#endif | |||||
assert(JackGlobals::fOpenMutex); | assert(JackGlobals::fOpenMutex); | ||||
JackGlobals::fOpenMutex->Lock(); | JackGlobals::fOpenMutex->Lock(); | ||||
int res = -1; | int res = -1; | ||||
@@ -200,7 +200,7 @@ EXPORT int jack_client_close(jack_client_t* ext_client) | |||||
EXPORT int jack_get_client_pid(const char *name) | EXPORT int jack_get_client_pid(const char *name) | ||||
{ | { | ||||
return (JackServerGlobals::fInstance != NULL) | |||||
return (JackServerGlobals::fInstance != NULL) | |||||
? JackServerGlobals::fInstance->GetEngine()->GetClientPID(name) | ? JackServerGlobals::fInstance->GetEngine()->GetClientPID(name) | ||||
: 0; | : 0; | ||||
} | } | ||||
@@ -18,6 +18,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
*/ | */ | ||||
#include "JackServerGlobals.h" | #include "JackServerGlobals.h" | ||||
#include "JackLockedEngine.h" | |||||
#include "JackTools.h" | #include "JackTools.h" | ||||
#include "shm.h" | #include "shm.h" | ||||
#include <getopt.h> | #include <getopt.h> | ||||
@@ -31,6 +32,8 @@ namespace Jack | |||||
JackServer* JackServerGlobals::fInstance; | JackServer* JackServerGlobals::fInstance; | ||||
unsigned int JackServerGlobals::fUserCount; | unsigned int JackServerGlobals::fUserCount; | ||||
int JackServerGlobals::fRTNotificationSocket; | int JackServerGlobals::fRTNotificationSocket; | ||||
std::map<std::string, JackDriverInfo*> JackServerGlobals::fSlavesList; | |||||
std::map<std::string, int> JackServerGlobals::fInternalsList; | |||||
bool (* JackServerGlobals::on_device_acquire)(const char * device_name) = NULL; | bool (* JackServerGlobals::on_device_acquire)(const char * device_name) = NULL; | ||||
void (* JackServerGlobals::on_device_release)(const char * device_name) = NULL; | void (* JackServerGlobals::on_device_release)(const char * device_name) = NULL; | ||||
@@ -63,6 +66,30 @@ void JackServerGlobals::Stop() | |||||
void JackServerGlobals::Delete() | void JackServerGlobals::Delete() | ||||
{ | { | ||||
jack_log("Jackdmp: delete server"); | jack_log("Jackdmp: delete server"); | ||||
// Slave drivers | |||||
std::map<std::string, JackDriverInfo*>::iterator it1; | |||||
for (it1 = fSlavesList.begin(); it1 != fSlavesList.end(); it1++) { | |||||
JackDriverInfo* info = (*it1).second; | |||||
if (info) { | |||||
fInstance->RemoveSlave((info)); | |||||
delete (info); | |||||
} | |||||
} | |||||
fSlavesList.clear(); | |||||
// Internal clients | |||||
std::map<std::string, int> ::iterator it2; | |||||
for (it2 = fInternalsList.begin(); it2 != fInternalsList.end(); it2++) { | |||||
int status; | |||||
int refnum = (*it2).second; | |||||
if (refnum > 0) { | |||||
// Client object is internally kept in JackEngine, and will be desallocated in InternalClientUnload | |||||
fInstance->GetEngine()->InternalClientUnload(refnum, &status); | |||||
} | |||||
} | |||||
fInternalsList.clear(); | |||||
delete fInstance; | delete fInstance; | ||||
fInstance = NULL; | fInstance = NULL; | ||||
} | } | ||||
@@ -80,49 +107,62 @@ bool JackServerGlobals::Init() | |||||
int opt = 0; | int opt = 0; | ||||
int option_index = 0; | int option_index = 0; | ||||
int seen_driver = 0; | |||||
char *driver_name = NULL; | |||||
char **driver_args = NULL; | |||||
JSList* driver_params = NULL; | |||||
char *master_driver_name = NULL; | |||||
char **master_driver_args = NULL; | |||||
JSList* master_driver_params = NULL; | |||||
jack_driver_desc_t* driver_desc; | |||||
jack_timer_type_t clock_source = JACK_TIMER_SYSTEM_CLOCK; | |||||
int driver_nargs = 1; | int driver_nargs = 1; | ||||
JSList* drivers = NULL; | JSList* drivers = NULL; | ||||
int show_version = 0; | |||||
int loopback = 0; | |||||
int sync = 0; | int sync = 0; | ||||
int rc, i; | int rc, i; | ||||
int ret; | int ret; | ||||
int replace_registry = 0; | |||||
FILE* fp = 0; | FILE* fp = 0; | ||||
char filename[255]; | char filename[255]; | ||||
char buffer[255]; | char buffer[255]; | ||||
int argc = 0; | int argc = 0; | ||||
char* argv[32]; | char* argv[32]; | ||||
jack_timer_type_t clock_source = JACK_TIMER_SYSTEM_CLOCK; | |||||
// First user starts the server | // First user starts the server | ||||
if (fUserCount++ == 0) { | if (fUserCount++ == 0) { | ||||
jack_log("JackServerGlobals Init"); | jack_log("JackServerGlobals Init"); | ||||
jack_driver_desc_t* driver_desc; | |||||
const char *options = "-ad:P:uvshVRL:STFl:t:mn:p:c:"; | |||||
static struct option long_options[] = { | |||||
{ "clock-source", 1, 0, 'c' }, | |||||
{ "driver", 1, 0, 'd' }, | |||||
{ "verbose", 0, 0, 'v' }, | |||||
{ "help", 0, 0, 'h' }, | |||||
{ "port-max", 1, 0, 'p' }, | |||||
{ "no-mlock", 0, 0, 'm' }, | |||||
{ "name", 0, 0, 'n' }, | |||||
{ "unlock", 0, 0, 'u' }, | |||||
{ "realtime", 0, 0, 'R' }, | |||||
{ "realtime-priority", 1, 0, 'P' }, | |||||
{ "timeout", 1, 0, 't' }, | |||||
{ "temporary", 0, 0, 'T' }, | |||||
{ "version", 0, 0, 'V' }, | |||||
{ "silent", 0, 0, 's' }, | |||||
{ "sync", 0, 0, 'S' }, | |||||
{ 0, 0, 0, 0 } | |||||
}; | |||||
const char *options = "-d:X:I:P:uvshVrRL:STFl:t:mn:p:" | |||||
#ifdef __linux__ | |||||
"c:" | |||||
#endif | |||||
; | |||||
struct option long_options[] = { | |||||
#ifdef __linux__ | |||||
{ "clock-source", 1, 0, 'c' }, | |||||
#endif | |||||
{ "loopback-driver", 1, 0, 'L' }, | |||||
{ "audio-driver", 1, 0, 'd' }, | |||||
{ "midi-driver", 1, 0, 'X' }, | |||||
{ "internal-client", 1, 0, 'I' }, | |||||
{ "verbose", 0, 0, 'v' }, | |||||
{ "help", 0, 0, 'h' }, | |||||
{ "port-max", 1, 0, 'p' }, | |||||
{ "no-mlock", 0, 0, 'm' }, | |||||
{ "name", 1, 0, 'n' }, | |||||
{ "unlock", 0, 0, 'u' }, | |||||
{ "realtime", 0, 0, 'R' }, | |||||
{ "no-realtime", 0, 0, 'r' }, | |||||
{ "replace-registry", 0, &replace_registry, 0 }, | |||||
{ "loopback", 0, 0, 'L' }, | |||||
{ "realtime-priority", 1, 0, 'P' }, | |||||
{ "timeout", 1, 0, 't' }, | |||||
{ "temporary", 0, 0, 'T' }, | |||||
{ "version", 0, 0, 'V' }, | |||||
{ "silent", 0, 0, 's' }, | |||||
{ "sync", 0, 0, 'S' }, | |||||
{ 0, 0, 0, 0 } | |||||
}; | |||||
snprintf(filename, 255, "%s/.jackdrc", getenv("HOME")); | snprintf(filename, 255, "%s/.jackdrc", getenv("HOME")); | ||||
fp = fopen(filename, "r"); | fp = fopen(filename, "r"); | ||||
@@ -156,7 +196,7 @@ bool JackServerGlobals::Init() | |||||
opterr = 0; | opterr = 0; | ||||
optind = 1; // Important : to reset argv parsing | optind = 1; // Important : to reset argv parsing | ||||
while (!seen_driver && | |||||
while (!master_driver_name && | |||||
(opt = getopt_long(argc, argv, options, long_options, &option_index)) != EOF) { | (opt = getopt_long(argc, argv, options, long_options, &option_index)) != EOF) { | ||||
switch (opt) { | switch (opt) { | ||||
@@ -174,34 +214,53 @@ bool JackServerGlobals::Init() | |||||
break; | break; | ||||
case 'd': | case 'd': | ||||
seen_driver = 1; | |||||
driver_name = optarg; | |||||
master_driver_name = optarg; | |||||
break; | break; | ||||
case 'v': | |||||
verbose_aux = 1; | |||||
case 'L': | |||||
loopback = atoi(optarg); | |||||
break; | break; | ||||
case 'S': | |||||
sync = 1; | |||||
case 'X': | |||||
fSlavesList[optarg] = NULL; | |||||
break; | break; | ||||
case 'n': | |||||
server_name = optarg; | |||||
case 'I': | |||||
fInternalsList[optarg] = -1; | |||||
break; | |||||
case 'p': | |||||
port_max = (unsigned int)atol(optarg); | |||||
break; | break; | ||||
case 'm': | case 'm': | ||||
do_mlock = 0; | do_mlock = 0; | ||||
break; | break; | ||||
case 'p': | |||||
port_max = (unsigned int)atol(optarg); | |||||
case 'u': | |||||
do_unlock = 1; | |||||
break; | |||||
case 'v': | |||||
verbose_aux = 1; | |||||
break; | |||||
case 'S': | |||||
sync = 1; | |||||
break; | |||||
case 'n': | |||||
server_name = optarg; | |||||
break; | break; | ||||
case 'P': | case 'P': | ||||
realtime_priority = atoi(optarg); | realtime_priority = atoi(optarg); | ||||
break; | break; | ||||
case 'r': | |||||
realtime = 0; | |||||
break; | |||||
case 'R': | case 'R': | ||||
realtime = 1; | realtime = 1; | ||||
break; | break; | ||||
@@ -214,14 +273,6 @@ bool JackServerGlobals::Init() | |||||
client_timeout = atoi(optarg); | client_timeout = atoi(optarg); | ||||
break; | break; | ||||
case 'u': | |||||
do_unlock = 1; | |||||
break; | |||||
case 'V': | |||||
show_version = 1; | |||||
break; | |||||
default: | default: | ||||
jack_error("unknown option character %c", optopt); | jack_error("unknown option character %c", optopt); | ||||
break; | break; | ||||
@@ -234,9 +285,9 @@ bool JackServerGlobals::Init() | |||||
goto error; | goto error; | ||||
} | } | ||||
driver_desc = jack_find_driver_descriptor(drivers, driver_name); | |||||
driver_desc = jack_find_driver_descriptor(drivers, master_driver_name); | |||||
if (!driver_desc) { | if (!driver_desc) { | ||||
jack_error("jackdmp: unknown driver '%s'", driver_name); | |||||
jack_error("jackdmp: unknown master driver '%s'", master_driver_name); | |||||
goto error; | goto error; | ||||
} | } | ||||
@@ -252,14 +303,14 @@ bool JackServerGlobals::Init() | |||||
goto error; | goto error; | ||||
} | } | ||||
driver_args = (char**)malloc(sizeof(char*) * driver_nargs); | |||||
driver_args[0] = driver_name; | |||||
master_driver_args = (char**)malloc(sizeof(char*) * driver_nargs); | |||||
master_driver_args[0] = master_driver_name; | |||||
for (i = 1; i < driver_nargs; i++) { | for (i = 1; i < driver_nargs; i++) { | ||||
driver_args[i] = argv[optind++]; | |||||
master_driver_args[i] = argv[optind++]; | |||||
} | } | ||||
if (jack_parse_driver_params(driver_desc, driver_nargs, driver_args, &driver_params)) { | |||||
if (jack_parse_driver_params(driver_desc, driver_nargs, master_driver_args, &master_driver_params)) { | |||||
goto error; | goto error; | ||||
} | } | ||||
@@ -294,7 +345,7 @@ bool JackServerGlobals::Init() | |||||
free(argv[i]); | free(argv[i]); | ||||
} | } | ||||
int res = Start(server_name, driver_desc, driver_params, sync, temporary, client_timeout, realtime, realtime_priority, port_max, verbose_aux, clock_source); | |||||
int res = Start(server_name, driver_desc, master_driver_params, sync, temporary, client_timeout, realtime, realtime_priority, port_max, verbose_aux, clock_source); | |||||
if (res < 0) { | if (res < 0) { | ||||
jack_error("Cannot start server... exit"); | jack_error("Cannot start server... exit"); | ||||
Delete(); | Delete(); | ||||
@@ -303,21 +354,57 @@ bool JackServerGlobals::Init() | |||||
jack_unregister_server(server_name); | jack_unregister_server(server_name); | ||||
goto error; | goto error; | ||||
} | } | ||||
// Slave drivers | |||||
std::map<std::string, JackDriverInfo*>::iterator it1; | |||||
for (it1 = fSlavesList.begin(); it1 != fSlavesList.end(); it1++) { | |||||
const char* name = ((*it1).first).c_str(); | |||||
driver_desc = jack_find_driver_descriptor(drivers, name); | |||||
if (!driver_desc) { | |||||
jack_error("jackdmp: unknown slave driver '%s'", name); | |||||
} else { | |||||
JackDriverInfo* info = fInstance->AddSlave(driver_desc, NULL); | |||||
(*it1).second = info; | |||||
} | |||||
} | |||||
// Loopback driver | |||||
if (loopback > 0) { | |||||
driver_desc = jack_find_driver_descriptor(drivers, "loopback"); | |||||
if (!driver_desc) { | |||||
jack_error("jackdmp: unknown driver '%s'", "loopback"); | |||||
} else { | |||||
fInstance->AddSlave(driver_desc, NULL); | |||||
} | |||||
} | |||||
// Internal clients | |||||
std::map<std::string, int>::iterator it2; | |||||
for (it2 = fInternalsList.begin(); it2 != fInternalsList.end(); it2++) { | |||||
int status, refnum; | |||||
const char* name = ((*it2).first).c_str(); | |||||
fInstance->InternalClientLoad2(name, name, NULL, JackNullOption, &refnum, -1, &status); | |||||
(*it2).second = refnum; | |||||
} | |||||
} | } | ||||
if (driver_params) | |||||
jack_free_driver_params(driver_params); | |||||
if (master_driver_params) | |||||
jack_free_driver_params(master_driver_params); | |||||
return true; | return true; | ||||
error: | error: | ||||
if (driver_params) | |||||
jack_free_driver_params(driver_params); | |||||
fUserCount--; | |||||
jack_log("JackServerGlobals Init error"); | |||||
if (master_driver_params) | |||||
jack_free_driver_params(master_driver_params); | |||||
//fUserCount--; | |||||
Destroy(); | |||||
return false; | return false; | ||||
} | } | ||||
void JackServerGlobals::Destroy() | void JackServerGlobals::Destroy() | ||||
{ | { | ||||
printf("JackServerGlobals Destroy %d\n", fUserCount); | |||||
if (--fUserCount == 0) { | if (--fUserCount == 0) { | ||||
jack_log("JackServerGlobals Destroy"); | jack_log("JackServerGlobals Destroy"); | ||||
Stop(); | Stop(); | ||||
@@ -24,6 +24,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
#include "JackDriverLoader.h" | #include "JackDriverLoader.h" | ||||
#include "JackCompilerDeps.h" | #include "JackCompilerDeps.h" | ||||
#include "JackServer.h" | #include "JackServer.h" | ||||
#include <map> | |||||
namespace Jack | namespace Jack | ||||
{ | { | ||||
@@ -39,6 +40,9 @@ struct SERVER_EXPORT JackServerGlobals | |||||
static JackServer* fInstance; | static JackServer* fInstance; | ||||
static unsigned int fUserCount; | static unsigned int fUserCount; | ||||
static int fRTNotificationSocket; // For debugging purpose | static int fRTNotificationSocket; // For debugging purpose | ||||
static std::map<std::string, JackDriverInfo*> fSlavesList; | |||||
static std::map<std::string, int> fInternalsList; | |||||
static bool (* on_device_acquire)(const char* device_name); | static bool (* on_device_acquire)(const char* device_name); | ||||
static void (* on_device_release)(const char* device_name); | static void (* on_device_release)(const char* device_name); | ||||
@@ -229,8 +229,8 @@ int main(int argc, char* argv[]) | |||||
int i,opt = 0; | int i,opt = 0; | ||||
int option_index = 0; | int option_index = 0; | ||||
char *master_driver_name = NULL; | |||||
char **master_driver_args = NULL; | |||||
char* master_driver_name = NULL; | |||||
char** master_driver_args = NULL; | |||||
int master_driver_nargs = 1; | int master_driver_nargs = 1; | ||||
int do_mlock = 1; | int do_mlock = 1; | ||||
int do_unlock = 0; | int do_unlock = 0; | ||||
@@ -426,7 +426,7 @@ int main(int argc, char* argv[]) | |||||
goto fail_free1; | goto fail_free1; | ||||
} | } | ||||
// Audio driver | |||||
// Master driver | |||||
master_driver_ctl = jackctl_server_get_driver(server_ctl, master_driver_name); | master_driver_ctl = jackctl_server_get_driver(server_ctl, master_driver_name); | ||||
if (master_driver_ctl == NULL) { | if (master_driver_ctl == NULL) { | ||||
fprintf(stderr, "Unknown driver \"%s\"\n", master_driver_name); | fprintf(stderr, "Unknown driver \"%s\"\n", master_driver_name); | ||||
@@ -464,7 +464,7 @@ int main(int argc, char* argv[]) | |||||
goto fail_free1; | goto fail_free1; | ||||
} | } | ||||
// Slave driver | |||||
// Slave drivers | |||||
for (it = slaves_list.begin(); it != slaves_list.end(); it++) { | for (it = slaves_list.begin(); it != slaves_list.end(); it++) { | ||||
jackctl_driver_t * slave_driver_ctl = jackctl_server_get_driver(server_ctl, *it); | jackctl_driver_t * slave_driver_ctl = jackctl_server_get_driver(server_ctl, *it); | ||||
if (slave_driver_ctl == NULL) { | if (slave_driver_ctl == NULL) { | ||||
@@ -488,7 +488,7 @@ int main(int argc, char* argv[]) | |||||
} | } | ||||
} | } | ||||
// Load internal clients | |||||
// Internal clients | |||||
for (it = internals_list.begin(); it != internals_list.end(); it++) { | for (it = internals_list.begin(); it != internals_list.end(); it++) { | ||||
jackctl_internal_t * internal_driver_ctl = jackctl_server_get_internal(server_ctl, *it); | jackctl_internal_t * internal_driver_ctl = jackctl_server_get_internal(server_ctl, *it); | ||||
if (internal_driver_ctl == NULL) { | if (internal_driver_ctl == NULL) { | ||||
@@ -2291,7 +2291,9 @@ int JackAlsaDriver::Open(jack_nframes_t nframes, | |||||
int JackAlsaDriver::Close() | int JackAlsaDriver::Close() | ||||
{ | { | ||||
JackAudioDriver::Close(); | |||||
// Generic audio driver close | |||||
int res = JackAudioDriver::Close(); | |||||
alsa_driver_delete((alsa_driver_t*)fDriver); | alsa_driver_delete((alsa_driver_t*)fDriver); | ||||
if (JackServerGlobals::on_device_release != NULL) | if (JackServerGlobals::on_device_release != NULL) | ||||
@@ -2310,7 +2312,7 @@ int JackAlsaDriver::Close() | |||||
} | } | ||||
} | } | ||||
return 0; | |||||
return res; | |||||
} | } | ||||
int JackAlsaDriver::Start() | int JackAlsaDriver::Start() | ||||
@@ -644,9 +644,11 @@ int JackFFADODriver::Open(ffado_jack_settings_t *params) | |||||
int JackFFADODriver::Close() | int JackFFADODriver::Close() | ||||
{ | { | ||||
JackAudioDriver::Close(); | |||||
// Generic audio driver close | |||||
int res = JackAudioDriver::Close(); | |||||
ffado_driver_delete((ffado_driver_t*)fDriver); | ffado_driver_delete((ffado_driver_t*)fDriver); | ||||
return 0; | |||||
return res; | |||||
} | } | ||||
int JackFFADODriver::Start() | int JackFFADODriver::Start() | ||||
@@ -832,9 +832,11 @@ int JackFreebobDriver::Open(freebob_jack_settings_t *params) | |||||
int JackFreebobDriver::Close() | int JackFreebobDriver::Close() | ||||
{ | { | ||||
JackAudioDriver::Close(); | |||||
// Generic audio driver close | |||||
int res = JackAudioDriver::Close(); | |||||
freebob_driver_delete((freebob_driver_t*)fDriver); | freebob_driver_delete((freebob_driver_t*)fDriver); | ||||
return 0; | |||||
return res; | |||||
} | } | ||||
int JackFreebobDriver::Start() | int JackFreebobDriver::Start() | ||||
@@ -1551,12 +1551,15 @@ int JackCoreAudioDriver::Close() | |||||
{ | { | ||||
jack_log("JackCoreAudioDriver::Close"); | jack_log("JackCoreAudioDriver::Close"); | ||||
Stop(); | Stop(); | ||||
JackAudioDriver::Close(); | |||||
// Generic audio driver close | |||||
int res = JackAudioDriver::Close(); | |||||
RemoveListeners(); | RemoveListeners(); | ||||
DisposeBuffers(); | DisposeBuffers(); | ||||
CloseAUHAL(); | CloseAUHAL(); | ||||
DestroyAggregateDevice(); | DestroyAggregateDevice(); | ||||
return 0; | |||||
return res; | |||||
} | } | ||||
int JackCoreAudioDriver::Attach() | int JackCoreAudioDriver::Attach() | ||||
@@ -45,15 +45,15 @@ void JackCoreMidiDriver::ReadProcAux(const MIDIPacketList *pktlist, jack_ringbuf | |||||
jack_error("ReadProc : ring buffer is full, skip events..."); | jack_error("ReadProc : ring buffer is full, skip events..."); | ||||
return; | return; | ||||
} | } | ||||
jack_ringbuffer_write(ringbuffer, (char*)&pktlist->numPackets, sizeof(UInt32)); | jack_ringbuffer_write(ringbuffer, (char*)&pktlist->numPackets, sizeof(UInt32)); | ||||
for (unsigned int i = 0; i < pktlist->numPackets; ++i) { | for (unsigned int i = 0; i < pktlist->numPackets; ++i) { | ||||
MIDIPacket *packet = (MIDIPacket *)pktlist->packet; | MIDIPacket *packet = (MIDIPacket *)pktlist->packet; | ||||
// TODO : use timestamp | // TODO : use timestamp | ||||
// Check available size first.. | // Check available size first.. | ||||
size = jack_ringbuffer_write_space(ringbuffer); | size = jack_ringbuffer_write_space(ringbuffer); | ||||
if (size < (sizeof(UInt16) + packet->length)) { | if (size < (sizeof(UInt16) + packet->length)) { | ||||
@@ -64,7 +64,7 @@ void JackCoreMidiDriver::ReadProcAux(const MIDIPacketList *pktlist, jack_ringbuf | |||||
jack_ringbuffer_write(ringbuffer, (char*)&packet->length, sizeof(UInt16)); | jack_ringbuffer_write(ringbuffer, (char*)&packet->length, sizeof(UInt16)); | ||||
// Write event actual data | // Write event actual data | ||||
jack_ringbuffer_write(ringbuffer, (char*)packet->data, packet->length); | jack_ringbuffer_write(ringbuffer, (char*)packet->data, packet->length); | ||||
packet = MIDIPacketNext(packet); | packet = MIDIPacketNext(packet); | ||||
} | } | ||||
} | } | ||||
@@ -83,7 +83,7 @@ void JackCoreMidiDriver::ReadVirtualProc(const MIDIPacketList *pktlist, void *re | |||||
void JackCoreMidiDriver::NotifyProc(const MIDINotification *message, void *refCon) | void JackCoreMidiDriver::NotifyProc(const MIDINotification *message, void *refCon) | ||||
{ | { | ||||
jack_info("NotifyProc %d", message->messageID); | |||||
jack_log("NotifyProc %d", message->messageID); | |||||
} | } | ||||
JackCoreMidiDriver::JackCoreMidiDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table) | JackCoreMidiDriver::JackCoreMidiDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table) | ||||
@@ -106,15 +106,15 @@ int JackCoreMidiDriver::Open(bool capturing, | |||||
OSStatus err; | OSStatus err; | ||||
CFStringRef coutputStr; | CFStringRef coutputStr; | ||||
std::string str; | std::string str; | ||||
// Get real input/output number | // Get real input/output number | ||||
fRealCaptureChannels = MIDIGetNumberOfSources(); | fRealCaptureChannels = MIDIGetNumberOfSources(); | ||||
fRealPlaybackChannels = MIDIGetNumberOfDestinations(); | fRealPlaybackChannels = MIDIGetNumberOfDestinations(); | ||||
// Generic JackMidiDriver Open | // Generic JackMidiDriver Open | ||||
if (JackMidiDriver::Open(capturing, playing, inchannels + fRealCaptureChannels, outchannels + fRealPlaybackChannels, monitor, capture_driver_name, playback_driver_name, capture_latency, playback_latency) != 0) | if (JackMidiDriver::Open(capturing, playing, inchannels + fRealCaptureChannels, outchannels + fRealPlaybackChannels, monitor, capture_driver_name, playback_driver_name, capture_latency, playback_latency) != 0) | ||||
return -1; | return -1; | ||||
coutputStr = CFStringCreateWithCString(0, "JackMidi", CFStringGetSystemEncoding()); | coutputStr = CFStringCreateWithCString(0, "JackMidi", CFStringGetSystemEncoding()); | ||||
err = MIDIClientCreate(coutputStr, NotifyProc, this, &fMidiClient); | err = MIDIClientCreate(coutputStr, NotifyProc, this, &fMidiClient); | ||||
CFRelease(coutputStr); | CFRelease(coutputStr); | ||||
@@ -122,7 +122,7 @@ int JackCoreMidiDriver::Open(bool capturing, | |||||
jack_error("Cannot create CoreMidi client"); | jack_error("Cannot create CoreMidi client"); | ||||
goto error; | goto error; | ||||
} | } | ||||
err = MIDIInputPortCreate(fMidiClient, CFSTR("Input port"), ReadProc, this, &fInputPort); | err = MIDIInputPortCreate(fMidiClient, CFSTR("Input port"), ReadProc, this, &fInputPort); | ||||
if (!fInputPort) { | if (!fInputPort) { | ||||
jack_error("Cannot open CoreMidi in port\n"); | jack_error("Cannot open CoreMidi in port\n"); | ||||
@@ -134,10 +134,10 @@ int JackCoreMidiDriver::Open(bool capturing, | |||||
jack_error("Cannot open CoreMidi out port\n"); | jack_error("Cannot open CoreMidi out port\n"); | ||||
goto error; | goto error; | ||||
} | } | ||||
fMidiDestination = new MIDIEndpointRef[inchannels + fRealCaptureChannels]; | fMidiDestination = new MIDIEndpointRef[inchannels + fRealCaptureChannels]; | ||||
assert(fMidiDestination); | assert(fMidiDestination); | ||||
// Virtual input | // Virtual input | ||||
for (int i = 0; i < inchannels; i++) { | for (int i = 0; i < inchannels; i++) { | ||||
std::stringstream num; | std::stringstream num; | ||||
@@ -151,13 +151,13 @@ int JackCoreMidiDriver::Open(bool capturing, | |||||
goto error; | goto error; | ||||
} | } | ||||
} | } | ||||
// Real input | // Real input | ||||
for (int i = 0; i < fRealCaptureChannels; i++) { | for (int i = 0; i < fRealCaptureChannels; i++) { | ||||
fMidiDestination[i + inchannels] = MIDIGetSource(i); | fMidiDestination[i + inchannels] = MIDIGetSource(i); | ||||
MIDIPortConnectSource(fInputPort, fMidiDestination[i + inchannels], fRingBuffer[i + inchannels]); | MIDIPortConnectSource(fInputPort, fMidiDestination[i + inchannels], fRingBuffer[i + inchannels]); | ||||
} | } | ||||
fMidiSource = new MIDIEndpointRef[outchannels + fRealPlaybackChannels]; | fMidiSource = new MIDIEndpointRef[outchannels + fRealPlaybackChannels]; | ||||
assert(fMidiSource); | assert(fMidiSource); | ||||
@@ -172,47 +172,50 @@ int JackCoreMidiDriver::Open(bool capturing, | |||||
if (!fMidiSource[i]) { | if (!fMidiSource[i]) { | ||||
jack_error("Cannot create CoreMidi source"); | jack_error("Cannot create CoreMidi source"); | ||||
goto error; | goto error; | ||||
} | |||||
} | |||||
} | } | ||||
// Real output | // Real output | ||||
for (int i = 0; i < fRealPlaybackChannels; i++) { | for (int i = 0; i < fRealPlaybackChannels; i++) { | ||||
fMidiSource[i + outchannels] = MIDIGetDestination(i); | fMidiSource[i + outchannels] = MIDIGetDestination(i); | ||||
} | } | ||||
return 0; | return 0; | ||||
error: | error: | ||||
Close(); | Close(); | ||||
return -1; | return -1; | ||||
} | } | ||||
int JackCoreMidiDriver::Close() | int JackCoreMidiDriver::Close() | ||||
{ | { | ||||
// Generic midi driver close | |||||
int res = JackMidiDriver::Close(); | |||||
if (fInputPort) | if (fInputPort) | ||||
MIDIPortDispose(fInputPort); | MIDIPortDispose(fInputPort); | ||||
if (fOutputPort) | |||||
if (fOutputPort) | |||||
MIDIPortDispose(fOutputPort); | MIDIPortDispose(fOutputPort); | ||||
// Only dispose "virtual" endpoints | // Only dispose "virtual" endpoints | ||||
for (int i = 0; i < fCaptureChannels - fRealCaptureChannels; i++) { | for (int i = 0; i < fCaptureChannels - fRealCaptureChannels; i++) { | ||||
if (fMidiDestination) | |||||
if (fMidiDestination) | |||||
MIDIEndpointDispose(fMidiDestination[i]); | MIDIEndpointDispose(fMidiDestination[i]); | ||||
} | } | ||||
delete[] fMidiDestination; | delete[] fMidiDestination; | ||||
// Only dispose "virtual" endpoints | // Only dispose "virtual" endpoints | ||||
for (int i = 0; i < fPlaybackChannels - fRealPlaybackChannels; i++) { | for (int i = 0; i < fPlaybackChannels - fRealPlaybackChannels; i++) { | ||||
if (fMidiSource[i]) | |||||
if (fMidiSource[i]) | |||||
MIDIEndpointDispose(fMidiSource[i]); | MIDIEndpointDispose(fMidiSource[i]); | ||||
} | } | ||||
delete[] fMidiSource; | delete[] fMidiSource; | ||||
if (fMidiClient) | |||||
if (fMidiClient) | |||||
MIDIClientDispose(fMidiClient); | MIDIClientDispose(fMidiClient); | ||||
return 0; | |||||
return res; | |||||
} | } | ||||
int JackCoreMidiDriver::Attach() | int JackCoreMidiDriver::Attach() | ||||
@@ -229,7 +232,7 @@ int JackCoreMidiDriver::Attach() | |||||
jack_log("JackCoreMidiDriver::Attach fBufferSize = %ld fSampleRate = %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate); | jack_log("JackCoreMidiDriver::Attach fBufferSize = %ld fSampleRate = %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate); | ||||
for (i = 0; i < fCaptureChannels; i++) { | for (i = 0; i < fCaptureChannels; i++) { | ||||
err = MIDIObjectGetStringProperty(fMidiDestination[i], kMIDIPropertyName, &pname); | err = MIDIObjectGetStringProperty(fMidiDestination[i], kMIDIPropertyName, &pname); | ||||
if (err == noErr) { | if (err == noErr) { | ||||
CFStringGetCString(pname, endpoint_name, sizeof(endpoint_name), 0); | CFStringGetCString(pname, endpoint_name, sizeof(endpoint_name), 0); | ||||
@@ -238,7 +241,7 @@ int JackCoreMidiDriver::Attach() | |||||
} else { | } else { | ||||
snprintf(alias, sizeof(alias) - 1, "%s:%s:out%d", fAliasName, fCaptureDriverName, i + 1); | 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); | snprintf(name, sizeof(name) - 1, "%s:capture_%d", fClientControl.fName, i + 1); | ||||
if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE, CaptureDriverFlags, fEngineControl->fBufferSize)) == NO_PORT) { | if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE, CaptureDriverFlags, fEngineControl->fBufferSize)) == NO_PORT) { | ||||
jack_error("driver: cannot register port for %s", name); | jack_error("driver: cannot register port for %s", name); | ||||
@@ -251,7 +254,7 @@ int JackCoreMidiDriver::Attach() | |||||
} | } | ||||
for (i = 0; i < fPlaybackChannels; i++) { | for (i = 0; i < fPlaybackChannels; i++) { | ||||
err = MIDIObjectGetStringProperty(fMidiSource[i], kMIDIPropertyName, &pname); | err = MIDIObjectGetStringProperty(fMidiSource[i], kMIDIPropertyName, &pname); | ||||
if (err == noErr) { | if (err == noErr) { | ||||
CFStringGetCString(pname, endpoint_name, sizeof(endpoint_name), 0); | CFStringGetCString(pname, endpoint_name, sizeof(endpoint_name), 0); | ||||
@@ -260,7 +263,7 @@ int JackCoreMidiDriver::Attach() | |||||
} else { | } else { | ||||
snprintf(alias, sizeof(alias) - 1, "%s:%s:in%d", fAliasName, fPlaybackDriverName, i + 1); | 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); | snprintf(name, sizeof(name) - 1, "%s:playback_%d", fClientControl.fName, i + 1); | ||||
if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE, PlaybackDriverFlags, fEngineControl->fBufferSize)) == NO_PORT) { | if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE, PlaybackDriverFlags, fEngineControl->fBufferSize)) == NO_PORT) { | ||||
jack_error("driver: cannot register port for %s", name); | jack_error("driver: cannot register port for %s", name); | ||||
@@ -277,23 +280,23 @@ int JackCoreMidiDriver::Attach() | |||||
int JackCoreMidiDriver::Read() | int JackCoreMidiDriver::Read() | ||||
{ | { | ||||
for (int chan = 0; chan < fCaptureChannels; chan++) { | for (int chan = 0; chan < fCaptureChannels; chan++) { | ||||
if (fGraphManager->GetConnectionsNum(fCapturePortList[chan]) > 0) { | if (fGraphManager->GetConnectionsNum(fCapturePortList[chan]) > 0) { | ||||
// Get JACK port | // Get JACK port | ||||
JackMidiBuffer* midi_buffer = GetInputBuffer(chan); | JackMidiBuffer* midi_buffer = GetInputBuffer(chan); | ||||
if (jack_ringbuffer_read_space(fRingBuffer[chan]) == 0) { | if (jack_ringbuffer_read_space(fRingBuffer[chan]) == 0) { | ||||
// Reset buffer | // Reset buffer | ||||
midi_buffer->Reset(midi_buffer->nframes); | midi_buffer->Reset(midi_buffer->nframes); | ||||
} else { | } else { | ||||
while (jack_ringbuffer_read_space(fRingBuffer[chan]) > 0) { | while (jack_ringbuffer_read_space(fRingBuffer[chan]) > 0) { | ||||
// Read event number | // Read event number | ||||
int ev_count = 0; | int ev_count = 0; | ||||
jack_ringbuffer_read(fRingBuffer[chan], (char*)&ev_count, sizeof(int)); | jack_ringbuffer_read(fRingBuffer[chan], (char*)&ev_count, sizeof(int)); | ||||
for (int j = 0; j < ev_count; j++) { | for (int j = 0; j < ev_count; j++) { | ||||
// Read event length | // Read event length | ||||
UInt16 event_len; | UInt16 event_len; | ||||
@@ -304,7 +307,7 @@ int JackCoreMidiDriver::Read() | |||||
} | } | ||||
} | } | ||||
} | } | ||||
} else { | } else { | ||||
// Consume ring buffer | // Consume ring buffer | ||||
jack_ringbuffer_read_advance(fRingBuffer[chan], jack_ringbuffer_read_space(fRingBuffer[chan])); | jack_ringbuffer_read_advance(fRingBuffer[chan], jack_ringbuffer_read_space(fRingBuffer[chan])); | ||||
@@ -316,35 +319,35 @@ int JackCoreMidiDriver::Read() | |||||
int JackCoreMidiDriver::Write() | int JackCoreMidiDriver::Write() | ||||
{ | { | ||||
MIDIPacketList* pktlist = (MIDIPacketList*)fMIDIBuffer; | MIDIPacketList* pktlist = (MIDIPacketList*)fMIDIBuffer; | ||||
for (int chan = 0; chan < fPlaybackChannels; chan++) { | for (int chan = 0; chan < fPlaybackChannels; chan++) { | ||||
if (fGraphManager->GetConnectionsNum(fPlaybackPortList[chan]) > 0) { | if (fGraphManager->GetConnectionsNum(fPlaybackPortList[chan]) > 0) { | ||||
MIDIPacket* packet = MIDIPacketListInit(pktlist); | MIDIPacket* packet = MIDIPacketListInit(pktlist); | ||||
JackMidiBuffer* midi_buffer = GetOutputBuffer(chan); | JackMidiBuffer* midi_buffer = GetOutputBuffer(chan); | ||||
// TODO : use timestamp | // TODO : use timestamp | ||||
for (unsigned int j = 0; j < midi_buffer->event_count; j++) { | for (unsigned int j = 0; j < midi_buffer->event_count; j++) { | ||||
JackMidiEvent* ev = &midi_buffer->events[j]; | JackMidiEvent* ev = &midi_buffer->events[j]; | ||||
packet = MIDIPacketListAdd(pktlist, sizeof(fMIDIBuffer), packet, MIDIGetCurrentHostTime(), ev->size, ev->GetData(midi_buffer)); | packet = MIDIPacketListAdd(pktlist, sizeof(fMIDIBuffer), packet, MIDIGetCurrentHostTime(), ev->size, ev->GetData(midi_buffer)); | ||||
} | } | ||||
if (packet) { | if (packet) { | ||||
if (chan < fPlaybackChannels - fRealPlaybackChannels) { | if (chan < fPlaybackChannels - fRealPlaybackChannels) { | ||||
OSStatus err = MIDIReceived(fMidiSource[chan], pktlist); | OSStatus err = MIDIReceived(fMidiSource[chan], pktlist); | ||||
if (err != noErr) | |||||
if (err != noErr) | |||||
jack_error("MIDIReceived error"); | jack_error("MIDIReceived error"); | ||||
} else { | } else { | ||||
OSStatus err = MIDISend(fOutputPort, fMidiSource[chan], pktlist); | OSStatus err = MIDISend(fOutputPort, fMidiSource[chan], pktlist); | ||||
if (err != noErr) | |||||
if (err != noErr) | |||||
jack_error("MIDISend error"); | jack_error("MIDISend error"); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
return 0; | return 0; | ||||
} | } | ||||
@@ -355,7 +358,7 @@ extern "C" | |||||
{ | { | ||||
#endif | #endif | ||||
SERVER_EXPORT jack_driver_desc_t * driver_get_descriptor() | |||||
SERVER_EXPORT jack_driver_desc_t * driver_get_descriptor() | |||||
{ | { | ||||
jack_driver_desc_t * desc; | jack_driver_desc_t * desc; | ||||
unsigned int i; | unsigned int i; | ||||
@@ -366,7 +369,7 @@ extern "C" | |||||
desc->nparams = 2; | desc->nparams = 2; | ||||
desc->params = (jack_driver_param_desc_t*)calloc (desc->nparams, sizeof (jack_driver_param_desc_t)); | desc->params = (jack_driver_param_desc_t*)calloc (desc->nparams, sizeof (jack_driver_param_desc_t)); | ||||
i = 0; | i = 0; | ||||
strcpy(desc->params[i].name, "inchannels"); | strcpy(desc->params[i].name, "inchannels"); | ||||
desc->params[i].character = 'i'; | desc->params[i].character = 'i'; | ||||
@@ -386,7 +389,7 @@ extern "C" | |||||
return desc; | return desc; | ||||
} | } | ||||
SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params) | |||||
SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params) | |||||
{ | { | ||||
const JSList * node; | const JSList * node; | ||||
const jack_driver_param_t * param; | const jack_driver_param_t * param; | ||||
@@ -407,7 +410,7 @@ extern "C" | |||||
break; | break; | ||||
} | } | ||||
} | } | ||||
Jack::JackDriverClientInterface* driver = new Jack::JackCoreMidiDriver("system_midi", "coremidi", engine, table); | 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) { | if (driver->Open(1, 1, virtual_in, virtual_out, false, "in", "out", 0, 0) == 0) { | ||||
return driver; | return driver; | ||||
@@ -392,7 +392,7 @@ bool JackSocketServerChannel::HandleRequest(int fd) | |||||
JackInternalClientLoadRequest req; | JackInternalClientLoadRequest req; | ||||
JackInternalClientLoadResult res; | JackInternalClientLoadResult res; | ||||
if (req.Read(socket) == 0) | if (req.Read(socket) == 0) | ||||
res.fResult = fServer->InternalClientLoad(req.fName, req.fDllName, req.fLoadInitName, req.fOptions, &res.fIntRefNum, req.fUUID, &res.fStatus); | |||||
res.fResult = fServer->InternalClientLoad1(req.fName, req.fDllName, req.fLoadInitName, req.fOptions, &res.fIntRefNum, req.fUUID, &res.fStatus); | |||||
if (res.Write(socket) < 0) | if (res.Write(socket) < 0) | ||||
jack_error("JackRequest::InternalClientLoad write error name = %s", req.fName); | jack_error("JackRequest::InternalClientLoad write error name = %s", req.fName); | ||||
break; | break; | ||||
@@ -180,7 +180,9 @@ error: | |||||
int JackPortAudioDriver::Close() | int JackPortAudioDriver::Close() | ||||
{ | { | ||||
// Generic audio driver close | |||||
int res = JackAudioDriver::Close(); | int res = JackAudioDriver::Close(); | ||||
jack_log("JackPortAudioDriver::Close"); | jack_log("JackPortAudioDriver::Close"); | ||||
Pa_CloseStream(fStream); | Pa_CloseStream(fStream); | ||||
return res; | return res; | ||||
@@ -264,6 +264,9 @@ int JackWinMMEDriver::Close() | |||||
{ | { | ||||
jack_log("JackWinMMEDriver::Close"); | jack_log("JackWinMMEDriver::Close"); | ||||
// Generic midi driver close | |||||
int res = JackMidiDriver::Close(); | |||||
// Close input | // Close input | ||||
if (fMidiDestination) { | if (fMidiDestination) { | ||||
for (int i = 0; i < fRealCaptureChannels; i++) { | for (int i = 0; i < fRealCaptureChannels; i++) { | ||||
@@ -280,7 +283,7 @@ int JackWinMMEDriver::Close() | |||||
delete[] fMidiSource; | delete[] fMidiSource; | ||||
} | } | ||||
return 0; | |||||
return res; | |||||
} | } | ||||
int JackWinMMEDriver::Attach() | int JackWinMMEDriver::Attach() | ||||