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() | |||