]> code.delx.au - pulseaudio/blobdiff - src/utils/pactl.c
Merge commit 'coling/lgpl21'
[pulseaudio] / src / utils / pactl.c
index 1ff979e9efc61f1cfcd8df9b70fd14e201b2711a..de1c6d3dccbe0bbfde2c61dea049da82eab91c0d 100644 (file)
@@ -5,7 +5,7 @@
 
   PulseAudio is free software; you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License as published
 
   PulseAudio is free software; you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License as published
-  by the Free Software Foundation; either version 2 of the License,
+  by the Free Software Foundation; either version 2.1 of the License,
   or (at your option) any later version.
 
   PulseAudio is distributed in the hope that it will be useful, but
   or (at your option) any later version.
 
   PulseAudio is distributed in the hope that it will be useful, but
@@ -45,7 +45,7 @@
 static pa_context *context = NULL;
 static pa_mainloop_api *mainloop_api = NULL;
 
 static pa_context *context = NULL;
 static pa_mainloop_api *mainloop_api = NULL;
 
-static char *device = NULL, *sample_name = NULL, *sink_name = NULL, *source_name = NULL, *module_name = NULL, *module_args = NULL;
+static char *device = NULL, *sample_name = NULL, *sink_name = NULL, *source_name = NULL, *module_name = NULL, *module_args = NULL, *card_name = NULL, *profile_name = NULL;
 static uint32_t sink_input_idx = PA_INVALID_INDEX, source_output_idx = PA_INVALID_INDEX;
 static uint32_t module_index;
 static int suspend;
 static uint32_t sink_input_idx = PA_INVALID_INDEX, source_output_idx = PA_INVALID_INDEX;
 static uint32_t module_index;
 static int suspend;
@@ -73,6 +73,7 @@ static enum {
     UNLOAD_MODULE,
     SUSPEND_SINK,
     SUSPEND_SOURCE,
     UNLOAD_MODULE,
     SUSPEND_SINK,
     SUSPEND_SOURCE,
+    SET_CARD_PROFILE
 } action = NONE;
 
 static void quit(int ret) {
 } action = NONE;
 
 static void quit(int ret) {
@@ -122,7 +123,7 @@ static void stat_callback(pa_context *c, const pa_stat_info *i, void *userdata)
 }
 
 static void get_server_info_callback(pa_context *c, const pa_server_info *i, void *useerdata) {
 }
 
 static void get_server_info_callback(pa_context *c, const pa_server_info *i, void *useerdata) {
-    char s[PA_SAMPLE_SPEC_SNPRINT_MAX];
+    char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
 
     if (!i) {
         fprintf(stderr, _("Failed to get server information: %s\n"), pa_strerror(pa_context_errno(c)));
 
     if (!i) {
         fprintf(stderr, _("Failed to get server information: %s\n"), pa_strerror(pa_context_errno(c)));
@@ -130,21 +131,24 @@ static void get_server_info_callback(pa_context *c, const pa_server_info *i, voi
         return;
     }
 
         return;
     }
 
-    pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec);
+    pa_sample_spec_snprint(ss, sizeof(ss), &i->sample_spec);
+    pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map);
 
     printf(_("User name: %s\n"
 
     printf(_("User name: %s\n"
-           "Host Name: %s\n"
-           "Server Name: %s\n"
-           "Server Version: %s\n"
-           "Default Sample Specification: %s\n"
-           "Default Sink: %s\n"
-           "Default Source: %s\n"
-           "Cookie: %08x\n"),
+             "Host Name: %s\n"
+             "Server Name: %s\n"
+             "Server Version: %s\n"
+             "Default Sample Specification: %s\n"
+             "Default Channel Map: %s\n"
+             "Default Sink: %s\n"
+             "Default Source: %s\n"
+             "Cookie: %08x\n"),
            i->user_name,
            i->host_name,
            i->server_name,
            i->server_version,
            i->user_name,
            i->host_name,
            i->server_name,
            i->server_version,
-           s,
+           ss,
+           cm,
            i->default_sink_name,
            i->default_source_name,
            i->cookie);
            i->default_sink_name,
            i->default_source_name,
            i->cookie);
@@ -153,6 +157,14 @@ static void get_server_info_callback(pa_context *c, const pa_server_info *i, voi
 }
 
 static void get_sink_info_callback(pa_context *c, const pa_sink_info *i, int is_last, void *userdata) {
 }
 
 static void get_sink_info_callback(pa_context *c, const pa_sink_info *i, int is_last, void *userdata) {
+
+    static const char *state_table[] = {
+        [1+PA_SINK_INVALID_STATE] = "n/a",
+        [1+PA_SINK_RUNNING] = "RUNNING",
+        [1+PA_SINK_IDLE] = "IDLE",
+        [1+PA_SINK_SUSPENDED] = "SUSPENDED"
+    };
+
     char
         s[PA_SAMPLE_SPEC_SNPRINT_MAX],
         cv[PA_CVOLUME_SNPRINT_MAX],
     char
         s[PA_SAMPLE_SPEC_SNPRINT_MAX],
         cv[PA_CVOLUME_SNPRINT_MAX],
@@ -180,6 +192,7 @@ static void get_sink_info_callback(pa_context *c, const pa_sink_info *i, int is_
     nl = 1;
 
     printf(_("Sink #%u\n"
     nl = 1;
 
     printf(_("Sink #%u\n"
+             "\tState: %s\n"
              "\tName: %s\n"
              "\tDescription: %s\n"
              "\tDriver: %s\n"
              "\tName: %s\n"
              "\tDescription: %s\n"
              "\tDriver: %s\n"
@@ -195,6 +208,7 @@ static void get_sink_info_callback(pa_context *c, const pa_sink_info *i, int is_
              "\tFlags: %s%s%s%s%s%s\n"
              "\tProperties:\n\t\t%s\n"),
            i->index,
              "\tFlags: %s%s%s%s%s%s\n"
              "\tProperties:\n\t\t%s\n"),
            i->index,
+           state_table[1+i->state],
            i->name,
            pa_strnull(i->description),
            pa_strnull(i->driver),
            i->name,
            pa_strnull(i->description),
            pa_strnull(i->driver),
@@ -205,7 +219,7 @@ static void get_sink_info_callback(pa_context *c, const pa_sink_info *i, int is_
            pa_cvolume_snprint(cv, sizeof(cv), &i->volume),
            i->flags & PA_SINK_DECIBEL_VOLUME ? "\n\t        " : "",
            i->flags & PA_SINK_DECIBEL_VOLUME ? pa_sw_cvolume_snprint_dB(cvdb, sizeof(cvdb), &i->volume) : "",
            pa_cvolume_snprint(cv, sizeof(cv), &i->volume),
            i->flags & PA_SINK_DECIBEL_VOLUME ? "\n\t        " : "",
            i->flags & PA_SINK_DECIBEL_VOLUME ? pa_sw_cvolume_snprint_dB(cvdb, sizeof(cvdb), &i->volume) : "",
-           pa_cvolume_get_balance(&i->channel_map, &i->volume),
+           pa_cvolume_get_balance(&i->volume, &i->channel_map),
            pa_volume_snprint(v, sizeof(v), i->base_volume),
            i->flags & PA_SINK_DECIBEL_VOLUME ? "\n\t             " : "",
            i->flags & PA_SINK_DECIBEL_VOLUME ? pa_sw_volume_snprint_dB(vdb, sizeof(vdb), i->base_volume) : "",
            pa_volume_snprint(v, sizeof(v), i->base_volume),
            i->flags & PA_SINK_DECIBEL_VOLUME ? "\n\t             " : "",
            i->flags & PA_SINK_DECIBEL_VOLUME ? pa_sw_volume_snprint_dB(vdb, sizeof(vdb), i->base_volume) : "",
@@ -223,6 +237,14 @@ static void get_sink_info_callback(pa_context *c, const pa_sink_info *i, int is_
 }
 
 static void get_source_info_callback(pa_context *c, const pa_source_info *i, int is_last, void *userdata) {
 }
 
 static void get_source_info_callback(pa_context *c, const pa_source_info *i, int is_last, void *userdata) {
+
+    static const char *state_table[] = {
+        [1+PA_SOURCE_INVALID_STATE] = "n/a",
+        [1+PA_SOURCE_RUNNING] = "RUNNING",
+        [1+PA_SOURCE_IDLE] = "IDLE",
+        [1+PA_SOURCE_SUSPENDED] = "SUSPENDED"
+    };
+
     char
         s[PA_SAMPLE_SPEC_SNPRINT_MAX],
         cv[PA_CVOLUME_SNPRINT_MAX],
     char
         s[PA_SAMPLE_SPEC_SNPRINT_MAX],
         cv[PA_CVOLUME_SNPRINT_MAX],
@@ -250,6 +272,7 @@ static void get_source_info_callback(pa_context *c, const pa_source_info *i, int
     nl = 1;
 
     printf(_("Source #%u\n"
     nl = 1;
 
     printf(_("Source #%u\n"
+             "\tState: %s\n"
              "\tName: %s\n"
              "\tDescription: %s\n"
              "\tDriver: %s\n"
              "\tName: %s\n"
              "\tDescription: %s\n"
              "\tDriver: %s\n"
@@ -265,6 +288,7 @@ static void get_source_info_callback(pa_context *c, const pa_source_info *i, int
              "\tFlags: %s%s%s%s%s%s\n"
              "\tProperties:\n\t\t%s\n"),
            i->index,
              "\tFlags: %s%s%s%s%s%s\n"
              "\tProperties:\n\t\t%s\n"),
            i->index,
+           state_table[1+i->state],
            i->name,
            pa_strnull(i->description),
            pa_strnull(i->driver),
            i->name,
            pa_strnull(i->description),
            pa_strnull(i->driver),
@@ -275,7 +299,7 @@ static void get_source_info_callback(pa_context *c, const pa_source_info *i, int
            pa_cvolume_snprint(cv, sizeof(cv), &i->volume),
            i->flags & PA_SOURCE_DECIBEL_VOLUME ? "\n\t        " : "",
            i->flags & PA_SOURCE_DECIBEL_VOLUME ? pa_sw_cvolume_snprint_dB(cvdb, sizeof(cvdb), &i->volume) : "",
            pa_cvolume_snprint(cv, sizeof(cv), &i->volume),
            i->flags & PA_SOURCE_DECIBEL_VOLUME ? "\n\t        " : "",
            i->flags & PA_SOURCE_DECIBEL_VOLUME ? pa_sw_cvolume_snprint_dB(cvdb, sizeof(cvdb), &i->volume) : "",
-           pa_cvolume_get_balance(&i->channel_map, &i->volume),
+           pa_cvolume_get_balance(&i->volume, &i->channel_map),
            pa_volume_snprint(v, sizeof(v), i->base_volume),
            i->flags & PA_SOURCE_DECIBEL_VOLUME ? "\n\t             " : "",
            i->flags & PA_SOURCE_DECIBEL_VOLUME ? pa_sw_volume_snprint_dB(vdb, sizeof(vdb), i->base_volume) : "",
            pa_volume_snprint(v, sizeof(v), i->base_volume),
            i->flags & PA_SOURCE_DECIBEL_VOLUME ? "\n\t             " : "",
            i->flags & PA_SOURCE_DECIBEL_VOLUME ? pa_sw_volume_snprint_dB(vdb, sizeof(vdb), i->base_volume) : "",
@@ -364,6 +388,55 @@ static void get_client_info_callback(pa_context *c, const pa_client_info *i, int
     pa_xfree(pl);
 }
 
     pa_xfree(pl);
 }
 
+static void get_card_info_callback(pa_context *c, const pa_card_info *i, int is_last, void *userdata) {
+    char t[32];
+    char *pl;
+
+    if (is_last < 0) {
+        fprintf(stderr, _("Failed to get card information: %s\n"), pa_strerror(pa_context_errno(c)));
+        complete_action();
+        return;
+    }
+
+    if (is_last) {
+        complete_action();
+        return;
+    }
+
+    assert(i);
+
+    if (nl)
+        printf("\n");
+    nl = 1;
+
+    snprintf(t, sizeof(t), "%u", i->owner_module);
+
+    printf(_("Card #%u\n"
+             "\tName: %s\n"
+             "\tDriver: %s\n"
+             "\tOwner Module: %s\n"
+             "\tProperties:\n\t\t%s\n"),
+           i->index,
+           i->name,
+           pa_strnull(i->driver),
+           i->owner_module != PA_INVALID_INDEX ? t : _("n/a"),
+           pl = pa_proplist_to_string_sep(i->proplist, "\n\t\t"));
+
+    if (i->profiles) {
+        pa_card_profile_info *p;
+
+        printf(_("\tProfiles:\n"));
+        for (p = i->profiles; p->name; p++)
+            printf("\t\t%s: %s (sinks: %u, sources: %u, priority. %u)\n", p->name, p->description, p->n_sinks, p->n_sources, p->priority);
+    }
+
+    if (i->active_profile)
+        printf(_("\tActive Profile: %s\n"),
+               i->active_profile->name);
+
+    pa_xfree(pl);
+}
+
 static void get_sink_input_info_callback(pa_context *c, const pa_sink_input_info *i, int is_last, void *userdata) {
     char t[32], k[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cvdb[PA_SW_CVOLUME_SNPRINT_DB_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
     char *pl;
 static void get_sink_input_info_callback(pa_context *c, const pa_sink_input_info *i, int is_last, void *userdata) {
     char t[32], k[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cvdb[PA_SW_CVOLUME_SNPRINT_DB_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
     char *pl;
@@ -413,7 +486,7 @@ static void get_sink_input_info_callback(pa_context *c, const pa_sink_input_info
            pa_yes_no(i->mute),
            pa_cvolume_snprint(cv, sizeof(cv), &i->volume),
            pa_sw_cvolume_snprint_dB(cvdb, sizeof(cvdb), &i->volume),
            pa_yes_no(i->mute),
            pa_cvolume_snprint(cv, sizeof(cv), &i->volume),
            pa_sw_cvolume_snprint_dB(cvdb, sizeof(cvdb), &i->volume),
-           pa_cvolume_get_balance(&i->channel_map, &i->volume),
+           pa_cvolume_get_balance(&i->volume, &i->channel_map),
            (double) i->buffer_usec,
            (double) i->sink_usec,
            i->resample_method ? i->resample_method : _("n/a"),
            (double) i->buffer_usec,
            (double) i->sink_usec,
            i->resample_method ? i->resample_method : _("n/a"),
@@ -514,7 +587,7 @@ static void get_sample_info_callback(pa_context *c, const pa_sample_info *i, int
            pa_sample_spec_valid(&i->sample_spec) ? pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map) : _("n/a"),
            pa_cvolume_snprint(cv, sizeof(cv), &i->volume),
            pa_sw_cvolume_snprint_dB(cvdb, sizeof(cvdb), &i->volume),
            pa_sample_spec_valid(&i->sample_spec) ? pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map) : _("n/a"),
            pa_cvolume_snprint(cv, sizeof(cv), &i->volume),
            pa_sw_cvolume_snprint_dB(cvdb, sizeof(cvdb), &i->volume),
-           pa_cvolume_get_balance(&i->channel_map, &i->volume),
+           pa_cvolume_get_balance(&i->volume, &i->channel_map),
            (double) i->duration/1000000.0,
            t,
            pa_yes_no(i->lazy),
            (double) i->duration/1000000.0,
            t,
            pa_yes_no(i->lazy),
@@ -579,6 +652,7 @@ static void stream_write_callback(pa_stream *s, size_t length, void *userdata) {
         pa_xfree(d);
         fprintf(stderr, _("Premature end of file\n"));
         quit(1);
         pa_xfree(d);
         fprintf(stderr, _("Premature end of file\n"));
         quit(1);
+        return;
     }
 
     pa_stream_write(s, d, length, pa_xfree, 0, PA_SEEK_RELATIVE);
     }
 
     pa_stream_write(s, d, length, pa_xfree, 0, PA_SEEK_RELATIVE);
@@ -629,7 +703,7 @@ static void context_state_callback(pa_context *c, void *userdata) {
                     break;
 
                 case LIST:
                     break;
 
                 case LIST:
-                    actions = 7;
+                    actions = 8;
                     pa_operation_unref(pa_context_get_module_info_list(c, get_module_info_callback, NULL));
                     pa_operation_unref(pa_context_get_sink_info_list(c, get_sink_info_callback, NULL));
                     pa_operation_unref(pa_context_get_source_info_list(c, get_source_info_callback, NULL));
                     pa_operation_unref(pa_context_get_module_info_list(c, get_module_info_callback, NULL));
                     pa_operation_unref(pa_context_get_sink_info_list(c, get_sink_info_callback, NULL));
                     pa_operation_unref(pa_context_get_source_info_list(c, get_source_info_callback, NULL));
@@ -637,6 +711,7 @@ static void context_state_callback(pa_context *c, void *userdata) {
                     pa_operation_unref(pa_context_get_source_output_info_list(c, get_source_output_info_callback, NULL));
                     pa_operation_unref(pa_context_get_client_info_list(c, get_client_info_callback, NULL));
                     pa_operation_unref(pa_context_get_sample_info_list(c, get_sample_info_callback, NULL));
                     pa_operation_unref(pa_context_get_source_output_info_list(c, get_source_output_info_callback, NULL));
                     pa_operation_unref(pa_context_get_client_info_list(c, get_client_info_callback, NULL));
                     pa_operation_unref(pa_context_get_sample_info_list(c, get_sample_info_callback, NULL));
+                    pa_operation_unref(pa_context_get_card_info_list(c, get_card_info_callback, NULL));
                     break;
 
                 case MOVE_SINK_INPUT:
                     break;
 
                 case MOVE_SINK_INPUT:
@@ -669,6 +744,10 @@ static void context_state_callback(pa_context *c, void *userdata) {
                         pa_operation_unref(pa_context_suspend_source_by_index(c, PA_INVALID_INDEX, suspend, simple_callback, NULL));
                     break;
 
                         pa_operation_unref(pa_context_suspend_source_by_index(c, PA_INVALID_INDEX, suspend, simple_callback, NULL));
                     break;
 
+                case SET_CARD_PROFILE:
+                    pa_operation_unref(pa_context_set_card_profile_by_name(c, card_name, profile_name, simple_callback, NULL));
+                    break;
+
                 default:
                     assert(0);
             }
                 default:
                     assert(0);
             }
@@ -693,22 +772,23 @@ static void exit_signal_callback(pa_mainloop_api *m, pa_signal_event *e, int sig
 static void help(const char *argv0) {
 
     printf(_("%s [options] stat\n"
 static void help(const char *argv0) {
 
     printf(_("%s [options] stat\n"
-           "%s [options] list\n"
-           "%s [options] exit\n"
-           "%s [options] upload-sample FILENAME [NAME]\n"
-           "%s [options] play-sample NAME [SINK]\n"
-           "%s [options] remove-sample NAME\n"
-           "%s [options] move-sink-input ID SINK\n"
-           "%s [options] move-source-output ID SOURCE\n"
-           "%s [options] load-module NAME [ARGS ...]\n"
-           "%s [options] unload-module ID\n"
-           "%s [options] suspend-sink [SINK] 1|0\n"
-           "%s [options] suspend-source [SOURCE] 1|0\n\n"
-           "  -h, --help                            Show this help\n"
-           "      --version                         Show version\n\n"
-           "  -s, --server=SERVER                   The name of the server to connect to\n"
-           "  -n, --client-name=NAME                How to call this client on the server\n"),
-           argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0);
+             "%s [options] list\n"
+             "%s [options] exit\n"
+             "%s [options] upload-sample FILENAME [NAME]\n"
+             "%s [options] play-sample NAME [SINK]\n"
+             "%s [options] remove-sample NAME\n"
+             "%s [options] move-sink-input ID SINK\n"
+             "%s [options] move-source-output ID SOURCE\n"
+             "%s [options] load-module NAME [ARGS ...]\n"
+             "%s [options] unload-module ID\n"
+             "%s [options] suspend-sink [SINK] 1|0\n"
+             "%s [options] suspend-source [SOURCE] 1|0\n"
+             "%s [options] set-card-profile [CARD] [PROFILE] \n\n"
+             "  -h, --help                            Show this help\n"
+             "      --version                         Show version\n\n"
+             "  -s, --server=SERVER                   The name of the server to connect to\n"
+             "  -n, --client-name=NAME                How to call this client on the server\n"),
+           argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0);
 }
 
 enum { ARG_VERSION = 256 };
 }
 
 enum { ARG_VERSION = 256 };
@@ -889,7 +969,7 @@ int main(int argc, char *argv[]) {
             action = SUSPEND_SINK;
 
             if (argc > optind+3 || optind+1 >= argc) {
             action = SUSPEND_SINK;
 
             if (argc > optind+3 || optind+1 >= argc) {
-                fprintf(stderr, _("You may not specify more than one sink. You have to specify at least one boolean value.\n"));
+                fprintf(stderr, _("You may not specify more than one sink. You have to specify a boolean value.\n"));
                 goto quit;
             }
 
                 goto quit;
             }
 
@@ -902,7 +982,7 @@ int main(int argc, char *argv[]) {
             action = SUSPEND_SOURCE;
 
             if (argc > optind+3 || optind+1 >= argc) {
             action = SUSPEND_SOURCE;
 
             if (argc > optind+3 || optind+1 >= argc) {
-                fprintf(stderr, _("You may not specify more than one source. You have to specify at least one boolean value.\n"));
+                fprintf(stderr, _("You may not specify more than one source. You have to specify a boolean value.\n"));
                 goto quit;
             }
 
                 goto quit;
             }
 
@@ -910,6 +990,17 @@ int main(int argc, char *argv[]) {
 
             if (argc > optind+2)
                 source_name = pa_xstrdup(argv[optind+1]);
 
             if (argc > optind+2)
                 source_name = pa_xstrdup(argv[optind+1]);
+        } else if (!strcmp(argv[optind], "set-card-profile")) {
+            action = SET_CARD_PROFILE;
+
+            if (argc != optind+3) {
+                fprintf(stderr, _("You have to specify a card name/index and a profile name\n"));
+                goto quit;
+            }
+
+            card_name = pa_xstrdup(argv[optind+1]);
+            profile_name = pa_xstrdup(argv[optind+2]);
+
         } else if (!strcmp(argv[optind], "help")) {
             help(bn);
             ret = 0;
         } else if (!strcmp(argv[optind], "help")) {
             help(bn);
             ret = 0;
@@ -942,7 +1033,10 @@ int main(int argc, char *argv[]) {
     }
 
     pa_context_set_state_callback(context, context_state_callback, NULL);
     }
 
     pa_context_set_state_callback(context, context_state_callback, NULL);
-    pa_context_connect(context, server, 0, NULL);
+    if (pa_context_connect(context, server, 0, NULL) < 0) {
+        fprintf(stderr, _("pa_context_connect() failed: %s"), pa_strerror(pa_context_errno(context)));
+        goto quit;
+    }
 
     if (pa_mainloop_run(m, &ret) < 0) {
         fprintf(stderr, _("pa_mainloop_run() failed.\n"));
 
     if (pa_mainloop_run(m, &ret) < 0) {
         fprintf(stderr, _("pa_mainloop_run() failed.\n"));
@@ -971,6 +1065,8 @@ quit:
     pa_xfree(source_name);
     pa_xfree(module_args);
     pa_xfree(client_name);
     pa_xfree(source_name);
     pa_xfree(module_args);
     pa_xfree(client_name);
+    pa_xfree(card_name);
+    pa_xfree(profile_name);
 
     return ret;
 }
 
     return ret;
 }