Jack2 1.9.7

JackServerGlobals.cpp

00001 /*
00002 Copyright (C) 2005 Grame
00003 
00004 This program is free software; you can redistribute it and/or modify
00005 it under the terms of the GNU General Public License as published by
00006 the Free Software Foundation; either version 2 of the License, or
00007 (at your option) any later version.
00008 
00009 This program is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU General Public License for more details.
00013 
00014 You should have received a copy of the GNU General Public License
00015 along with this program; if not, write to the Free Software
00016 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017 
00018 */
00019 
00020 #include "JackServerGlobals.h"
00021 #include "JackLockedEngine.h"
00022 #include "JackTools.h"
00023 #include "shm.h"
00024 #include <getopt.h>
00025 #include <errno.h>
00026 #include <sys/utsname.h>
00027 
00028 static char* server_name = NULL;
00029 
00030 namespace Jack
00031 {
00032 
00033 JackServer* JackServerGlobals::fInstance;
00034 unsigned int JackServerGlobals::fUserCount;
00035 int JackServerGlobals::fRTNotificationSocket;
00036 std::map<std::string, JackDriverInfo*> JackServerGlobals::fSlavesList;
00037 std::map<std::string, int> JackServerGlobals::fInternalsList;
00038 
00039 bool (* JackServerGlobals::on_device_acquire)(const char * device_name) = NULL;
00040 void (* JackServerGlobals::on_device_release)(const char * device_name) = NULL;
00041 
00042 int JackServerGlobals::Start(const char* server_name,
00043                              jack_driver_desc_t* driver_desc,
00044                              JSList* driver_params,
00045                              int sync,
00046                              int temporary,
00047                              int time_out_ms,
00048                              int rt,
00049                              int priority,
00050                              int port_max,
00051                              int verbose,
00052                             jack_timer_type_t clock)
00053 {
00054     jack_log("Jackdmp: sync = %ld timeout = %ld rt = %ld priority = %ld verbose = %ld ", sync, time_out_ms, rt, priority, verbose);
00055     new JackServer(sync, temporary, time_out_ms, rt, priority, port_max, verbose, clock, server_name);  // Will setup fInstance and fUserCount globals
00056     int res = fInstance->Open(driver_desc, driver_params);
00057     return (res < 0) ? res : fInstance->Start();
00058 }
00059 
00060 void JackServerGlobals::Stop()
00061 {
00062     jack_log("Jackdmp: server close");
00063     fInstance->Stop();
00064     fInstance->Close();
00065 }
00066 
00067 void JackServerGlobals::Delete()
00068 {
00069     jack_log("Jackdmp: delete server");
00070 
00071     // Slave drivers
00072     std::map<std::string, JackDriverInfo*>::iterator it1;
00073     for (it1 = fSlavesList.begin(); it1 != fSlavesList.end(); it1++) {
00074         JackDriverInfo* info = (*it1).second;
00075         if (info) {
00076             fInstance->RemoveSlave((info));
00077             delete (info);
00078         }
00079     }
00080     fSlavesList.clear();
00081 
00082     // Internal clients
00083     std::map<std::string, int> ::iterator it2;
00084     for (it2 = fInternalsList.begin(); it2 != fInternalsList.end(); it2++) {
00085         int status;
00086         int refnum = (*it2).second;
00087         if (refnum > 0) {
00088             // Client object is internally kept in JackEngine, and will be desallocated in InternalClientUnload
00089             fInstance->GetEngine()->InternalClientUnload(refnum, &status);
00090         }
00091     }
00092     fInternalsList.clear();
00093 
00094     delete fInstance;
00095     fInstance = NULL;
00096 }
00097 
00098 bool JackServerGlobals::Init()
00099 {
00100     struct utsname utsname;
00101     int success;
00102     success = uname( &utsname );
00103     
00104     int realtime = 0;
00105     int client_timeout = 0; /* msecs; if zero, use period size. */
00106     int realtime_priority;
00107     if( success == 0 && strstr( utsname.version, "PREEMPT RT" ) )
00108       realtime_priority = 60;
00109     else
00110       realtime_priority = 20;
00111     int verbose_aux = 0;
00112     int do_mlock = 1;
00113     unsigned int port_max = 128;
00114     int do_unlock = 0;
00115     int temporary = 0;
00116 
00117     int opt = 0;
00118     int option_index = 0;
00119     char *master_driver_name = NULL;
00120     char **master_driver_args = NULL;
00121     JSList* master_driver_params = NULL;
00122     jack_driver_desc_t* driver_desc;
00123     jack_timer_type_t clock_source = JACK_TIMER_SYSTEM_CLOCK;
00124     int driver_nargs = 1;
00125     JSList* drivers = NULL;
00126     int loopback = 0;
00127     int sync = 0;
00128     int rc, i;
00129     int ret;
00130     int replace_registry = 0;
00131 
00132     FILE* fp = 0;
00133     char filename[255];
00134     char buffer[255];
00135     int argc = 0;
00136     char* argv[32];
00137 
00138     // First user starts the server
00139     if (fUserCount++ == 0) {
00140 
00141         jack_log("JackServerGlobals Init");
00142 
00143         const char *options = "-d:X:I:P:uvshVrRL:STFl:t:mn:p:"
00144     #ifdef __linux__
00145             "c:"
00146     #endif
00147         ;
00148 
00149     struct option long_options[] = {
00150     #ifdef __linux__
00151                                        { "clock-source", 1, 0, 'c' },
00152     #endif
00153                                        { "loopback-driver", 1, 0, 'L' },
00154                                        { "audio-driver", 1, 0, 'd' },
00155                                        { "midi-driver", 1, 0, 'X' },
00156                                        { "internal-client", 1, 0, 'I' },
00157                                        { "verbose", 0, 0, 'v' },
00158                                        { "help", 0, 0, 'h' },
00159                                        { "port-max", 1, 0, 'p' },
00160                                        { "no-mlock", 0, 0, 'm' },
00161                                        { "name", 1, 0, 'n' },
00162                                        { "unlock", 0, 0, 'u' },
00163                                        { "realtime", 0, 0, 'R' },
00164                                        { "no-realtime", 0, 0, 'r' },
00165                                        { "replace-registry", 0, &replace_registry, 0 },
00166                                        { "loopback", 0, 0, 'L' },
00167                                        { "realtime-priority", 1, 0, 'P' },
00168                                        { "timeout", 1, 0, 't' },
00169                                        { "temporary", 0, 0, 'T' },
00170                                        { "version", 0, 0, 'V' },
00171                                        { "silent", 0, 0, 's' },
00172                                        { "sync", 0, 0, 'S' },
00173                                        { 0, 0, 0, 0 }
00174                                    };
00175 
00176         snprintf(filename, 255, "%s/.jackdrc", getenv("HOME"));
00177         fp = fopen(filename, "r");
00178 
00179         if (!fp) {
00180             fp = fopen("/etc/jackdrc", "r");
00181         }
00182         // if still not found, check old config name for backwards compatability
00183         if (!fp) {
00184             fp = fopen("/etc/jackd.conf", "r");
00185         }
00186 
00187         argc = 0;
00188         if (fp) {
00189             ret = fscanf(fp, "%s", buffer);
00190             while (ret != 0 && ret != EOF) {
00191                 argv[argc] = (char*)malloc(64);
00192                 strcpy(argv[argc], buffer);
00193                 ret = fscanf(fp, "%s", buffer);
00194                 argc++;
00195             }
00196             fclose(fp);
00197         }
00198 
00199         /*
00200         For testing
00201         int argc = 15;
00202         char* argv[] = {"jackdmp", "-R", "-v", "-d", "coreaudio", "-p", "512", "-d", "~:Aggregate:0", "-r", "48000", "-i", "2", "-o", "2" };
00203         */
00204 
00205         opterr = 0;
00206         optind = 1; // Important : to reset argv parsing
00207 
00208         while (!master_driver_name &&
00209                 (opt = getopt_long(argc, argv, options, long_options, &option_index)) != EOF) {
00210 
00211             switch (opt) {
00212 
00213                 case 'c':
00214                     if (tolower (optarg[0]) == 'h') {
00215                         clock_source = JACK_TIMER_HPET;
00216                     } else if (tolower (optarg[0]) == 'c') {
00217                         clock_source = JACK_TIMER_CYCLE_COUNTER;
00218                     } else if (tolower (optarg[0]) == 's') {
00219                         clock_source = JACK_TIMER_SYSTEM_CLOCK;
00220                     } else {
00221                         jack_error("unknown option character %c", optopt);
00222                     }
00223                     break;
00224 
00225                 case 'd':
00226                     master_driver_name = optarg;
00227                     break;
00228 
00229                 case 'L':
00230                     loopback = atoi(optarg);
00231                     break;
00232 
00233                  case 'X':
00234                     fSlavesList[optarg] = NULL;
00235                     break;
00236 
00237                 case 'I':
00238                     fInternalsList[optarg] = -1;
00239                     break;
00240 
00241                 case 'p':
00242                     port_max = (unsigned int)atol(optarg);
00243                     break;
00244 
00245                 case 'm':
00246                     do_mlock = 0;
00247                     break;
00248 
00249                 case 'u':
00250                     do_unlock = 1;
00251                     break;
00252 
00253                 case 'v':
00254                     verbose_aux = 1;
00255                     break;
00256 
00257                 case 'S':
00258                     sync = 1;
00259                     break;
00260 
00261                 case 'n':
00262                     server_name = optarg;
00263                     break;
00264 
00265                 case 'P':
00266                     realtime_priority = atoi(optarg);
00267                     break;
00268 
00269                 case 'r':
00270                     realtime = 0;
00271                     break;
00272 
00273                 case 'R':
00274                     realtime = 1;
00275                     break;
00276 
00277                 case 'T':
00278                     temporary = 1;
00279                     break;
00280 
00281                 case 't':
00282                     client_timeout = atoi(optarg);
00283                     break;
00284 
00285                 default:
00286                     jack_error("unknown option character %c", optopt);
00287                     break;
00288             }
00289         }
00290 
00291         drivers = jack_drivers_load(drivers);
00292         if (!drivers) {
00293             jack_error("jackdmp: no drivers found; exiting");
00294             goto error;
00295         }
00296 
00297         driver_desc = jack_find_driver_descriptor(drivers, master_driver_name);
00298         if (!driver_desc) {
00299             jack_error("jackdmp: unknown master driver '%s'", master_driver_name);
00300             goto error;
00301         }
00302 
00303         if (optind < argc) {
00304             driver_nargs = 1 + argc - optind;
00305         } else {
00306             driver_nargs = 1;
00307         }
00308 
00309         if (driver_nargs == 0) {
00310             jack_error("No driver specified ... hmm. JACK won't do"
00311                        " anything when run like this.");
00312             goto error;
00313         }
00314 
00315         master_driver_args = (char**)malloc(sizeof(char*) * driver_nargs);
00316         master_driver_args[0] = master_driver_name;
00317 
00318         for (i = 1; i < driver_nargs; i++) {
00319             master_driver_args[i] = argv[optind++];
00320         }
00321 
00322         if (jack_parse_driver_params(driver_desc, driver_nargs, master_driver_args, &master_driver_params)) {
00323             goto error;
00324         }
00325 
00326 #ifndef WIN32
00327         if (server_name == NULL)
00328             server_name = (char*)JackTools::DefaultServerName();
00329 #endif
00330 
00331         rc = jack_register_server(server_name, false);
00332         switch (rc) {
00333             case EEXIST:
00334                 jack_error("`%s' server already active", server_name);
00335                 goto error;
00336             case ENOSPC:
00337                 jack_error("too many servers already active");
00338                 goto error;
00339             case ENOMEM:
00340                 jack_error("no access to shm registry");
00341                 goto error;
00342             default:
00343                 jack_info("server `%s' registered", server_name);
00344         }
00345 
00346         /* clean up shared memory and files from any previous instance of this server name */
00347         jack_cleanup_shm();
00348         JackTools::CleanupFiles(server_name);
00349 
00350         if (!realtime && client_timeout == 0)
00351             client_timeout = 500; /* 0.5 sec; usable when non realtime. */
00352 
00353         for (i = 0; i < argc; i++) {
00354             free(argv[i]);
00355         }
00356 
00357         int res = Start(server_name, driver_desc, master_driver_params, sync, temporary, client_timeout, realtime, realtime_priority, port_max, verbose_aux, clock_source);
00358         if (res < 0) {
00359             jack_error("Cannot start server... exit");
00360             Delete();
00361             jack_cleanup_shm();
00362             JackTools::CleanupFiles(server_name);
00363             jack_unregister_server(server_name);
00364             goto error;
00365         }
00366 
00367         // Slave drivers
00368         std::map<std::string, JackDriverInfo*>::iterator it1;
00369         for (it1 = fSlavesList.begin(); it1 != fSlavesList.end(); it1++) {
00370             const char* name = ((*it1).first).c_str();
00371             driver_desc = jack_find_driver_descriptor(drivers, name);
00372             if (!driver_desc) {
00373                 jack_error("jackdmp: unknown slave driver '%s'", name);
00374             } else {
00375                 (*it1).second = fInstance->AddSlave(driver_desc, NULL);
00376             }
00377         }
00378 
00379         // Loopback driver
00380         if (loopback > 0) {
00381             driver_desc = jack_find_driver_descriptor(drivers, "loopback");
00382             if (!driver_desc) {
00383                 jack_error("jackdmp: unknown driver '%s'", "loopback");
00384             } else {
00385                 fSlavesList["loopback"] = fInstance->AddSlave(driver_desc, NULL);
00386             }
00387         }
00388 
00389         // Internal clients
00390         std::map<std::string, int>::iterator it2;
00391         for (it2 = fInternalsList.begin(); it2 != fInternalsList.end(); it2++) {
00392             int status, refnum;
00393             const char* name = ((*it2).first).c_str();
00394             fInstance->InternalClientLoad2(name, name, NULL, JackNullOption, &refnum, -1, &status);
00395             (*it2).second = refnum;
00396         }
00397     }
00398 
00399     if (master_driver_params)
00400         jack_free_driver_params(master_driver_params);
00401     return true;
00402 
00403 error:
00404     jack_log("JackServerGlobals Init error");
00405     if (master_driver_params)
00406         jack_free_driver_params(master_driver_params);
00407     Destroy();
00408     return false;
00409 }
00410 
00411 void JackServerGlobals::Destroy()
00412 {
00413     if (--fUserCount == 0) {
00414         jack_log("JackServerGlobals Destroy");
00415         Stop();
00416         Delete();
00417         jack_cleanup_shm();
00418         JackTools::CleanupFiles(server_name);
00419         jack_unregister_server(server_name);
00420     }
00421 }
00422 
00423 } // end of namespace
00424 
00425 

Generated for Jack2 by doxygen 1.7.3