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 | |||
--------------------------- | |||
2011-03-13 Stephane Letz <letz@grame.fr> | |||
* Correct JackNetMaster::SetBufferSize. | |||
2011-03-11 Stephane Letz <letz@grame.fr> | |||
* Correct JackNetMaster::SetBufferSize. | |||
@@ -78,15 +78,15 @@ struct jackctl_server | |||
/* int32_t, msecs; if zero, use period size. */ | |||
union jackctl_parameter_value client_timeout; | |||
union jackctl_parameter_value default_client_timeout; | |||
/* uint32_t, clock source type */ | |||
union jackctl_parameter_value clock_source; | |||
union jackctl_parameter_value default_clock_source; | |||
/* uint32_t, max port number */ | |||
union jackctl_parameter_value port_max; | |||
union jackctl_parameter_value default_port_max; | |||
/* bool */ | |||
union jackctl_parameter_value replace_registry; | |||
union jackctl_parameter_value default_replace_registry; | |||
@@ -366,7 +366,7 @@ jackctl_internals_load( | |||
} | |||
while (descriptor_node_ptr != NULL) | |||
{ | |||
{ | |||
internal_ptr = (struct jackctl_internal *)malloc(sizeof(struct jackctl_internal)); | |||
if (internal_ptr == NULL) | |||
{ | |||
@@ -745,7 +745,7 @@ EXPORT jackctl_server_t * jackctl_server_create( | |||
{ | |||
goto fail_free_parameters; | |||
} | |||
value.ui = PORT_NUM; | |||
if (jackctl_add_parameter( | |||
&server_ptr->parameters, | |||
@@ -795,7 +795,7 @@ EXPORT jackctl_server_t * jackctl_server_create( | |||
{ | |||
goto fail_free_parameters; | |||
} | |||
/* Allowed to fail */ | |||
jackctl_internals_load(server_ptr); | |||
@@ -882,7 +882,7 @@ jackctl_server_start( | |||
if (!server_ptr->realtime.b && server_ptr->client_timeout.i == 0) | |||
server_ptr->client_timeout.i = 500; /* 0.5 sec; usable when non realtime. */ | |||
/* check port max value before allocating server */ | |||
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); | |||
@@ -896,7 +896,7 @@ jackctl_server_start( | |||
server_ptr->client_timeout.i, | |||
server_ptr->realtime.b, | |||
server_ptr->realtime_priority.i, | |||
server_ptr->port_max.ui, | |||
server_ptr->port_max.ui, | |||
server_ptr->verbose.b, | |||
(jack_timer_type_t)server_ptr->clock_source.ui, | |||
server_ptr->name.str); | |||
@@ -1179,7 +1179,7 @@ EXPORT bool jackctl_server_load_internal( | |||
{ | |||
int status; | |||
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); | |||
} else { | |||
return false; | |||
@@ -1192,6 +1192,7 @@ EXPORT bool jackctl_server_unload_internal( | |||
{ | |||
int status; | |||
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); | |||
} else { | |||
return false; | |||
@@ -446,7 +446,7 @@ jack_get_descriptor (JSList * drivers, const char * sofile, const char * symbol) | |||
free(filename); | |||
return NULL; | |||
} | |||
if ((descriptor = so_get_descriptor ()) == NULL) { | |||
jack_error("driver from '%s' returned NULL descriptor", filename); | |||
UnloadDriverModule(dlhandle); | |||
@@ -467,7 +467,7 @@ jack_get_descriptor (JSList * drivers, const char * sofile, const char * symbol) | |||
/* check it doesn't exist already */ | |||
for (node = drivers; node; node = jack_slist_next (node)) { | |||
other_descriptor = (jack_driver_desc_t *) node->data; | |||
if (strcmp(descriptor->name, other_descriptor->name) == 0) { | |||
jack_error("the drivers in '%s' and '%s' both have the name '%s'; using the first", | |||
other_descriptor->file, filename, other_descriptor->name); | |||
@@ -603,7 +603,7 @@ jack_drivers_load (JSList * drivers) { | |||
} | |||
while ((dir_entry = readdir(dir_stream))) { | |||
/* check the filename is of the right format */ | |||
if (strncmp ("jack_", dir_entry->d_name, 5) != 0) { | |||
continue; | |||
@@ -619,7 +619,7 @@ jack_drivers_load (JSList * drivers) { | |||
} | |||
desc = jack_get_descriptor (drivers, dir_entry->d_name, "driver_get_descriptor"); | |||
if (desc) { | |||
driver_list = jack_slist_append (driver_list, desc); | |||
} else { | |||
@@ -771,9 +771,9 @@ jack_internals_load (JSList * internals) { | |||
#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) | |||
{ | |||
#ifdef WIN32 | |||
@@ -783,7 +783,7 @@ Jack::JackDriverClientInterface* JackDriverInfo::Open(jack_driver_desc_t* driver | |||
#endif | |||
fHandle = LoadDriverModule (driver_desc->file); | |||
if (fHandle == NULL) { | |||
#ifdef WIN32 | |||
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); | |||
return NULL; | |||
} | |||
fBackend = fInitialize(engine, synchro, params); | |||
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 "JackControlAPI.h" | |||
#include "JackPlatformPlug.h" | |||
#include "JackDriver.h" | |||
#include "JackSystemDeps.h" | |||
namespace Jack | |||
{ | |||
class JackDriverClientInterface; | |||
class JackLockedEngine; | |||
}; | |||
typedef jack_driver_desc_t * (*JackDriverDescFunction) (); | |||
typedef Jack::JackDriverClientInterface* (*driverInitialize) (Jack::JackLockedEngine*, Jack::JackSynchro*, const JSList*); | |||
@@ -39,34 +34,30 @@ class JackDriverInfo | |||
{ | |||
private: | |||
driverInitialize fInitialize; | |||
DRIVER_HANDLE fHandle; | |||
Jack::JackDriverClientInterface* fBackend; | |||
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* GetBackend() | |||
{ | |||
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 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) | |||
{ | |||
*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) | |||
@@ -61,7 +61,6 @@ JackServer::JackServer(bool sync, bool temporary, int timeout, bool rt, int prio | |||
JackServer::~JackServer() | |||
{ | |||
JackGraphManager::Destroy(fGraphManager); | |||
delete fAudioDriver; | |||
delete fDriverInfo; | |||
delete fFreewheelDriver; | |||
delete fEngine; | |||
@@ -136,14 +135,14 @@ int JackServer::Close() | |||
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); | |||
assert(client); | |||
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); | |||
assert(client); | |||
@@ -154,6 +153,8 @@ int JackServer::InternalClientLoadAux(JackLoadableInternalClient* client, const | |||
{ | |||
// Clear status | |||
*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)) { | |||
delete client; | |||
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 fAudioDriver; | |||
delete fDriverInfo; | |||
// Activate master | |||
@@ -57,7 +57,7 @@ class SERVER_EXPORT JackServer | |||
JackConnectionManager fConnectionState; | |||
JackSynchro fSynchroTable[CLIENT_NUM]; | |||
bool fFreewheel; | |||
int InternalClientLoadAux(JackLoadableInternalClient* client, const char* so_name, const char* client_name, int options, int* int_ref, int uuid, int* status); | |||
public: | |||
@@ -77,19 +77,19 @@ class SERVER_EXPORT JackServer | |||
// Command thread : API | |||
int SetBufferSize(jack_nframes_t buffer_size); | |||
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); | |||
// Transport management | |||
int ReleaseTimebase(int refnum); | |||
int SetTimebaseCallback(int refnum, int conditional); | |||
// Backend management | |||
JackDriverInfo* AddSlave(jack_driver_desc_t* driver_desc, JSList* driver_params); | |||
void RemoveSlave(JackDriverInfo* info); | |||
int SwitchMaster(jack_driver_desc_t* driver_desc, JSList* driver_params); | |||
// Object access | |||
JackLockedEngine* GetEngine(); | |||
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); | |||
if (status == NULL) /* no status from caller? */ | |||
status = &my_status; /* use local status word */ | |||
*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 */ | |||
jack_varargs_init(&va); | |||
if (!JackServerGlobals::Init()) { // jack server initialisation | |||
int my_status1 = (JackFailure | JackServerError); | |||
*status = (jack_status_t)my_status1; | |||
return NULL; | |||
} | |||
if (JACK_DEBUG) { | |||
client = new JackDebugClient(new JackInternalClient(JackServerGlobals::fInstance, GetSynchroTable())); // Debug mode | |||
} 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); | |||
if (status == NULL) /* no status from caller? */ | |||
status = &my_status; /* use local status word */ | |||
*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 */ | |||
jack_varargs_parse(options, ap, &va); | |||
if (!JackServerGlobals::Init()) { // jack server initialisation | |||
int my_status1 = (JackFailure | JackServerError); | |||
*status = (jack_status_t)my_status1; | |||
return NULL; | |||
} | |||
if (JACK_DEBUG) { | |||
client = new JackDebugClient(new JackInternalClient(JackServerGlobals::fInstance, GetSynchroTable())); // Debug mode | |||
} else { | |||
@@ -180,7 +180,7 @@ EXPORT int jack_client_close(jack_client_t* ext_client) | |||
{ | |||
#ifdef __CLIENTDEBUG__ | |||
JackGlobals::CheckContext("jack_client_close"); | |||
#endif | |||
#endif | |||
assert(JackGlobals::fOpenMutex); | |||
JackGlobals::fOpenMutex->Lock(); | |||
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) | |||
{ | |||
return (JackServerGlobals::fInstance != NULL) | |||
return (JackServerGlobals::fInstance != NULL) | |||
? JackServerGlobals::fInstance->GetEngine()->GetClientPID(name) | |||
: 0; | |||
} | |||
@@ -18,6 +18,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
*/ | |||
#include "JackServerGlobals.h" | |||
#include "JackLockedEngine.h" | |||
#include "JackTools.h" | |||
#include "shm.h" | |||
#include <getopt.h> | |||
@@ -31,6 +32,8 @@ namespace Jack | |||
JackServer* JackServerGlobals::fInstance; | |||
unsigned int JackServerGlobals::fUserCount; | |||
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; | |||
void (* JackServerGlobals::on_device_release)(const char * device_name) = NULL; | |||
@@ -63,6 +66,30 @@ void JackServerGlobals::Stop() | |||
void JackServerGlobals::Delete() | |||
{ | |||
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; | |||
fInstance = NULL; | |||
} | |||
@@ -80,49 +107,62 @@ bool JackServerGlobals::Init() | |||
int opt = 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; | |||
JSList* drivers = NULL; | |||
int show_version = 0; | |||
int loopback = 0; | |||
int sync = 0; | |||
int rc, i; | |||
int ret; | |||
int replace_registry = 0; | |||
FILE* fp = 0; | |||
char filename[255]; | |||
char buffer[255]; | |||
int argc = 0; | |||
char* argv[32]; | |||
jack_timer_type_t clock_source = JACK_TIMER_SYSTEM_CLOCK; | |||
// First user starts the server | |||
if (fUserCount++ == 0) { | |||
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")); | |||
fp = fopen(filename, "r"); | |||
@@ -156,7 +196,7 @@ bool JackServerGlobals::Init() | |||
opterr = 0; | |||
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) { | |||
switch (opt) { | |||
@@ -174,34 +214,53 @@ bool JackServerGlobals::Init() | |||
break; | |||
case 'd': | |||
seen_driver = 1; | |||
driver_name = optarg; | |||
master_driver_name = optarg; | |||
break; | |||
case 'v': | |||
verbose_aux = 1; | |||
case 'L': | |||
loopback = atoi(optarg); | |||
break; | |||
case 'S': | |||
sync = 1; | |||
case 'X': | |||
fSlavesList[optarg] = NULL; | |||
break; | |||
case 'n': | |||
server_name = optarg; | |||
case 'I': | |||
fInternalsList[optarg] = -1; | |||
break; | |||
case 'p': | |||
port_max = (unsigned int)atol(optarg); | |||
break; | |||
case 'm': | |||
do_mlock = 0; | |||
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; | |||
case 'P': | |||
realtime_priority = atoi(optarg); | |||
break; | |||
case 'r': | |||
realtime = 0; | |||
break; | |||
case 'R': | |||
realtime = 1; | |||
break; | |||
@@ -214,14 +273,6 @@ bool JackServerGlobals::Init() | |||
client_timeout = atoi(optarg); | |||
break; | |||
case 'u': | |||
do_unlock = 1; | |||
break; | |||
case 'V': | |||
show_version = 1; | |||
break; | |||
default: | |||
jack_error("unknown option character %c", optopt); | |||
break; | |||
@@ -234,9 +285,9 @@ bool JackServerGlobals::Init() | |||
goto error; | |||
} | |||
driver_desc = jack_find_driver_descriptor(drivers, driver_name); | |||
driver_desc = jack_find_driver_descriptor(drivers, master_driver_name); | |||
if (!driver_desc) { | |||
jack_error("jackdmp: unknown driver '%s'", driver_name); | |||
jack_error("jackdmp: unknown master driver '%s'", master_driver_name); | |||
goto error; | |||
} | |||
@@ -252,14 +303,14 @@ bool JackServerGlobals::Init() | |||
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++) { | |||
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; | |||
} | |||
@@ -294,7 +345,7 @@ bool JackServerGlobals::Init() | |||
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) { | |||
jack_error("Cannot start server... exit"); | |||
Delete(); | |||
@@ -303,21 +354,57 @@ bool JackServerGlobals::Init() | |||
jack_unregister_server(server_name); | |||
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; | |||
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; | |||
} | |||
void JackServerGlobals::Destroy() | |||
{ | |||
printf("JackServerGlobals Destroy %d\n", fUserCount); | |||
if (--fUserCount == 0) { | |||
jack_log("JackServerGlobals Destroy"); | |||
Stop(); | |||
@@ -24,6 +24,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
#include "JackDriverLoader.h" | |||
#include "JackCompilerDeps.h" | |||
#include "JackServer.h" | |||
#include <map> | |||
namespace Jack | |||
{ | |||
@@ -39,6 +40,9 @@ struct SERVER_EXPORT JackServerGlobals | |||
static JackServer* fInstance; | |||
static unsigned int fUserCount; | |||
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 void (* on_device_release)(const char* device_name); | |||
@@ -229,8 +229,8 @@ int main(int argc, char* argv[]) | |||
int i,opt = 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 do_mlock = 1; | |||
int do_unlock = 0; | |||
@@ -426,7 +426,7 @@ int main(int argc, char* argv[]) | |||
goto fail_free1; | |||
} | |||
// Audio driver | |||
// Master driver | |||
master_driver_ctl = jackctl_server_get_driver(server_ctl, master_driver_name); | |||
if (master_driver_ctl == NULL) { | |||
fprintf(stderr, "Unknown driver \"%s\"\n", master_driver_name); | |||
@@ -464,7 +464,7 @@ int main(int argc, char* argv[]) | |||
goto fail_free1; | |||
} | |||
// Slave driver | |||
// Slave drivers | |||
for (it = slaves_list.begin(); it != slaves_list.end(); it++) { | |||
jackctl_driver_t * slave_driver_ctl = jackctl_server_get_driver(server_ctl, *it); | |||
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++) { | |||
jackctl_internal_t * internal_driver_ctl = jackctl_server_get_internal(server_ctl, *it); | |||
if (internal_driver_ctl == NULL) { | |||
@@ -2291,7 +2291,9 @@ int JackAlsaDriver::Open(jack_nframes_t nframes, | |||
int JackAlsaDriver::Close() | |||
{ | |||
JackAudioDriver::Close(); | |||
// Generic audio driver close | |||
int res = JackAudioDriver::Close(); | |||
alsa_driver_delete((alsa_driver_t*)fDriver); | |||
if (JackServerGlobals::on_device_release != NULL) | |||
@@ -2310,7 +2312,7 @@ int JackAlsaDriver::Close() | |||
} | |||
} | |||
return 0; | |||
return res; | |||
} | |||
int JackAlsaDriver::Start() | |||
@@ -644,9 +644,11 @@ int JackFFADODriver::Open(ffado_jack_settings_t *params) | |||
int JackFFADODriver::Close() | |||
{ | |||
JackAudioDriver::Close(); | |||
// Generic audio driver close | |||
int res = JackAudioDriver::Close(); | |||
ffado_driver_delete((ffado_driver_t*)fDriver); | |||
return 0; | |||
return res; | |||
} | |||
int JackFFADODriver::Start() | |||
@@ -832,9 +832,11 @@ int JackFreebobDriver::Open(freebob_jack_settings_t *params) | |||
int JackFreebobDriver::Close() | |||
{ | |||
JackAudioDriver::Close(); | |||
// Generic audio driver close | |||
int res = JackAudioDriver::Close(); | |||
freebob_driver_delete((freebob_driver_t*)fDriver); | |||
return 0; | |||
return res; | |||
} | |||
int JackFreebobDriver::Start() | |||
@@ -1551,12 +1551,15 @@ int JackCoreAudioDriver::Close() | |||
{ | |||
jack_log("JackCoreAudioDriver::Close"); | |||
Stop(); | |||
JackAudioDriver::Close(); | |||
// Generic audio driver close | |||
int res = JackAudioDriver::Close(); | |||
RemoveListeners(); | |||
DisposeBuffers(); | |||
CloseAUHAL(); | |||
DestroyAggregateDevice(); | |||
return 0; | |||
return res; | |||
} | |||
int JackCoreAudioDriver::Attach() | |||
@@ -45,15 +45,15 @@ void JackCoreMidiDriver::ReadProcAux(const MIDIPacketList *pktlist, jack_ringbuf | |||
jack_error("ReadProc : ring buffer is full, skip events..."); | |||
return; | |||
} | |||
jack_ringbuffer_write(ringbuffer, (char*)&pktlist->numPackets, sizeof(UInt32)); | |||
for (unsigned int i = 0; i < pktlist->numPackets; ++i) { | |||
MIDIPacket *packet = (MIDIPacket *)pktlist->packet; | |||
// TODO : use timestamp | |||
// Check available size first.. | |||
size = jack_ringbuffer_write_space(ringbuffer); | |||
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)); | |||
// Write event actual data | |||
jack_ringbuffer_write(ringbuffer, (char*)packet->data, packet->length); | |||
packet = MIDIPacketNext(packet); | |||
} | |||
} | |||
@@ -83,7 +83,7 @@ void JackCoreMidiDriver::ReadVirtualProc(const MIDIPacketList *pktlist, void *re | |||
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) | |||
@@ -106,15 +106,15 @@ int JackCoreMidiDriver::Open(bool capturing, | |||
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); | |||
@@ -122,7 +122,7 @@ int JackCoreMidiDriver::Open(bool capturing, | |||
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"); | |||
@@ -134,10 +134,10 @@ int JackCoreMidiDriver::Open(bool capturing, | |||
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; | |||
@@ -151,13 +151,13 @@ int JackCoreMidiDriver::Open(bool capturing, | |||
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); | |||
@@ -172,47 +172,50 @@ int JackCoreMidiDriver::Open(bool capturing, | |||
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() | |||
{ | |||
// Generic midi driver close | |||
int res = JackMidiDriver::Close(); | |||
if (fInputPort) | |||
MIDIPortDispose(fInputPort); | |||
if (fOutputPort) | |||
if (fOutputPort) | |||
MIDIPortDispose(fOutputPort); | |||
// Only dispose "virtual" endpoints | |||
for (int i = 0; i < fCaptureChannels - fRealCaptureChannels; i++) { | |||
if (fMidiDestination) | |||
if (fMidiDestination) | |||
MIDIEndpointDispose(fMidiDestination[i]); | |||
} | |||
delete[] fMidiDestination; | |||
// Only dispose "virtual" endpoints | |||
for (int i = 0; i < fPlaybackChannels - fRealPlaybackChannels; i++) { | |||
if (fMidiSource[i]) | |||
if (fMidiSource[i]) | |||
MIDIEndpointDispose(fMidiSource[i]); | |||
} | |||
delete[] fMidiSource; | |||
if (fMidiClient) | |||
if (fMidiClient) | |||
MIDIClientDispose(fMidiClient); | |||
return 0; | |||
return res; | |||
} | |||
int JackCoreMidiDriver::Attach() | |||
@@ -229,7 +232,7 @@ int JackCoreMidiDriver::Attach() | |||
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); | |||
@@ -238,7 +241,7 @@ int JackCoreMidiDriver::Attach() | |||
} 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, CaptureDriverFlags, fEngineControl->fBufferSize)) == NO_PORT) { | |||
jack_error("driver: cannot register port for %s", name); | |||
@@ -251,7 +254,7 @@ int JackCoreMidiDriver::Attach() | |||
} | |||
for (i = 0; i < fPlaybackChannels; i++) { | |||
err = MIDIObjectGetStringProperty(fMidiSource[i], kMIDIPropertyName, &pname); | |||
if (err == noErr) { | |||
CFStringGetCString(pname, endpoint_name, sizeof(endpoint_name), 0); | |||
@@ -260,7 +263,7 @@ int JackCoreMidiDriver::Attach() | |||
} 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, PlaybackDriverFlags, fEngineControl->fBufferSize)) == NO_PORT) { | |||
jack_error("driver: cannot register port for %s", name); | |||
@@ -277,23 +280,23 @@ int JackCoreMidiDriver::Attach() | |||
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; | |||
@@ -304,7 +307,7 @@ int JackCoreMidiDriver::Read() | |||
} | |||
} | |||
} | |||
} else { | |||
// Consume ring buffer | |||
jack_ringbuffer_read_advance(fRingBuffer[chan], jack_ringbuffer_read_space(fRingBuffer[chan])); | |||
@@ -316,35 +319,35 @@ int JackCoreMidiDriver::Read() | |||
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) | |||
if (err != noErr) | |||
jack_error("MIDIReceived error"); | |||
} else { | |||
OSStatus err = MIDISend(fOutputPort, fMidiSource[chan], pktlist); | |||
if (err != noErr) | |||
if (err != noErr) | |||
jack_error("MIDISend error"); | |||
} | |||
} | |||
} | |||
} | |||
return 0; | |||
} | |||
@@ -355,7 +358,7 @@ extern "C" | |||
{ | |||
#endif | |||
SERVER_EXPORT jack_driver_desc_t * driver_get_descriptor() | |||
SERVER_EXPORT jack_driver_desc_t * driver_get_descriptor() | |||
{ | |||
jack_driver_desc_t * desc; | |||
unsigned int i; | |||
@@ -366,7 +369,7 @@ extern "C" | |||
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'; | |||
@@ -386,7 +389,7 @@ extern "C" | |||
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 jack_driver_param_t * param; | |||
@@ -407,7 +410,7 @@ extern "C" | |||
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; | |||
@@ -392,7 +392,7 @@ bool JackSocketServerChannel::HandleRequest(int fd) | |||
JackInternalClientLoadRequest req; | |||
JackInternalClientLoadResult res; | |||
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) | |||
jack_error("JackRequest::InternalClientLoad write error name = %s", req.fName); | |||
break; | |||
@@ -180,7 +180,9 @@ error: | |||
int JackPortAudioDriver::Close() | |||
{ | |||
// Generic audio driver close | |||
int res = JackAudioDriver::Close(); | |||
jack_log("JackPortAudioDriver::Close"); | |||
Pa_CloseStream(fStream); | |||
return res; | |||
@@ -264,6 +264,9 @@ int JackWinMMEDriver::Close() | |||
{ | |||
jack_log("JackWinMMEDriver::Close"); | |||
// Generic midi driver close | |||
int res = JackMidiDriver::Close(); | |||
// Close input | |||
if (fMidiDestination) { | |||
for (int i = 0; i < fRealCaptureChannels; i++) { | |||
@@ -280,7 +283,7 @@ int JackWinMMEDriver::Close() | |||
delete[] fMidiSource; | |||
} | |||
return 0; | |||
return res; | |||
} | |||
int JackWinMMEDriver::Attach() | |||