diff --git a/ChangeLog b/ChangeLog index 9b358dc7..f4beb044 100644 --- a/ChangeLog +++ b/ChangeLog @@ -34,6 +34,10 @@ Valerio Pilo Jackdmp changes log --------------------------- +2011-03-13 Stephane Letz + + * Correct JackNetMaster::SetBufferSize. + 2011-03-11 Stephane Letz * Correct JackNetMaster::SetBufferSize. diff --git a/common/JackControlAPI.cpp b/common/JackControlAPI.cpp index cd0ec2bf..a87d1963 100644 --- a/common/JackControlAPI.cpp +++ b/common/JackControlAPI.cpp @@ -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; diff --git a/common/JackDriverLoader.cpp b/common/JackDriverLoader.cpp index 80ea3318..83bbcbb4 100644 --- a/common/JackDriverLoader.cpp +++ b/common/JackDriverLoader.cpp @@ -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); +} diff --git a/common/JackDriverLoader.h b/common/JackDriverLoader.h index 17777e54..c194304d 100644 --- a/common/JackDriverLoader.h +++ b/common/JackDriverLoader.h @@ -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); diff --git a/common/JackInternalClientChannel.h b/common/JackInternalClientChannel.h index 6b0772ce..dc81ac8c 100644 --- a/common/JackInternalClientChannel.h +++ b/common/JackInternalClientChannel.h @@ -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) diff --git a/common/JackServer.cpp b/common/JackServer.cpp index 50894529..a35cff62 100644 --- a/common/JackServer.cpp +++ b/common/JackServer.cpp @@ -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 diff --git a/common/JackServer.h b/common/JackServer.h index 9b07d60f..9c737d53 100644 --- a/common/JackServer.h +++ b/common/JackServer.h @@ -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(); diff --git a/common/JackServerAPI.cpp b/common/JackServerAPI.cpp index 5561f154..49cc4a58 100644 --- a/common/JackServerAPI.cpp +++ b/common/JackServerAPI.cpp @@ -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; } diff --git a/common/JackServerGlobals.cpp b/common/JackServerGlobals.cpp index 04489190..10349078 100644 --- a/common/JackServerGlobals.cpp +++ b/common/JackServerGlobals.cpp @@ -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 @@ -31,6 +32,8 @@ namespace Jack JackServer* JackServerGlobals::fInstance; unsigned int JackServerGlobals::fUserCount; int JackServerGlobals::fRTNotificationSocket; +std::map JackServerGlobals::fSlavesList; +std::map 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::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 ::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::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::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(); diff --git a/common/JackServerGlobals.h b/common/JackServerGlobals.h index f7d6e439..69b8979e 100644 --- a/common/JackServerGlobals.h +++ b/common/JackServerGlobals.h @@ -24,6 +24,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include "JackDriverLoader.h" #include "JackCompilerDeps.h" #include "JackServer.h" +#include 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 fSlavesList; + static std::map fInternalsList; + static bool (* on_device_acquire)(const char* device_name); static void (* on_device_release)(const char* device_name); diff --git a/common/Jackdmp.cpp b/common/Jackdmp.cpp index 954f413f..2e8a78e7 100644 --- a/common/Jackdmp.cpp +++ b/common/Jackdmp.cpp @@ -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) { diff --git a/linux/alsa/JackAlsaDriver.cpp b/linux/alsa/JackAlsaDriver.cpp index fdf5a0cb..9353e80c 100644 --- a/linux/alsa/JackAlsaDriver.cpp +++ b/linux/alsa/JackAlsaDriver.cpp @@ -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() diff --git a/linux/firewire/JackFFADODriver.cpp b/linux/firewire/JackFFADODriver.cpp index 486c3794..0966b1da 100644 --- a/linux/firewire/JackFFADODriver.cpp +++ b/linux/firewire/JackFFADODriver.cpp @@ -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() diff --git a/linux/freebob/JackFreebobDriver.cpp b/linux/freebob/JackFreebobDriver.cpp index 552e9927..96131d0b 100644 --- a/linux/freebob/JackFreebobDriver.cpp +++ b/linux/freebob/JackFreebobDriver.cpp @@ -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() diff --git a/macosx/coreaudio/JackCoreAudioDriver.cpp b/macosx/coreaudio/JackCoreAudioDriver.cpp index fc26cd4a..0acad8a7 100644 --- a/macosx/coreaudio/JackCoreAudioDriver.cpp +++ b/macosx/coreaudio/JackCoreAudioDriver.cpp @@ -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() diff --git a/macosx/coremidi/JackCoreMidiDriver.cpp b/macosx/coremidi/JackCoreMidiDriver.cpp index 55ffeae6..1cb7176b 100644 --- a/macosx/coremidi/JackCoreMidiDriver.cpp +++ b/macosx/coremidi/JackCoreMidiDriver.cpp @@ -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; diff --git a/posix/JackSocketServerChannel.cpp b/posix/JackSocketServerChannel.cpp index ac857de2..3008e307 100644 --- a/posix/JackSocketServerChannel.cpp +++ b/posix/JackSocketServerChannel.cpp @@ -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; diff --git a/windows/portaudio/JackPortAudioDriver.cpp b/windows/portaudio/JackPortAudioDriver.cpp index 1e0ae845..1732102f 100644 --- a/windows/portaudio/JackPortAudioDriver.cpp +++ b/windows/portaudio/JackPortAudioDriver.cpp @@ -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; diff --git a/windows/winmme/JackWinMMEDriver.cpp b/windows/winmme/JackWinMMEDriver.cpp index b76a8299..d3635c64 100644 --- a/windows/winmme/JackWinMMEDriver.cpp +++ b/windows/winmme/JackWinMMEDriver.cpp @@ -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()