Jack2 1.9.6

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 "JackTools.h"
00022 #include "shm.h"
00023 #include <getopt.h>
00024 #include <errno.h>
00025 #include <sys/utsname.h>
00026 
00027 static char* server_name = NULL;
00028 
00029 namespace Jack
00030 {
00031 
00032 JackServer* JackServerGlobals::fInstance; 
00033 unsigned int JackServerGlobals::fUserCount;
00034 bool (* JackServerGlobals::on_device_acquire)(const char * device_name) = NULL;
00035 void (* JackServerGlobals::on_device_release)(const char * device_name) = NULL;
00036 
00037 int JackServerGlobals::Start(const char* server_name,
00038                              jack_driver_desc_t* driver_desc,
00039                              JSList* driver_params,
00040                              int sync,
00041                              int temporary,
00042                              int time_out_ms,
00043                              int rt,
00044                              int priority,
00045                              int port_max,
00046                              int verbose,
00047                             jack_timer_type_t clock)
00048 {
00049     jack_log("Jackdmp: sync = %ld timeout = %ld rt = %ld priority = %ld verbose = %ld ", sync, time_out_ms, rt, priority, verbose);
00050     new JackServer(sync, temporary, time_out_ms, rt, priority, port_max, verbose, clock, server_name);  // Will setup fInstance and fUserCount globals
00051     int res = fInstance->Open(driver_desc, driver_params);
00052     return (res < 0) ? res : fInstance->Start();
00053 }
00054 
00055 void JackServerGlobals::Stop()
00056 {
00057     jack_log("Jackdmp: server close");
00058     fInstance->Stop();
00059     fInstance->Close();
00060 }
00061 
00062 void JackServerGlobals::Delete()
00063 {
00064     jack_log("Jackdmp: delete server");
00065     delete fInstance;
00066     fInstance = NULL;
00067 }
00068 
00069 bool JackServerGlobals::Init()
00070 {
00071     struct utsname utsname;
00072     int success;
00073     success = uname( &utsname );
00074     
00075     int realtime = 0;
00076     int client_timeout = 0; /* msecs; if zero, use period size. */
00077     int realtime_priority;
00078     if( success == 0 && strstr( utsname.version, "PREEMPT RT" ) )
00079       realtime_priority = 60;
00080     else
00081       realtime_priority = 20;
00082     int verbose_aux = 0;
00083     int do_mlock = 1;
00084     unsigned int port_max = 128;
00085     int do_unlock = 0;
00086     int temporary = 0;
00087 
00088     int opt = 0;
00089     int option_index = 0;
00090     int seen_driver = 0;
00091     char *driver_name = NULL;
00092     char **driver_args = NULL;
00093     JSList* driver_params = NULL;
00094     int driver_nargs = 1;
00095     JSList* drivers = NULL;
00096     int show_version = 0;
00097     int sync = 0;
00098     int rc, i;
00099     int ret;
00100 
00101     FILE* fp = 0;
00102     char filename[255];
00103     char buffer[255];
00104     int argc = 0;
00105     char* argv[32];
00106     jack_timer_type_t clock_source = JACK_TIMER_SYSTEM_CLOCK;
00107     
00108     // First user starts the server
00109     if (fUserCount++ == 0) {
00110 
00111         jack_log("JackServerGlobals Init");
00112 
00113         jack_driver_desc_t* driver_desc;
00114         const char *options = "-ad:P:uvshVRL:STFl:t:mn:p:c:";
00115         static struct option long_options[] = {
00116                                                   { "clock-source", 1, 0, 'c' },
00117                                                   { "driver", 1, 0, 'd' },
00118                                                   { "verbose", 0, 0, 'v' },
00119                                                   { "help", 0, 0, 'h' },
00120                                                   { "port-max", 1, 0, 'p' },
00121                                                   { "no-mlock", 0, 0, 'm' },
00122                                                   { "name", 0, 0, 'n' },
00123                                                   { "unlock", 0, 0, 'u' },
00124                                                   { "realtime", 0, 0, 'R' },
00125                                                   { "realtime-priority", 1, 0, 'P' },
00126                                                   { "timeout", 1, 0, 't' },
00127                                                   { "temporary", 0, 0, 'T' },
00128                                                   { "version", 0, 0, 'V' },
00129                                                   { "silent", 0, 0, 's' },
00130                                                   { "sync", 0, 0, 'S' },
00131                                                   { 0, 0, 0, 0 }
00132                                               };
00133 
00134         snprintf(filename, 255, "%s/.jackdrc", getenv("HOME"));
00135         fp = fopen(filename, "r");
00136 
00137         if (!fp) {
00138             fp = fopen("/etc/jackdrc", "r");
00139         }
00140         // if still not found, check old config name for backwards compatability
00141         if (!fp) {
00142             fp = fopen("/etc/jackd.conf", "r");
00143         }
00144 
00145         argc = 0;
00146         if (fp) {
00147             ret = fscanf(fp, "%s", buffer);
00148             while (ret != 0 && ret != EOF) {
00149                 argv[argc] = (char*)malloc(64);
00150                 strcpy(argv[argc], buffer);
00151                 ret = fscanf(fp, "%s", buffer);
00152                 argc++;
00153             }
00154             fclose(fp);
00155         }
00156 
00157         /*
00158         For testing
00159         int argc = 15;
00160         char* argv[] = {"jackdmp", "-R", "-v", "-d", "coreaudio", "-p", "512", "-d", "~:Aggregate:0", "-r", "48000", "-i", "2", "-o", "2" };
00161         */
00162 
00163         opterr = 0;
00164         optind = 1; // Important : to reset argv parsing
00165 
00166         while (!seen_driver &&
00167                 (opt = getopt_long(argc, argv, options, long_options, &option_index)) != EOF) {
00168 
00169             switch (opt) {
00170             
00171                 case 'c':
00172                     if (tolower (optarg[0]) == 'h') {
00173                         clock_source = JACK_TIMER_HPET;
00174                     } else if (tolower (optarg[0]) == 'c') {
00175                         clock_source = JACK_TIMER_CYCLE_COUNTER;
00176                     } else if (tolower (optarg[0]) == 's') {
00177                         clock_source = JACK_TIMER_SYSTEM_CLOCK;
00178                     } else {
00179                         jack_error("unknown option character %c", optopt);
00180                     }                
00181                     break;
00182 
00183                 case 'd':
00184                     seen_driver = 1;
00185                     driver_name = optarg;
00186                     break;
00187 
00188                 case 'v':
00189                     verbose_aux = 1;
00190                     break;
00191 
00192                 case 'S':
00193                     sync = 1;
00194                     break;
00195 
00196                 case 'n':
00197                     server_name = optarg;
00198                     break;
00199 
00200                 case 'm':
00201                     do_mlock = 0;
00202                     break;
00203 
00204                 case 'p':
00205                     port_max = (unsigned int)atol(optarg);
00206                     break;
00207 
00208                 case 'P':
00209                     realtime_priority = atoi(optarg);
00210                     break;
00211 
00212                 case 'R':
00213                     realtime = 1;
00214                     break;
00215 
00216                 case 'T':
00217                     temporary = 1;
00218                     break;
00219 
00220                 case 't':
00221                     client_timeout = atoi(optarg);
00222                     break;
00223 
00224                 case 'u':
00225                     do_unlock = 1;
00226                     break;
00227 
00228                 case 'V':
00229                     show_version = 1;
00230                     break;
00231 
00232                 default:
00233                     jack_error("unknown option character %c", optopt);
00234                     break;
00235             }
00236         }
00237 
00238         drivers = jack_drivers_load(drivers);
00239         if (!drivers) {
00240             jack_error("jackdmp: no drivers found; exiting");
00241             goto error;
00242         }
00243 
00244         driver_desc = jack_find_driver_descriptor(drivers, driver_name);
00245         if (!driver_desc) {
00246             jack_error("jackdmp: unknown driver '%s'", driver_name);
00247             goto error;
00248         }
00249 
00250         if (optind < argc) {
00251             driver_nargs = 1 + argc - optind;
00252         } else {
00253             driver_nargs = 1;
00254         }
00255 
00256         if (driver_nargs == 0) {
00257             jack_error("No driver specified ... hmm. JACK won't do"
00258                        " anything when run like this.");
00259             goto error;
00260         }
00261 
00262         driver_args = (char**)malloc(sizeof(char*) * driver_nargs);
00263         driver_args[0] = driver_name;
00264 
00265         for (i = 1; i < driver_nargs; i++) {
00266             driver_args[i] = argv[optind++];
00267         }
00268 
00269         if (jack_parse_driver_params(driver_desc, driver_nargs, driver_args, &driver_params)) {
00270             goto error;
00271         }
00272 
00273 #ifndef WIN32
00274         if (server_name == NULL)
00275             server_name = (char*)JackTools::DefaultServerName();
00276 #endif
00277 
00278         rc = jack_register_server(server_name, false);
00279         switch (rc) {
00280             case EEXIST:
00281                 jack_error("`%s' server already active", server_name);
00282                 goto error;
00283             case ENOSPC:
00284                 jack_error("too many servers already active");
00285                 goto error;
00286             case ENOMEM:
00287                 jack_error("no access to shm registry");
00288                 goto error;
00289             default:
00290                 jack_info("server `%s' registered", server_name);
00291         }
00292 
00293         /* clean up shared memory and files from any previous instance of this server name */
00294         jack_cleanup_shm();
00295         JackTools::CleanupFiles(server_name);
00296 
00297         if (!realtime && client_timeout == 0)
00298             client_timeout = 500; /* 0.5 sec; usable when non realtime. */
00299 
00300         for (i = 0; i < argc; i++) {
00301             free(argv[i]);
00302         }
00303 
00304         int res = Start(server_name, driver_desc, driver_params, sync, temporary, client_timeout, realtime, realtime_priority, port_max, verbose_aux, clock_source);
00305         if (res < 0) {
00306             jack_error("Cannot start server... exit");
00307             Delete();
00308             jack_cleanup_shm();
00309             JackTools::CleanupFiles(server_name);
00310             jack_unregister_server(server_name);
00311             goto error;
00312         }
00313     }
00314 
00315     if (driver_params)
00316         jack_free_driver_params(driver_params);
00317     return true;
00318 
00319 error:
00320     if (driver_params)
00321         jack_free_driver_params(driver_params);
00322     fUserCount--;
00323     return false;
00324 }
00325 
00326 void JackServerGlobals::Destroy()
00327 {
00328     if (--fUserCount == 0) {
00329         jack_log("JackServerGlobals Destroy");
00330         Stop();
00331         Delete();
00332         jack_cleanup_shm();
00333         JackTools::CleanupFiles(server_name);
00334         jack_unregister_server(server_name);
00335     }
00336 }
00337 
00338 } // end of namespace
00339 
00340 

Generated for Jack2 by doxygen 1.7.3