diff --git a/Makefile.am b/Makefile.am index 8212076..db767bd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -43,6 +43,7 @@ bin_PROGRAMS = jack_load \ jack_midi_dump \ jack_iodelay \ jack_load_test \ + jack_property \ $(JACK_TRANSPORT) \ $(NETJACK_TOOLS) @@ -56,6 +57,10 @@ endif AM_CFLAGS = -I.. $(JACK_CFLAGS) $(sndfile_cflags) AM_CXXFLAGS = -I.. $(JACK_CFLAGS) $(sndfile_cflags) +jack_property_SOURCES = property.c +jack_property_LDFLAGS = @OS_LDFLAGS@ +jack_property_LDADD = $(top_builddir)/libjack/libjack.la + jack_connect_SOURCES = connect.c jack_connect_LDFLAGS = @OS_LDFLAGS@ jack_connect_LDADD = $(top_builddir)/libjack/libjack.la diff --git a/property.c b/property.c new file mode 100644 index 0000000..b4b2164 --- /dev/null +++ b/property.c @@ -0,0 +1,330 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +static int subject_is_client = 0; +static int subject_is_port = 0; +static jack_uuid_t uuid; +static char* subject; + +static void +show_usage (void) +{ + fprintf (stderr, "\nUsage: jack_property [options] UUID [ key [ value [ type ] ] ]\n"); + fprintf (stderr, "Set/Display JACK properties (metadata).\n\n"); + fprintf (stderr, "Set options:\n"); + fprintf (stderr, " -s, --set Set property \"key\" to \"value\" for \"UUID\" with optional MIME type \"type\"\n"); + fprintf (stderr, " -d, --delete Remove/delete property \"key\" for \"UUID\"\n"); + fprintf (stderr, " -d, --delete UUID Remove/delete all properties for \"UUID\"\n"); + fprintf (stderr, " -D, --delete-all Remove/delete all properties\n"); + fprintf (stderr, " --client Interpret UUID as a client name, not a UUID\n"); + fprintf (stderr, " --port Interpret UUID as a port name, not a UUID\n"); + fprintf (stderr, "Display options:\n"); + fprintf (stderr, " -l Show all properties\n"); + fprintf (stderr, " -l, --list UUID Show value all properties of UUID\n"); + fprintf (stderr, " -l, --list UUID key Show value for key of UUID\n"); + fprintf (stderr, "For more information see http://jackaudio.org/\n"); +} + +static int +get_subject (jack_client_t* client, char* argv[], int* optind) +{ + if (subject_is_client) { + char* cstr = argv[(*optind)++]; + char* ustr; + + if ((ustr = jack_get_uuid_for_client_name (client, cstr)) == NULL) { + fprintf (stderr, "cannot get UUID for client named %s\n", cstr); + + } + + if (jack_uuid_parse (ustr, uuid)) { + fprintf (stderr, "cannot parse client UUID as UUID\n"); + return -1; + } + + subject = cstr; + + } else if (subject_is_port) { + + char* pstr = argv[(*optind)++]; + jack_port_t* port; + + if ((port = jack_port_by_name (client, pstr)) == NULL) { + fprintf (stderr, "cannot find port name %s\n", pstr); + return -1; + } + + jack_port_uuid (port, uuid); + subject = pstr; + + } else { + char* str = argv[(*optind)++]; + + if (jack_uuid_parse (str, uuid)) { + fprintf (stderr, "cannot parse subject as UUID\n"); + return -1; + } + + subject = str; + } + + return 0; +} + +int main (int argc, char* argv[]) +{ + jack_client_t* client = NULL; + jack_options_t options = JackNullOption; + char* key = NULL; + char* value = NULL; + char* type = NULL; + int set = 1; + int delete = 0; + int delete_all = 0; + int list_all = 0; + int c; + int option_index; + extern int optind; + struct option long_options[] = { + { "set", 0, 0, 's' }, + { "delete", 0, 0, 'd' }, + { "delete-all", 0, 0, 'D' }, + { "list", 0, 0, 'l' }, + { "all", 0, 0, 'a' }, + { "client", 0, 0, 'c' }, + { "port", 0, 0, 'p' }, + { 0, 0, 0, 0 } + }; + + while ((c = getopt_long (argc, argv, "sdDlaApc", long_options, &option_index)) >= 0) { + switch (c) { + case 's': + if (argc < 5) { + show_usage (); + exit (1); + } + set = 1; + break; + case 'd': + if (argc < 3) { + show_usage (); + return 1; + } + set = 0; + delete = 1; + break; + + case 'D': + delete = 0; + set = 0; + delete_all = 1; + break; + + case 'l': + set = 0; + delete = 0; + delete_all = 0; + break; + + case 'a': + list_all = 1; + set = 0; + delete = 0; + delete_all = 0; + break; + + case 'p': + subject_is_port = 1; + break; + + case 'c': + subject_is_client = 1; + break; + + case '?': + default: + show_usage (); + exit (1); + } + } + + if (delete_all) { + + /* Don't need to be a JACK client to do this + (or several other things, actually, but the + need is hard to determine a priori). + */ + + if (jack_remove_all_properties () == 0) { + printf ("JACK metadata successfully delete\n"); + exit (0); + } + exit (1); + } + + if ((client = jack_client_open ("jack-property", options, NULL)) == 0) { + fprintf (stderr, "Cannot connect to JACK server\n"); + exit (1); + } + + if (delete) { + + int args_left = argc - optind; + + if (args_left < 1) { + show_usage (); + exit (1); + } + + /* argc == 3: delete all properties for a subject + argc == 4: delete value of key for subject + */ + + if (args_left >= 2) { + + if (get_subject (client, argv, &optind)) { + return 1; + } + + key = argv[optind++]; + + if (jack_remove_property (uuid, key)) { + fprintf (stderr, "\"%s\" property not removed for %s\n", key, subject); + exit (1); + } + + } else { + + if (get_subject (client, argv, &optind)) { + return 1; + } + + if (jack_remove_properties (uuid)) { + fprintf (stderr, "cannot remove properties for UUID %s\n", subject); + exit (1); + } + } + + } else if (set) { + + int args_left = argc - optind; + + if (get_subject (client, argv, &optind)) { + return -1; + } + + key = argv[optind++]; + value = argv[optind++]; + + if (args_left >= 3) { + type = argv[optind++]; + } else { + type = ""; + } + + if (jack_set_property (uuid, key, value, type)) { + fprintf (stderr, "cannot set value for key %s of %s\n", value, subject); + exit (1); + } + + } else { + + /* list */ + + int args_left = argc - optind; + + /* argc == 3: list all properties for a subject + argc == 4: list value of key for subject + argc == ?: list all + */ + + if (args_left >= 2) { + + /* list properties for a UUID/key pair */ + + if (get_subject (client, argv, &optind)) { + return -1; + } + + key = argv[optind++]; + + if (jack_get_property (uuid, key, &value, &type) == 0) { + printf ("%s\n", value); + free (value); + if (type) { + free (type); + } + } else { + fprintf (stderr, "Value not found for %s of %s\n", key, subject); + exit (1); + } + + } else if (args_left == 1) { + + /* list all properties for a given UUID */ + + jack_description_t description; + size_t cnt, n; + + if (get_subject (client, argv, &optind)) { + return -1; + } + + if ((cnt = jack_get_properties (uuid, &description)) < 0) { + fprintf (stderr, "could not retrieve properties for %s\n", subject); + exit (1); + } + + for (n = 0; n < cnt; ++n) { + if (description.properties[n].type) { + printf ("key: %s value: %s type: %s\n", + description.properties[n].key, + description.properties[n].data, + description.properties[n].type); + } else { + printf ("key: %s value: %s\n", + description.properties[n].key, + description.properties[n].data); + } + } + + } else { + + /* list all properties */ + + jack_description_t* description; + size_t cnt; + + if ((cnt = jack_get_all_properties (&description)) < 0) { + fprintf (stderr, "could not retrieve properties for %s\n", subject); + exit (1); + } +#if 0 + for (n = 0; n < cnt; ++n) { + if (description.properties[n].type) { + printf ("key: %s value: %s type: %s\n", + description.properties[n].key, + description.properties[n].data, + description.properties[n].type); + } else { + printf ("key: %s value: %s\n", + description.properties[n].key, + description.properties[n].data); + } + } +#endif + } + } + + + (void) jack_client_close (client); + return 0; +}