Jack2 1.9.6
|
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