void JackServerGlobals::Destroy()
{
    if (--fUserCount == 0) {
        jack_log("JackServerGlobals Destroy");
        Stop();
        Delete();
        jack_cleanup_shm();
        JackTools::CleanupFiles(server_name);
        jack_unregister_server(server_name);
    }
}
Beispiel #2
0
bool jackctl_server_stop(jackctl_server_t *server_ptr)
{
	//jack_engine_driver_exit (server_ptr->engine);
	jack_engine_delete (server_ptr->engine);

    /* clean up shared memory and files from this server instance */
    //jack_log("cleaning up shared memory");

    jack_cleanup_shm();

    //jack_log("cleaning up files");

    jack_cleanup_files (server_ptr->name.str);

    //jack_log("unregistering server `%s'", server_ptr->name.str);

    jack_unregister_server(server_ptr->name.str);

    server_ptr->engine = NULL;

    return true;
}
Beispiel #3
0
bool
jackctl_server_start(
    jackctl_server_t *server_ptr,
    jackctl_driver_t *driver_ptr)
{
    int rc;
    sigset_t oldsignals;


    // TODO:
    int frame_time_offset = 0;

    rc = jack_register_server (server_ptr->name.str, server_ptr->replace_registry.b);
    switch (rc)
    {
    case EEXIST:
        jack_error("`%s' server already active", server_ptr->name.str);
        goto fail;
    case ENOSPC:
        jack_error("too many servers already active");
        goto fail;
    case ENOMEM:
        jack_error("no access to shm registry");
        goto fail;
    }

    //jack_log("server `%s' registered", server_ptr->name.str);

    /* clean up shared memory and files from any previous
     * instance of this server name */
    jack_cleanup_shm ();
    jack_cleanup_files (server_ptr->name.str);

    if (!server_ptr->realtime.b && server_ptr->client_timeout.i == 0)
        server_ptr->client_timeout.i = 500; /* 0.5 sec; usable when non realtime. */
    
    oldsignals = jackctl_block_signals();

    if ((server_ptr->engine = jack_engine_new (server_ptr->realtime.b, server_ptr->realtime_priority.i, 
				    server_ptr->do_mlock.b, server_ptr->do_unlock.b, server_ptr->name.str,
				    server_ptr->temporary.b, server_ptr->verbose.b, server_ptr->client_timeout.i,
				    server_ptr->port_max.i, getpid(), frame_time_offset, 
				    server_ptr->nozombies.b, server_ptr->timothres.ui, drivers)) == 0) {
	    jack_error ("cannot create engine");
	    goto fail_unregister;
    }

    if (jack_engine_load_driver (server_ptr->engine, driver_ptr->desc_ptr, driver_ptr->set_parameters))
    {
		jack_error ("cannot load driver module %s", driver_ptr->desc_ptr->name);
		goto fail_delete;
    }

    if (server_ptr->engine->driver->start (server_ptr->engine->driver) != 0) {
	    jack_error ("cannot start driver");
	    goto fail_close;
    }

    jackctl_unblock_signals( oldsignals );
    return true;

fail_close:

fail_delete:
    jack_engine_delete (server_ptr->engine);
    server_ptr->engine = NULL;

fail_unregister:
    //jack_log("cleaning up shared memory");

    jack_cleanup_shm();

    //jack_log("cleaning up files");

    jack_cleanup_files(server_ptr->name.str);

    //jack_log("unregistering server `%s'", server_ptr->name.str);

    jack_unregister_server(server_ptr->name.str);
    jackctl_unblock_signals( oldsignals );

fail:
    return false;
}
bool JackServerGlobals::Init()
{
    int realtime = 0;
    int client_timeout = 0; /* msecs; if zero, use period size. */
    int realtime_priority = 10;
    int verbose_aux = 0;
    int do_mlock = 1;
    unsigned int port_max = 128;
    int do_unlock = 0;
    int temporary = 0;

    int opt = 0;
    int option_index = 0;
    char *master_driver_name = NULL;
    char **master_driver_args = NULL;
    JSList* master_driver_params = NULL;
    jack_driver_desc_t* driver_desc;
    jack_timer_type_t clock_source = JACK_TIMER_SYSTEM_CLOCK;
    int driver_nargs = 1;
    JSList* drivers = NULL;
    int loopback = 0;
    int sync = 0;
    int rc, i;
    int ret;
    int replace_registry = 0;

    FILE* fp = 0;
    char filename[255];
    char buffer[255];
    int argc = 0;
    char* argv[32];

    // First user starts the server
    if (fUserCount++ == 0) {

        jack_log("JackServerGlobals Init");

        const char *options = "-d:X:I:P:uvshVrRL:STFl:t:mn:p:"
    #ifdef __linux__
            "c:"
    #endif
        ;

    struct option long_options[] = {
    #ifdef __linux__
                                       { "clock-source", 1, 0, 'c' },
    #endif
                                       { "loopback-driver", 1, 0, 'L' },
                                       { "audio-driver", 1, 0, 'd' },
                                       { "midi-driver", 1, 0, 'X' },
                                       { "internal-client", 1, 0, 'I' },
                                       { "verbose", 0, 0, 'v' },
                                       { "help", 0, 0, 'h' },
                                       { "port-max", 1, 0, 'p' },
                                       { "no-mlock", 0, 0, 'm' },
                                       { "name", 1, 0, 'n' },
                                       { "unlock", 0, 0, 'u' },
                                       { "realtime", 0, 0, 'R' },
                                       { "no-realtime", 0, 0, 'r' },
                                       { "replace-registry", 0, &replace_registry, 0 },
                                       { "loopback", 0, 0, 'L' },
                                       { "realtime-priority", 1, 0, 'P' },
                                       { "timeout", 1, 0, 't' },
                                       { "temporary", 0, 0, 'T' },
                                       { "version", 0, 0, 'V' },
                                       { "silent", 0, 0, 's' },
                                       { "sync", 0, 0, 'S' },
                                       { 0, 0, 0, 0 }
                                   };

        snprintf(filename, 255, "%s/.jackdrc", getenv("HOME"));
        fp = fopen(filename, "r");

        if (!fp) {
            fp = fopen("/etc/jackdrc", "r");
        }
        // if still not found, check old config name for backwards compatability
        if (!fp) {
            fp = fopen("/etc/jackd.conf", "r");
        }

        argc = 0;
        if (fp) {
            ret = fscanf(fp, "%s", buffer);
            while (ret != 0 && ret != EOF) {
                argv[argc] = (char*)malloc(64);
                strcpy(argv[argc], buffer);
                ret = fscanf(fp, "%s", buffer);
                argc++;
            }
            fclose(fp);
        }

        /*
        For testing
        int argc = 15;
        char* argv[] = {"jackdmp", "-R", "-v", "-d", "coreaudio", "-p", "512", "-d", "~:Aggregate:0", "-r", "48000", "-i", "2", "-o", "2" };
        */

        opterr = 0;
        optind = 1; // Important : to reset argv parsing

        while (!master_driver_name &&
                (opt = getopt_long(argc, argv, options, long_options, &option_index)) != EOF) {

            switch (opt) {

                case 'c':
                    if (tolower (optarg[0]) == 'h') {
                        clock_source = JACK_TIMER_HPET;
                    } else if (tolower (optarg[0]) == 'c') {
                        clock_source = JACK_TIMER_CYCLE_COUNTER;
                    } else if (tolower (optarg[0]) == 's') {
                        clock_source = JACK_TIMER_SYSTEM_CLOCK;
                    } else {
                        jack_error("unknown option character %c", optopt);
                    }
                    break;

                case 'd':
                    master_driver_name = optarg;
                    break;

                case 'L':
                    loopback = atoi(optarg);
                    break;

                 case 'X':
                    fSlavesList[optarg] = NULL;
                    break;

                case 'I':
                    fInternalsList[optarg] = -1;
                    break;

                case 'p':
                    port_max = (unsigned int)atol(optarg);
                    break;

                case 'm':
                    do_mlock = 0;
                    break;

                case 'u':
                    do_unlock = 1;
                    break;

                case 'v':
                    verbose_aux = 1;
                    break;

                case 'S':
                    sync = 1;
                    break;

                case 'n':
                    server_name = optarg;
                    break;

                case 'P':
                    realtime_priority = atoi(optarg);
                    break;

                case 'r':
                    realtime = 0;
                    break;

                case 'R':
                    realtime = 1;
                    break;

                case 'T':
                    temporary = 1;
                    break;

                case 't':
                    client_timeout = atoi(optarg);
                    break;

                default:
                    jack_error("unknown option character %c", optopt);
                    break;
            }
        }

        drivers = jack_drivers_load(drivers);
        if (!drivers) {
            jack_error("jackdmp: no drivers found; exiting");
            goto error;
        }

        driver_desc = jack_find_driver_descriptor(drivers, master_driver_name);
        if (!driver_desc) {
            jack_error("jackdmp: unknown master driver '%s'", master_driver_name);
            goto error;
        }

        if (optind < argc) {
            driver_nargs = 1 + argc - optind;
        } else {
            driver_nargs = 1;
        }

        if (driver_nargs == 0) {
            jack_error("No driver specified ... hmm. JACK won't do"
                       " anything when run like this.");
            goto error;
        }

        master_driver_args = (char**)malloc(sizeof(char*) * driver_nargs);
        master_driver_args[0] = master_driver_name;

        for (i = 1; i < driver_nargs; i++) {
            master_driver_args[i] = argv[optind++];
        }

        if (jack_parse_driver_params(driver_desc, driver_nargs, master_driver_args, &master_driver_params)) {
            goto error;
        }

#ifndef WIN32
        if (server_name == NULL)
            server_name = (char*)JackTools::DefaultServerName();
#endif

        rc = jack_register_server(server_name, false);
        switch (rc) {
            case EEXIST:
                jack_error("`%s' server already active", server_name);
                goto error;
            case ENOSPC:
                jack_error("too many servers already active");
                goto error;
            case ENOMEM:
                jack_error("no access to shm registry");
                goto error;
            default:
                jack_info("server `%s' registered", server_name);
        }

        /* clean up shared memory and files from any previous instance of this server name */
        jack_cleanup_shm();
        JackTools::CleanupFiles(server_name);

        if (!realtime && client_timeout == 0)
            client_timeout = 500; /* 0.5 sec; usable when non realtime. */

        for (i = 0; i < argc; i++) {
            free(argv[i]);
        }

        int res = Start(server_name, driver_desc, master_driver_params, sync, temporary, client_timeout, realtime, realtime_priority, port_max, verbose_aux, clock_source);
        if (res < 0) {
            jack_error("Cannot start server... exit");
            Delete();
            jack_cleanup_shm();
            JackTools::CleanupFiles(server_name);
            jack_unregister_server(server_name);
            goto error;
        }

        // Slave drivers
        std::map<std::string, JackDriverInfo*>::iterator it1;
        for (it1 = fSlavesList.begin(); it1 != fSlavesList.end(); it1++) {
            const char* name = ((*it1).first).c_str();
            driver_desc = jack_find_driver_descriptor(drivers, name);
            if (!driver_desc) {
                jack_error("jackdmp: unknown slave driver '%s'", name);
            } else {
                (*it1).second = fInstance->AddSlave(driver_desc, NULL);
            }
        }

        // Loopback driver
        if (loopback > 0) {
            driver_desc = jack_find_driver_descriptor(drivers, "loopback");
            if (!driver_desc) {
                jack_error("jackdmp: unknown driver '%s'", "loopback");
            } else {
                fSlavesList["loopback"] = fInstance->AddSlave(driver_desc, NULL);
            }
        }

        // Internal clients
        std::map<std::string, int>::iterator it2;
        for (it2 = fInternalsList.begin(); it2 != fInternalsList.end(); it2++) {
            int status, refnum;
            const char* name = ((*it2).first).c_str();
            fInstance->InternalClientLoad2(name, name, NULL, JackNullOption, &refnum, -1, &status);
            (*it2).second = refnum;
        }
    }

    if (master_driver_params)
        jack_free_driver_params(master_driver_params);
    return true;

error:
    jack_log("JackServerGlobals Init error");
    if (master_driver_params)
        jack_free_driver_params(master_driver_params);
    Destroy();
    return false;
}
Beispiel #5
0
int	       
main (int argc, char *argv[])

{
	jack_driver_desc_t * desc;
	int replace_registry = 0;
	int do_sanity_checks = 1;
	int show_version = 0;

#ifdef HAVE_ZITA_BRIDGE_DEPS
	const char *options = "A:d:P:uvshVrRZTFlI:t:mM:n:Np:c:X:C:";
#else
	const char *options = "A:d:P:uvshVrRZTFlI:t:mM:n:Np:c:X:C:";
#endif
	struct option long_options[] = 
	{ 
		/* keep ordered by single-letter option code */

#ifdef HAVE_ZITA_BRIDGE_DEPS
                { "alsa-add", 1, 0, 'A' },
#endif
		{ "clock-source", 1, 0, 'c' },
		{ "driver", 1, 0, 'd' },
		{ "help", 0, 0, 'h' },
		{ "tmpdir-location", 0, 0, 'l' },
		{ "internal-client", 0, 0, 'I' },
		{ "no-mlock", 0, 0, 'm' },
		{ "midi-bufsize", 1, 0, 'M' },
		{ "name", 1, 0, 'n' },
                { "no-sanity-checks", 0, 0, 'N' },
		{ "port-max", 1, 0, 'p' },
		{ "realtime-priority", 1, 0, 'P' },
		{ "no-realtime", 0, 0, 'r' },
		{ "realtime", 0, 0, 'R' },
		{ "replace-registry", 0, &replace_registry, 0 },
		{ "silent", 0, 0, 's' },
		{ "sync", 0, 0, 'S' },
		{ "timeout", 1, 0, 't' },
		{ "temporary", 0, 0, 'T' },
		{ "unlock", 0, 0, 'u' },
		{ "version", 0, 0, 'V' },
		{ "verbose", 0, 0, 'v' },
		{ "slave-driver", 1, 0, 'X' },
		{ "nozombies", 0, 0, 'Z' },
		{ "timeout-thres", 2, 0, 'C' },
		{ 0, 0, 0, 0 }
	};
	int opt = 0;
	int option_index = 0;
	int seen_driver = 0;
	char *driver_name = NULL;
	char **driver_args = NULL;
	JSList * driver_params;
	JSList * slave_drivers = NULL;
        JSList * load_list = NULL;
	size_t midi_buffer_size = 0;
	int driver_nargs = 1;
	int i;
	int rc;
#ifdef HAVE_ZITA_BRIDGE_DEPS
        const char* alsa_add_client_name_playback = "zalsa_out";
        const char* alsa_add_client_name_capture = "zalsa_in";
        char alsa_add_args[64];
        char* dirstr;
#endif
	setvbuf (stdout, NULL, _IOLBF, 0);

	maybe_use_capabilities ();

	opterr = 0;
	while (!seen_driver &&
	       (opt = getopt_long (argc, argv, options,
				   long_options, &option_index)) != EOF) {
		switch (opt) {

#ifdef HAVE_ZITA_BRIDGE_DEPS
                case 'A':
                        /* add a new internal client named after the ALSA device name
                           given as optarg, using the last character 'p' or 'c' to
                           indicate playback or capture. If there isn't one,
                           assume capture (common case: USB mics etc.)
                        */
                        if ((dirstr = strstr (optarg, "%p")) != NULL && dirstr == (optarg + strlen(optarg) - 2)) {
                                snprintf (alsa_add_args, sizeof (alsa_add_args), "%.*s_play:%s/-dhw:%.*s", 
                                          (int) strlen (optarg) - 2, optarg,
                                          alsa_add_client_name_playback,
                                          (int) strlen (optarg) - 2, optarg);
                                load_list = jack_slist_append(load_list, strdup (alsa_add_args));
                        } else if ((dirstr = strstr (optarg, "%c")) != NULL && dirstr == (optarg + strlen(optarg) - 2)) {
                                snprintf (alsa_add_args, sizeof (alsa_add_args), "%.*s_rec:%s/-dhw:%.*s", 
                                          (int) strlen (optarg) - 2, optarg,
                                          alsa_add_client_name_capture,
                                          (int) strlen (optarg) - 2, optarg);
                                load_list = jack_slist_append(load_list, strdup (alsa_add_args));
                        } else {
                                snprintf (alsa_add_args, sizeof (alsa_add_args), "%s_play:%s/-dhw:%s", 
                                          optarg,
                                          alsa_add_client_name_playback,
                                          optarg);
                                load_list = jack_slist_append(load_list, strdup (alsa_add_args));
                                snprintf (alsa_add_args, sizeof (alsa_add_args), "%s_rec:%s/-dhw:%s", 
                                          optarg,
                                          alsa_add_client_name_capture,
                                          optarg);
                                load_list = jack_slist_append(load_list, strdup (alsa_add_args));
                        }
                        break;
#endif

		case 'c':
			if (tolower (optarg[0]) == 'h') {
				clock_source = JACK_TIMER_HPET;
			} else if (tolower (optarg[0]) == 'c') {
				/* For backwards compatibility with scripts,
				 * allow the user to request the cycle clock
				 * on the command line, but use the system
				 * clock instead
				 */
				clock_source = JACK_TIMER_SYSTEM_CLOCK;
			} else if (tolower (optarg[0]) == 's') {
				clock_source = JACK_TIMER_SYSTEM_CLOCK;
			} else {
				usage (stderr);
				return -1;
			}
			break;

		case 'C':
			if (optarg)
				timeout_count_threshold = atoi (optarg);
			else
				timeout_count_threshold = 250;
			break;

		case 'd':
			seen_driver = optind + 1;
			driver_name = optarg;
			break;

		case 'D':
			frame_time_offset = JACK_MAX_FRAMES - atoi(optarg); 
			break;

		case 'l':
			/* special flag to allow libjack to determine jackd's idea of where tmpdir is */
			printf ("%s\n", jack_tmpdir);
			exit (0);

                case 'I':
			load_list = jack_slist_append(load_list, optarg);
                        break;

		case 'm':
			do_mlock = 0;
			break;

		case 'M':
			midi_buffer_size = (unsigned int) atol (optarg);
			break;

		case 'n':
			server_name = optarg;
			break;

		case 'N':
			do_sanity_checks = 0;
			break;

		case 'p':
			port_max = (unsigned int) atol (optarg);
			break;

		case 'P':
			realtime_priority = atoi (optarg);
			break;

		case 'r':
			realtime = 0;
			break;

		case 'R':
			/* this is now the default */
			realtime = 1;
			break;

		case 's':
			jack_set_error_function (silent_jack_error_callback);
			break;

                case 'S':
                        /* this option is for jack2 only (synchronous mode) */
                        break;

		case 'T':
			temporary = 1;
			break;

		case 't':
			client_timeout = atoi (optarg);
			break;

		case 'u':
			do_unlock = 1;
			break;

		case 'v':
			verbose = 1;
			break;

		case 'V':
			show_version = 1;
			break;

		case 'X':
			slave_drivers = jack_slist_append(slave_drivers, optarg);
			break;
		case 'Z':
			nozombies = 1;
			break;

		default:
			jack_error ("Unknown option character %c",
				    optopt);
			/*fallthru*/
		case 'h':
			usage (stdout);
			return -1;
		}
	}

	if (show_version) {
		printf ( "jackd version " VERSION 
				" tmpdir " DEFAULT_TMP_DIR 
				" protocol " PROTOCOL_VERSION
				"\n");
		return 0;
	}

	copyright (stdout);

	if (do_sanity_checks && (0 < sanitycheck (realtime, FALSE))) {
		return -1;
	}

	if (!seen_driver) {
		usage (stderr);
		exit (1);
	}

        /* DIRTY HACK needed to pick up -X supplied as part of ALSA driver args. This is legacy
           hack to make control apps like qjackctl based on the < 0.124 command line interface
           continue to work correctly.

           If -X seq was given as part of the driver args, load the ALSA MIDI slave driver.
        */
        
        for (i = seen_driver; i < argc; ++i) {
                if (strcmp (argv[i], "-X") == 0) {
                        if (argc >= i + 2) {
                                if (strcmp (argv[i+1], "seq") == 0) {
                                        slave_drivers = jack_slist_append (slave_drivers,"alsa_midi");
                                }
                        }
                        break;
                } else if (strcmp (argv[i], "-Xseq") == 0) {
                        slave_drivers = jack_slist_append (slave_drivers,"alsa_midi");
                        break;
                }
        }

	drivers = jack_drivers_load ();

	if (!drivers) {
		fprintf (stderr, "jackd: no drivers found; exiting\n");
		exit (1);
	}
	
	if (midi_buffer_size != 0) {
		jack_port_type_info_t* port_type = &jack_builtin_port_types[JACK_MIDI_PORT_TYPE];
		port_type->buffer_size = midi_buffer_size * jack_midi_internal_event_size ();
		port_type->buffer_scale_factor = -1;
		if (verbose) {
			fprintf (stderr, "Set MIDI buffer size to %u bytes\n", port_type->buffer_size);
		}
	}

	desc = jack_find_driver_descriptor (driver_name);
	if (!desc) {
		fprintf (stderr, "jackd: unknown driver '%s'\n", driver_name);
		exit (1);
	}

	if (optind < argc) {
		driver_nargs = 1 + argc - optind;
	} else {
		driver_nargs = 1;
	}

	if (driver_nargs == 0) {
		fprintf (stderr, "No driver specified ... hmm. JACK won't do"
			 " anything when run like this.\n");
		return -1;
	}

	driver_args = (char **) malloc (sizeof (char *) * driver_nargs);
	driver_args[0] = driver_name;
	
	for (i = 1; i < driver_nargs; i++) {
		driver_args[i] = argv[optind++];
	}

	if (jack_parse_driver_params (desc, driver_nargs,
				      driver_args, &driver_params)) {
		exit (0);
	}

	if (server_name == NULL)
		server_name = jack_default_server_name ();

	rc = jack_register_server (server_name, replace_registry);
	switch (rc) {
	case EEXIST:
		fprintf (stderr, "`%s' server already active\n", server_name);
		exit (1);
	case ENOSPC:
		fprintf (stderr, "too many servers already active\n");
		exit (2);
	case ENOMEM:
		fprintf (stderr, "no access to shm registry\n");
		exit (3);
	default:
		if (verbose)
			fprintf (stderr, "server `%s' registered\n",
				 server_name);
	}

	/* clean up shared memory and files from any previous
	 * instance of this server name */
	jack_cleanup_shm ();
	jack_cleanup_files (server_name);

	/* run the server engine until it terminates */
	jack_main (desc, driver_params, slave_drivers, load_list);

	/* clean up shared memory and files from this server instance */
	if (verbose)
		fprintf (stderr, "cleaning up shared memory\n");
	jack_cleanup_shm ();
	if (verbose)
		fprintf (stderr, "cleaning up files\n");
	jack_cleanup_files (server_name);
	if (verbose)
		fprintf (stderr, "unregistering server `%s'\n", server_name);
	jack_unregister_server (server_name);

	exit (0);
}