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-2008 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                          "               [ --replace-registry OR -r ]\n"
00083              "               [ --silent OR -s ]\n"
00084              "               [ --sync OR -S ]\n"
00085              "               [ --version OR -V ]\n"
00086              "         -d driver [ ... driver args ... ]\n"
00087              "             where driver can be `alsa', `coreaudio', 'portaudio' or `dummy'\n"
00088              "       jackdmp -d driver --help\n"
00089              "             to display options for each driver\n\n");
00090 }
00091 
00092 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, const char* server_name)
00093 {
00094     printf("Jackdmp: sync = %ld timeout = %ld rt = %ld priority = %ld verbose = %ld \n", sync, time_out_ms, rt, priority, verbose);
00095     fServer = new JackServer(sync, temporary, time_out_ms, rt, priority, loopback, verbose, server_name);
00096     int res = fServer->Open(driver_desc, driver_params);
00097     return (res < 0) ? res : fServer->Start();
00098 }
00099 
00100 static int JackStop()
00101 {
00102     fServer->Stop();
00103     fServer->Close();
00104     printf("Jackdmp: server close\n");
00105     delete fServer;
00106     printf("Jackdmp: delete server\n");
00107     return 0;
00108 }
00109 
00110 static int JackDelete()
00111 {
00112     delete fServer;
00113     printf("Jackdmp: delete server\n");
00114     return 0;
00115 }
00116 
00117 static void intrpt(int signum)
00118 {
00119     printf("jack main caught signal %d\n", signum);
00120     (void) signal(SIGINT, SIG_DFL);
00121         SetEvent(waitEvent);
00122 }
00123 
00124 /*
00125 static char* jack_default_server_name(void)
00126 {
00127         char *server_name;
00128         if ((server_name = getenv("JACK_DEFAULT_SERVER")) == NULL)
00129                 server_name = "default";
00130         return server_name;
00131 }
00132  
00133 // returns the name of the per-user subdirectory of jack_tmpdir 
00134 static char* jack_user_dir(void)
00135 {
00136         static char user_dir[PATH_MAX] = "";
00137  
00138         // format the path name on the first call 
00139         if (user_dir[0] == '\0') {
00140                 snprintf (user_dir, sizeof (user_dir), "%s/jack-%d",
00141                           jack_tmpdir, _getuid ());
00142         }
00143  
00144         return user_dir;
00145 }
00146  
00147 // returns the name of the per-server subdirectory of jack_user_dir() 
00148  
00149 static char* get_jack_server_dir(const char * toto)
00150 {
00151         static char server_dir[PATH_MAX] = "";
00152  
00153         // format the path name on the first call 
00154         if (server_dir[0] == '\0') {
00155                 snprintf (server_dir, sizeof (server_dir), "%s/%s",
00156                           jack_user_dir (), server_name);
00157         }
00158  
00159         return server_dir;
00160 }
00161  
00162 static void jack_cleanup_files (const char *server_name)
00163 {
00164         DIR *dir;
00165         struct dirent *dirent;
00166         char *dir_name = get_jack_server_dir (server_name);
00167  
00168         // nothing to do if the server directory does not exist 
00169         if ((dir = opendir (dir_name)) == NULL) {
00170                 return;
00171         }
00172  
00173         // unlink all the files in this directory, they are mine 
00174         while ((dirent = readdir (dir)) != NULL) {
00175  
00176                 char fullpath[PATH_MAX];
00177  
00178                 if ((strcmp (dirent->d_name, ".") == 0)
00179                     || (strcmp (dirent->d_name, "..") == 0)) {
00180                         continue;
00181                 }
00182  
00183                 snprintf (fullpath, sizeof (fullpath), "%s/%s",
00184                           dir_name, dirent->d_name);
00185  
00186                 if (unlink (fullpath)) {
00187                         jack_error ("cannot unlink `%s' (%s)", fullpath,
00188                                     strerror (errno));
00189                 }
00190         } 
00191  
00192         closedir (dir);
00193  
00194         // now, delete the per-server subdirectory, itself 
00195         if (rmdir (dir_name)) {
00196                 jack_error ("cannot remove `%s' (%s)", dir_name,
00197                             strerror (errno));
00198         }
00199  
00200         // finally, delete the per-user subdirectory, if empty 
00201         if (rmdir (jack_user_dir ())) {
00202                 if (errno != ENOTEMPTY) {
00203                         jack_error ("cannot remove `%s' (%s)",
00204                                     jack_user_dir (), strerror (errno));
00205                 }
00206         }
00207 }
00208 */
00209 
00210 /*
00211 BOOL CtrlHandler( DWORD fdwCtrlType ) 
00212 { 
00213   switch( fdwCtrlType ) 
00214   { 
00215     // Handle the CTRL-C signal. 
00216     case CTRL_C_EVENT: 
00217       printf( "Ctrl-C event\n\n" );
00218       Beep( 750, 300 ); 
00219           SetEvent(waitEvent);
00220       return( TRUE );
00221  
00222     // CTRL-CLOSE: confirm that the user wants to exit. 
00223     case CTRL_CLOSE_EVENT: 
00224       Beep( 600, 200 ); 
00225       printf( "Ctrl-Close event\n\n" );
00226           SetEvent(waitEvent);
00227       return( TRUE ); 
00228  
00229     // Pass other signals to the next handler. 
00230     case CTRL_BREAK_EVENT: 
00231       Beep( 900, 200 ); 
00232       printf( "Ctrl-Break event\n\n" );
00233       return FALSE; 
00234  
00235     case CTRL_LOGOFF_EVENT: 
00236       Beep( 1000, 200 ); 
00237       printf( "Ctrl-Logoff event\n\n" );
00238       return FALSE; 
00239  
00240     case CTRL_SHUTDOWN_EVENT: 
00241       Beep( 750, 500 ); 
00242       printf( "Ctrl-Shutdown event\n\n" );
00243       return FALSE; 
00244  
00245     default: 
00246       return FALSE; 
00247   } 
00248 } 
00249  
00250 */
00251 
00252 int main(int argc, char* argv[])
00253 {
00254     jack_driver_desc_t * driver_desc;
00255     const char *options = "-ad:P:uvshVRL:STFl:t:mn:p:";
00256     struct option long_options[] = {
00257                                        { "driver", 1, 0, 'd'
00258                                        },
00259                                        { "verbose", 0, 0, 'v' },
00260                                        { "help", 0, 0, 'h' },
00261                                        { "port-max", 1, 0, 'p' },
00262                                        { "no-mlock", 0, 0, 'm' },
00263                                        { "name", 0, 0, 'n' },
00264                                        { "unlock", 0, 0, 'u' },
00265                                        { "realtime", 0, 0, 'R' },
00266                                                                            { "replace-registry", 0, 0, 'r' },
00267                                        { "loopback", 0, 0, 'L' },
00268                                        { "realtime-priority", 1, 0, 'P' },
00269                                        { "timeout", 1, 0, 't' },
00270                                        { "temporary", 0, 0, 'T' },
00271                                        { "version", 0, 0, 'V' },
00272                                        { "silent", 0, 0, 's' },
00273                                        { "sync", 0, 0, 'S' },
00274                                        { 0, 0, 0, 0 }
00275                                    };
00276     int opt = 0;
00277     int option_index = 0;
00278     int seen_driver = 0;
00279     char *driver_name = NULL;
00280     char **driver_args = NULL;
00281     JSList * driver_params;
00282     int driver_nargs = 1;
00283     int show_version = 0;
00284         int replace_registry = 0;
00285     int sync = 0;
00286     int i;
00287     int rc;
00288     char c;
00289 
00290         // Creates wait event
00291         if ((waitEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL) {
00292         printf("CreateEvent fails err = %ld\n", GetLastError());
00293         return 0;
00294     }
00295 
00296     opterr = 0;
00297     while (!seen_driver &&
00298             (opt = getopt_long(argc, argv, options,
00299                                long_options, &option_index)) != EOF) {
00300         switch (opt) {
00301 
00302             case 'd':
00303                 seen_driver = 1;
00304                 driver_name = optarg;
00305                 break;
00306 
00307             case 'v':
00308                 xverbose = 1;
00309                 break;
00310 
00311             case 's':
00312                 // steph
00313                 //jack_set_error_function(silent_jack_error_callback);
00314                 break;
00315 
00316             case 'S':
00317                 sync = 1;
00318                 break;
00319 
00320             case 'n':
00321                 server_name = optarg;
00322                 break;
00323 
00324             case 'm':
00325                 do_mlock = 0;
00326                 break;
00327 
00328             case 'p':
00329                 port_max = (unsigned int)atol(optarg);
00330                 break;
00331 
00332             case 'P':
00333                 realtime_priority = atoi(optarg);
00334                 break;
00335                                 
00336                         case 'r':
00337                                 replace_registry = 1;
00338                                 break;
00339 
00340             case 'R':
00341                 realtime = 1;
00342                 break;
00343 
00344             case 'L':
00345                 loopback = atoi(optarg);
00346                 break;
00347 
00348             case 'T':
00349                 temporary = 1;
00350                 break;
00351 
00352             case 't':
00353                 client_timeout = atoi(optarg);
00354                 break;
00355 
00356             case 'u':
00357                 do_unlock = 1;
00358                 break;
00359 
00360             case 'V':
00361                 show_version = 1;
00362                 break;
00363 
00364             default:
00365                 fprintf(stderr, "unknown option character %c\n",
00366                         optopt);
00367                 /*fallthru*/
00368             case 'h':
00369                 usage(stdout);
00370                 return -1;
00371         }
00372     }
00373 
00374     if (!seen_driver) {
00375         usage (stderr);
00376         //exit (1);
00377                 return 0;
00378     }
00379 
00380     drivers = jack_drivers_load (drivers);
00381     if (!drivers) {
00382         fprintf (stderr, "jackdmp: no drivers found; exiting\n");
00383         //exit (1);
00384                 return 0;
00385     }
00386 
00387     driver_desc = jack_find_driver_descriptor (drivers, driver_name);
00388     if (!driver_desc) {
00389         fprintf (stderr, "jackdmp: unknown driver '%s'\n", driver_name);
00390         //exit (1);
00391                 return 0;
00392     }
00393 
00394     if (optind < argc) {
00395         driver_nargs = 1 + argc - optind;
00396     } else {
00397         driver_nargs = 1;
00398     }
00399 
00400     if (driver_nargs == 0) {
00401         fprintf (stderr, "No driver specified ... hmm. JACK won't do"
00402                  " anything when run like this.\n");
00403         return -1;
00404     }
00405 
00406     driver_args = (char **) malloc (sizeof (char *) * driver_nargs);
00407     driver_args[0] = driver_name;
00408 
00409     for (i = 1; i < driver_nargs; i++) {
00410         driver_args[i] = argv[optind++];
00411     }
00412 
00413     if (jack_parse_driver_params (driver_desc, driver_nargs,
00414                                   driver_args, &driver_params)) {
00415        // exit (0);
00416                 return 0;
00417     }
00418 
00419     //if (server_name == NULL)
00420     //  server_name = jack_default_server_name ();
00421 
00422     copyright (stdout);
00423 
00424     rc = jack_register_server (server_name, replace_registry);
00425     switch (rc) {
00426         case EEXIST:
00427             fprintf (stderr, "`%s' server already active\n", server_name);
00428             //exit (1);
00429                         return 0;
00430         case ENOSPC:
00431             fprintf (stderr, "too many servers already active\n");
00432             //exit (2);
00433                         return 0;
00434         case ENOMEM:
00435             fprintf (stderr, "no access to shm registry\n");
00436             //exit (3);
00437                         return 0;
00438         default:
00439             if (xverbose)
00440                 fprintf (stderr, "server `%s' registered\n",
00441                          server_name);
00442     }
00443 
00444 
00445     /* clean up shared memory and files from any previous
00446      * instance of this server name */
00447     jack_cleanup_shm();
00448     //  jack_cleanup_files(server_name);
00449 
00450     if (!realtime && client_timeout == 0)
00451         client_timeout = 500; /* 0.5 sec; usable when non realtime. */
00452 
00453     int res = JackStart(driver_desc, driver_params, sync, client_timeout, realtime, realtime_priority, loopback, xverbose, server_name);
00454     if (res < 0) {
00455         printf("Cannot start server... exit\n");
00456         JackDelete();
00457         return 0;
00458     }
00459 
00460         /*
00461         if( SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE ) ) 
00462         { 
00463                 printf( "\nThe Control Handler is installed.\n" ); 
00464         } else {
00465                 printf( "\nERROR: Could not set control handler"); 
00466         }
00467         */
00468         
00469         
00470         (void) signal(SIGINT, intrpt);
00471         (void) signal(SIGABRT, intrpt);
00472         (void) signal(SIGTERM, intrpt);
00473 
00474         if ((res = WaitForSingleObject(waitEvent, INFINITE)) != WAIT_OBJECT_0) {
00475         printf("WaitForSingleObject fails err = %ld\n", GetLastError());
00476     }
00477         
00478         /*
00479     printf("Type 'q' to quit\n");
00480     while ((c = getchar()) != 'q') {}
00481         */
00482         
00483 
00484     JackStop();
00485 
00486     jack_cleanup_shm();
00487     //  jack_cleanup_files(server_name);
00488     jack_unregister_server(server_name);
00489 
00490         CloseHandle(waitEvent);
00491     return 1;
00492 }
00493 
00494 

Generated on Thu Feb 14 11:16:01 2008 for Jackdmp by  doxygen 1.5.1