JackdmpWIN32.cpp

00001 /*
00002 Copyright (C) 2001 Paul Davis 
00003 Copyright (C) 2004-2006 Grame
00004 
00005 This program is free software; you can redistribute it and/or modify
00006 it under the terms of the GNU General Public License as published by
00007 the Free Software Foundation; either version 2 of the License, or
00008 (at your option) any later version.
00009 
00010 This program is distributed in the hope that it will be useful,
00011 but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 GNU General Public License for more details.
00014 
00015 You should have received a copy of the GNU General Public License
00016 along with this program; if not, write to the Free Software
00017 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00018 
00019 */
00020 
00021 #include <iostream>
00022 #include <assert.h>
00023 #include <process.h>
00024 #include <getopt.h>
00025 #include <signal.h>
00026 
00027 #include "JackServer.h"
00028 #include "JackConstants.h" 
00029 #include "driver_interface.h"
00030 #include "JackDriverLoader.h"
00031 #include "shm.h"
00032 
00033 using namespace Jack;
00034 
00035 static JackServer* fServer;
00036 static char *server_name = "default";
00037 static int realtime_priority = 10;
00038 static int do_mlock = 1;
00039 static unsigned int port_max = 128;
00040 static int realtime = 0;
00041 static int loopback = 0;
00042 static int temporary = 0;
00043 static int client_timeout = 0; /* msecs; if zero, use period size. */
00044 static int do_unlock = 0;
00045 static JSList* drivers = NULL;
00046 static int sync = 0;
00047 static int xverbose = 0;
00048 
00049 #define DEFAULT_TMP_DIR "/tmp"
00050 char *jack_tmpdir = DEFAULT_TMP_DIR;
00051 
00052 HANDLE waitEvent;
00053 
00054 void jack_print_driver_options (jack_driver_desc_t * desc, FILE *file);
00055 void jack_print_driver_param_usage (jack_driver_desc_t * desc, unsigned long param, FILE *file);
00056 int jack_parse_driver_params (jack_driver_desc_t * desc, int argc, char* argv[], JSList ** param_ptr);
00057 static void silent_jack_error_callback (const char *desc)
00058 {}
00059 
00060 static void copyright(FILE* file)
00061 {
00062     fprintf (file, "jackdmp " VERSION "\n"
00063              "Copyright 2001-2005 Paul Davis and others.\n"
00064              "Copyright 2004-2006 Grame.\n"
00065              "jackdmp comes with ABSOLUTELY NO WARRANTY\n"
00066              "This is free software, and you are welcome to redistribute it\n"
00067              "under certain conditions; see the file COPYING for details\n");
00068 }
00069 
00070 static void usage (FILE *file)
00071 {
00072     copyright (file);
00073     fprintf (file, "\n"
00074              "usage: jackdmp [ --realtime OR -R [ --realtime-priority OR -P priority ] ]\n"
00075              "               [ --name OR -n server-name ]\n"
00076              // "               [ --no-mlock OR -m ]\n"
00077              // "               [ --unlock OR -u ]\n"
00078              "               [ --timeout OR -t client-timeout-in-msecs ]\n"
00079              "               [ --loopback OR -L loopback-port-number ]\n"
00080              // "               [ --port-max OR -p maximum-number-of-ports]\n"
00081              "               [ --verbose OR -v ]\n"
00082              "               [ --silent OR -s ]\n"
00083              "               [ --sync OR -S ]\n"
00084              "               [ --version OR -V ]\n"
00085              "         -d driver [ ... driver args ... ]\n"
00086              "             where driver can be `alsa', `coreaudio', 'portaudio' or `dummy'\n"
00087              "       jackdmp -d driver --help\n"
00088              "             to display options for each driver\n\n");
00089 }
00090 
00091 static int JackStart(jack_driver_desc_t* driver_desc, JSList* driver_params, int sync, int time_out_ms, int rt, int priority, int loopback, int verbose)
00092 {
00093     printf("Jackdmp: sync = %ld timeout = %ld rt = %ld priority = %ld verbose = %ld \n", sync, time_out_ms, rt, priority, verbose);
00094     fServer = new JackServer(sync, time_out_ms, rt, priority, loopback, verbose);
00095     int res = fServer->Open(driver_desc, driver_params);
00096     return (res < 0) ? res : fServer->Start();
00097 }
00098 
00099 static int JackStop()
00100 {
00101     fServer->Stop();
00102     fServer->Close();
00103     printf("Jackdmp: server close\n");
00104     delete fServer;
00105     printf("Jackdmp: delete server\n");
00106     return 0;
00107 }
00108 
00109 static int JackDelete()
00110 {
00111     delete fServer;
00112     printf("Jackdmp: delete server\n");
00113     return 0;
00114 }
00115 
00116 static void intrpt(int signum)
00117 {
00118     printf("jack main caught signal %d\n", signum);
00119     (void) signal(SIGINT, SIG_DFL);
00120         SetEvent(waitEvent);
00121 }
00122 
00123 /*
00124 static char* jack_default_server_name(void)
00125 {
00126         char *server_name;
00127         if ((server_name = getenv("JACK_DEFAULT_SERVER")) == NULL)
00128                 server_name = "default";
00129         return server_name;
00130 }
00131  
00132 // returns the name of the per-user subdirectory of jack_tmpdir 
00133 static char* jack_user_dir(void)
00134 {
00135         static char user_dir[PATH_MAX] = "";
00136  
00137         // format the path name on the first call 
00138         if (user_dir[0] == '\0') {
00139                 snprintf (user_dir, sizeof (user_dir), "%s/jack-%d",
00140                           jack_tmpdir, _getuid ());
00141         }
00142  
00143         return user_dir;
00144 }
00145  
00146 // returns the name of the per-server subdirectory of jack_user_dir() 
00147  
00148 static char* get_jack_server_dir(const char * toto)
00149 {
00150         static char server_dir[PATH_MAX] = "";
00151  
00152         // format the path name on the first call 
00153         if (server_dir[0] == '\0') {
00154                 snprintf (server_dir, sizeof (server_dir), "%s/%s",
00155                           jack_user_dir (), server_name);
00156         }
00157  
00158         return server_dir;
00159 }
00160  
00161 static void jack_cleanup_files (const char *server_name)
00162 {
00163         DIR *dir;
00164         struct dirent *dirent;
00165         char *dir_name = get_jack_server_dir (server_name);
00166  
00167         // nothing to do if the server directory does not exist 
00168         if ((dir = opendir (dir_name)) == NULL) {
00169                 return;
00170         }
00171  
00172         // unlink all the files in this directory, they are mine 
00173         while ((dirent = readdir (dir)) != NULL) {
00174  
00175                 char fullpath[PATH_MAX];
00176  
00177                 if ((strcmp (dirent->d_name, ".") == 0)
00178                     || (strcmp (dirent->d_name, "..") == 0)) {
00179                         continue;
00180                 }
00181  
00182                 snprintf (fullpath, sizeof (fullpath), "%s/%s",
00183                           dir_name, dirent->d_name);
00184  
00185                 if (unlink (fullpath)) {
00186                         jack_error ("cannot unlink `%s' (%s)", fullpath,
00187                                     strerror (errno));
00188                 }
00189         } 
00190  
00191         closedir (dir);
00192  
00193         // now, delete the per-server subdirectory, itself 
00194         if (rmdir (dir_name)) {
00195                 jack_error ("cannot remove `%s' (%s)", dir_name,
00196                             strerror (errno));
00197         }
00198  
00199         // finally, delete the per-user subdirectory, if empty 
00200         if (rmdir (jack_user_dir ())) {
00201                 if (errno != ENOTEMPTY) {
00202                         jack_error ("cannot remove `%s' (%s)",
00203                                     jack_user_dir (), strerror (errno));
00204                 }
00205         }
00206 }
00207 */
00208 
00209 /*
00210 BOOL CtrlHandler( DWORD fdwCtrlType ) 
00211 { 
00212   switch( fdwCtrlType ) 
00213   { 
00214     // Handle the CTRL-C signal. 
00215     case CTRL_C_EVENT: 
00216       printf( "Ctrl-C event\n\n" );
00217       Beep( 750, 300 ); 
00218           SetEvent(waitEvent);
00219       return( TRUE );
00220  
00221     // CTRL-CLOSE: confirm that the user wants to exit. 
00222     case CTRL_CLOSE_EVENT: 
00223       Beep( 600, 200 ); 
00224       printf( "Ctrl-Close event\n\n" );
00225           SetEvent(waitEvent);
00226       return( TRUE ); 
00227  
00228     // Pass other signals to the next handler. 
00229     case CTRL_BREAK_EVENT: 
00230       Beep( 900, 200 ); 
00231       printf( "Ctrl-Break event\n\n" );
00232       return FALSE; 
00233  
00234     case CTRL_LOGOFF_EVENT: 
00235       Beep( 1000, 200 ); 
00236       printf( "Ctrl-Logoff event\n\n" );
00237       return FALSE; 
00238  
00239     case CTRL_SHUTDOWN_EVENT: 
00240       Beep( 750, 500 ); 
00241       printf( "Ctrl-Shutdown event\n\n" );
00242       return FALSE; 
00243  
00244     default: 
00245       return FALSE; 
00246   } 
00247 } 
00248  
00249 */
00250 
00251 int main(int argc, char* argv[])
00252 {
00253     jack_driver_desc_t * driver_desc;
00254     const char *options = "-ad:P:uvshVRL:STFl:t:mn:p:";
00255     struct option long_options[] = {
00256                                        { "driver", 1, 0, 'd'
00257                                        },
00258                                        { "verbose", 0, 0, 'v' },
00259                                        { "help", 0, 0, 'h' },
00260                                        { "port-max", 1, 0, 'p' },
00261                                        { "no-mlock", 0, 0, 'm' },
00262                                        { "name", 0, 0, 'n' },
00263                                        { "unlock", 0, 0, 'u' },
00264                                        { "realtime", 0, 0, 'R' },
00265                                        { "loopback", 0, 0, 'L' },
00266                                        { "realtime-priority", 1, 0, 'P' },
00267                                        { "timeout", 1, 0, 't' },
00268                                        { "temporary", 0, 0, 'T' },
00269                                        { "version", 0, 0, 'V' },
00270                                        { "silent", 0, 0, 's' },
00271                                        { "sync", 0, 0, 'S' },
00272                                        { 0, 0, 0, 0 }
00273                                    };
00274     int opt = 0;
00275     int option_index = 0;
00276     int seen_driver = 0;
00277     char *driver_name = NULL;
00278     char **driver_args = NULL;
00279     JSList * driver_params;
00280     int driver_nargs = 1;
00281     int show_version = 0;
00282     int sync = 0;
00283     int i;
00284     int rc;
00285     char c;
00286 
00287         // Creates wait event
00288         if ((waitEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL) {
00289         printf("CreateEvent fails err = %ld\n", GetLastError());
00290         return 0;
00291     }
00292 
00293     opterr = 0;
00294     while (!seen_driver &&
00295             (opt = getopt_long(argc, argv, options,
00296                                long_options, &option_index)) != EOF) {
00297         switch (opt) {
00298 
00299             case 'd':
00300                 seen_driver = 1;
00301                 driver_name = optarg;
00302                 break;
00303 
00304             case 'v':
00305                 xverbose = 1;
00306                 break;
00307 
00308             case 's':
00309                 // steph
00310                 //jack_set_error_function(silent_jack_error_callback);
00311                 break;
00312 
00313             case 'S':
00314                 sync = 1;
00315                 break;
00316 
00317             case 'n':
00318                 server_name = optarg;
00319                 break;
00320 
00321             case 'm':
00322                 do_mlock = 0;
00323                 break;
00324 
00325             case 'p':
00326                 port_max = (unsigned int)atol(optarg);
00327                 break;
00328 
00329             case 'P':
00330                 realtime_priority = atoi(optarg);
00331                 break;
00332 
00333             case 'R':
00334                 realtime = 1;
00335                 break;
00336 
00337             case 'L':
00338                 loopback = atoi(optarg);
00339                 break;
00340 
00341             case 'T':
00342                 temporary = 1;
00343                 break;
00344 
00345             case 't':
00346                 client_timeout = atoi(optarg);
00347                 break;
00348 
00349             case 'u':
00350                 do_unlock = 1;
00351                 break;
00352 
00353             case 'V':
00354                 show_version = 1;
00355                 break;
00356 
00357             default:
00358                 fprintf(stderr, "unknown option character %c\n",
00359                         optopt);
00360                 /*fallthru*/
00361             case 'h':
00362                 usage(stdout);
00363                 return -1;
00364         }
00365     }
00366 
00367     if (!seen_driver) {
00368         usage (stderr);
00369         //exit (1);
00370                 return 0;
00371     }
00372 
00373     drivers = jack_drivers_load (drivers);
00374     if (!drivers) {
00375         fprintf (stderr, "jackdmp: no drivers found; exiting\n");
00376         //exit (1);
00377                 return 0;
00378     }
00379 
00380     driver_desc = jack_find_driver_descriptor (drivers, driver_name);
00381     if (!driver_desc) {
00382         fprintf (stderr, "jackdmp: unknown driver '%s'\n", driver_name);
00383         //exit (1);
00384                 return 0;
00385     }
00386 
00387     if (optind < argc) {
00388         driver_nargs = 1 + argc - optind;
00389     } else {
00390         driver_nargs = 1;
00391     }
00392 
00393     if (driver_nargs == 0) {
00394         fprintf (stderr, "No driver specified ... hmm. JACK won't do"
00395                  " anything when run like this.\n");
00396         return -1;
00397     }
00398 
00399     driver_args = (char **) malloc (sizeof (char *) * driver_nargs);
00400     driver_args[0] = driver_name;
00401 
00402     for (i = 1; i < driver_nargs; i++) {
00403         driver_args[i] = argv[optind++];
00404     }
00405 
00406     if (jack_parse_driver_params (driver_desc, driver_nargs,
00407                                   driver_args, &driver_params)) {
00408        // exit (0);
00409                 return 0;
00410     }
00411 
00412     //if (server_name == NULL)
00413     //  server_name = jack_default_server_name ();
00414 
00415     copyright (stdout);
00416 
00417     rc = jack_register_server (server_name);
00418     switch (rc) {
00419         case EEXIST:
00420             fprintf (stderr, "`%s' server already active\n", server_name);
00421             //exit (1);
00422                         return 0;
00423         case ENOSPC:
00424             fprintf (stderr, "too many servers already active\n");
00425             //exit (2);
00426                         return 0;
00427         case ENOMEM:
00428             fprintf (stderr, "no access to shm registry\n");
00429             //exit (3);
00430                         return 0;
00431         default:
00432             if (xverbose)
00433                 fprintf (stderr, "server `%s' registered\n",
00434                          server_name);
00435     }
00436 
00437 
00438     /* clean up shared memory and files from any previous
00439      * instance of this server name */
00440     jack_cleanup_shm();
00441     //  jack_cleanup_files(server_name);
00442 
00443     if (!realtime && client_timeout == 0)
00444         client_timeout = 500; /* 0.5 sec; usable when non realtime. */
00445 
00446     int res = JackStart(driver_desc, driver_params, sync, client_timeout, realtime, realtime_priority, loopback, xverbose);
00447     if (res < 0) {
00448         printf("Cannot start server... exit\n");
00449         JackDelete();
00450         return 0;
00451     }
00452 
00453         /*
00454         if( SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE ) ) 
00455         { 
00456                 printf( "\nThe Control Handler is installed.\n" ); 
00457         } else {
00458                 printf( "\nERROR: Could not set control handler"); 
00459         }
00460         */
00461         
00462         
00463         (void) signal(SIGINT, intrpt);
00464         (void) signal(SIGABRT, intrpt);
00465         (void) signal(SIGTERM, intrpt);
00466 
00467         if ((res = WaitForSingleObject(waitEvent, INFINITE)) != WAIT_OBJECT_0) {
00468         printf("WaitForSingleObject fails err = %ld\n", GetLastError());
00469     }
00470         
00471         /*
00472     printf("Type 'q' to quit\n");
00473     while ((c = getchar()) != 'q') {}
00474         */
00475         
00476 
00477     JackStop();
00478 
00479     jack_cleanup_shm();
00480     //  jack_cleanup_files(server_name);
00481     jack_unregister_server(server_name);
00482 
00483         CloseHandle(waitEvent);
00484     return 1;
00485 }
00486 
00487 

Generated on Wed Jan 10 11:42:44 2007 for Jackdmp by  doxygen 1.4.5