diff options
Diffstat (limited to 'src/utils/pactl.c')
-rw-r--r-- | src/utils/pactl.c | 368 |
1 files changed, 237 insertions, 131 deletions
diff --git a/src/utils/pactl.c b/src/utils/pactl.c index 2f430ca7..154e7f9c 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -45,7 +45,7 @@ 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; @@ -73,6 +73,7 @@ static enum { UNLOAD_MODULE, SUSPEND_SINK, SUSPEND_SOURCE, + SET_CARD_PROFILE } action = NONE; static void quit(int ret) { @@ -153,7 +154,21 @@ 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) { - char s[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX]; + + 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], + cvdb[PA_SW_CVOLUME_SNPRINT_DB_MAX], + v[PA_VOLUME_SNPRINT_MAX], + vdb[PA_SW_VOLUME_SNPRINT_DB_MAX], + cm[PA_CHANNEL_MAP_SNPRINT_MAX]; char *pl; if (is_last < 0) { @@ -173,24 +188,38 @@ static void get_sink_info_callback(pa_context *c, const pa_sink_info *i, int is_ printf("\n"); nl = 1; - printf(_("*** Sink #%u ***\n" - "Name: %s\n" - "Driver: %s\n" - "Sample Specification: %s\n" - "Channel Map: %s\n" - "Owner Module: %u\n" - "Volume: %s\n" - "Monitor Source: %s\n" - "Latency: %0.0f usec, configured %0.0f usec\n" - "Flags: %s%s%s%s%s%s\n" - "Properties:\n%s"), + printf(_("Sink #%u\n" + "\tState: %s\n" + "\tName: %s\n" + "\tDescription: %s\n" + "\tDriver: %s\n" + "\tSample Specification: %s\n" + "\tChannel Map: %s\n" + "\tOwner Module: %u\n" + "\tMute: %s\n" + "\tVolume: %s%s%s\n" + "\t balance %0.2f\n" + "\tBase Volume: %s%s%s\n" + "\tMonitor Source: %s\n" + "\tLatency: %0.0f usec, configured %0.0f usec\n" + "\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), pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec), pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map), i->owner_module, - i->mute ? _("muted") : pa_cvolume_snprint(cv, sizeof(cv), &i->volume), + pa_yes_no(i->mute), + 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->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_strnull(i->monitor_source_name), (double) i->latency, (double) i->configured_latency, i->flags & PA_SINK_HARDWARE ? "HARDWARE " : "", @@ -199,13 +228,27 @@ static void get_sink_info_callback(pa_context *c, const pa_sink_info *i, int is_ i->flags & PA_SINK_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "", i->flags & PA_SINK_DECIBEL_VOLUME ? "DECIBEL_VOLUME " : "", i->flags & PA_SINK_LATENCY ? "LATENCY " : "", - pl = pa_proplist_to_string(i->proplist)); + pl = pa_proplist_to_string_sep(i->proplist, "\n\t\t")); pa_xfree(pl); } static void get_source_info_callback(pa_context *c, const pa_source_info *i, int is_last, void *userdata) { - char s[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX]; + + 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], + cvdb[PA_SW_CVOLUME_SNPRINT_DB_MAX], + v[PA_VOLUME_SNPRINT_MAX], + vdb[PA_SW_VOLUME_SNPRINT_DB_MAX], + cm[PA_CHANNEL_MAP_SNPRINT_MAX]; char *pl; if (is_last < 0) { @@ -225,24 +268,38 @@ static void get_source_info_callback(pa_context *c, const pa_source_info *i, int printf("\n"); nl = 1; - printf(_("*** Source #%u ***\n" - "Name: %s\n" - "Driver: %s\n" - "Sample Specification: %s\n" - "Channel Map: %s\n" - "Owner Module: %u\n" - "Volume: %s\n" - "Monitor of Sink: %s\n" - "Latency: %0.0f usec, configured %0.0f usec\n" - "Flags: %s%s%s%s%s%s\n" - "Properties:\n%s"), + printf(_("Source #%u\n" + "\tState: %s\n" + "\tName: %s\n" + "\tDescription: %s\n" + "\tDriver: %s\n" + "\tSample Specification: %s\n" + "\tChannel Map: %s\n" + "\tOwner Module: %u\n" + "\tMute: %s\n" + "\tVolume: %s%s%s\n" + "\t balance %0.2f\n" + "\tBase Volume: %s%s%s\n" + "\tMonitor of Sink: %s\n" + "\tLatency: %0.0f usec, configured %0.0f usec\n" + "\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), pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec), pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map), i->owner_module, - i->mute ? "muted" : pa_cvolume_snprint(cv, sizeof(cv), &i->volume), + pa_yes_no(i->mute), + 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->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) : "", i->monitor_of_sink_name ? i->monitor_of_sink_name : _("n/a"), (double) i->latency, (double) i->configured_latency, i->flags & PA_SOURCE_HARDWARE ? "HARDWARE " : "", @@ -251,13 +308,14 @@ static void get_source_info_callback(pa_context *c, const pa_source_info *i, int i->flags & PA_SOURCE_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "", i->flags & PA_SOURCE_DECIBEL_VOLUME ? "DECIBEL_VOLUME " : "", i->flags & PA_SOURCE_LATENCY ? "LATENCY " : "", - pl = pa_proplist_to_string(i->proplist)); + pl = pa_proplist_to_string_sep(i->proplist, "\n\t\t")); pa_xfree(pl); } static void get_module_info_callback(pa_context *c, const pa_module_info *i, int is_last, void *userdata) { char t[32]; + char *pl; if (is_last < 0) { fprintf(stderr, _("Failed to get module information: %s\n"), pa_strerror(pa_context_errno(c))); @@ -278,16 +336,18 @@ static void get_module_info_callback(pa_context *c, const pa_module_info *i, int snprintf(t, sizeof(t), "%u", i->n_used); - printf(_("*** Module #%u ***\n" - "Name: %s\n" - "Argument: %s\n" - "Usage counter: %s\n" - "Auto unload: %s\n"), + printf(_("Module #%u\n" + "\tName: %s\n" + "\tArgument: %s\n" + "\tUsage counter: %s\n" + "\tProperties:\n\t\t%s\n"), i->index, i->name, i->argument ? i->argument : "", i->n_used != PA_INVALID_INDEX ? t : _("n/a"), - pa_yes_no(i->auto_unload)); + pl = pa_proplist_to_string_sep(i->proplist, "\n\t\t")); + + pa_xfree(pl); } static void get_client_info_callback(pa_context *c, const pa_client_info *i, int is_last, void *userdata) { @@ -313,20 +373,69 @@ static void get_client_info_callback(pa_context *c, const pa_client_info *i, int snprintf(t, sizeof(t), "%u", i->owner_module); - printf(_("*** Client #%u ***\n" - "Driver: %s\n" - "Owner Module: %s\n" - "Properties:\n%s"), + printf(_("Client #%u\n" + "\tDriver: %s\n" + "\tOwner Module: %s\n" + "\tProperties:\n\t\t%s\n"), + i->index, + pa_strnull(i->driver), + i->owner_module != PA_INVALID_INDEX ? t : _("n/a"), + pl = pa_proplist_to_string_sep(i->proplist, "\n\t\t")); + + 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(i->proplist)); + 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\n", p->name, p->description); + } + + 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], cm[PA_CHANNEL_MAP_SNPRINT_MAX]; + 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; if (is_last < 0) { @@ -349,18 +458,21 @@ static void get_sink_input_info_callback(pa_context *c, const pa_sink_input_info snprintf(t, sizeof(t), "%u", i->owner_module); snprintf(k, sizeof(k), "%u", i->client); - printf(_("*** Sink Input #%u ***\n" - "Driver: %s\n" - "Owner Module: %s\n" - "Client: %s\n" - "Sink: %u\n" - "Sample Specification: %s\n" - "Channel Map: %s\n" - "Volume: %s\n" - "Buffer Latency: %0.0f usec\n" - "Sink Latency: %0.0f usec\n" - "Resample method: %s\n" - "Properties:\n%s"), + printf(_("Sink Input #%u\n" + "\tDriver: %s\n" + "\tOwner Module: %s\n" + "\tClient: %s\n" + "\tSink: %u\n" + "\tSample Specification: %s\n" + "\tChannel Map: %s\n" + "\tMute: %s\n" + "\tVolume: %s\n" + "\t %s\n" + "\t balance %0.2f\n" + "\tBuffer Latency: %0.0f usec\n" + "\tSink Latency: %0.0f usec\n" + "\tResample method: %s\n" + "\tProperties:\n\t\t%s\n"), i->index, pa_strnull(i->driver), i->owner_module != PA_INVALID_INDEX ? t : _("n/a"), @@ -368,11 +480,14 @@ static void get_sink_input_info_callback(pa_context *c, const pa_sink_input_info i->sink, pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec), pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map), - i->mute ? _("muted") : pa_cvolume_snprint(cv, sizeof(cv), &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->volume, &i->channel_map), (double) i->buffer_usec, (double) i->sink_usec, i->resample_method ? i->resample_method : _("n/a"), - pl = pa_proplist_to_string(i->proplist)); + pl = pa_proplist_to_string_sep(i->proplist, "\n\t\t")); pa_xfree(pl); } @@ -402,17 +517,17 @@ static void get_source_output_info_callback(pa_context *c, const pa_source_outpu snprintf(t, sizeof(t), "%u", i->owner_module); snprintf(k, sizeof(k), "%u", i->client); - printf(_("*** Source Output #%u ***\n" - "Driver: %s\n" - "Owner Module: %s\n" - "Client: %s\n" - "Source: %u\n" - "Sample Specification: %s\n" - "Channel Map: %s\n" - "Buffer Latency: %0.0f usec\n" - "Source Latency: %0.0f usec\n" - "Resample method: %s\n" - "Properties:\n%s"), + printf(_("Source Output #%u\n" + "\tDriver: %s\n" + "\tOwner Module: %s\n" + "\tClient: %s\n" + "\tSource: %u\n" + "\tSample Specification: %s\n" + "\tChannel Map: %s\n" + "\tBuffer Latency: %0.0f usec\n" + "\tSource Latency: %0.0f usec\n" + "\tResample method: %s\n" + "\tProperties:\n\t\t%s\n"), i->index, pa_strnull(i->driver), i->owner_module != PA_INVALID_INDEX ? t : _("n/a"), @@ -423,13 +538,13 @@ static void get_source_output_info_callback(pa_context *c, const pa_source_outpu (double) i->buffer_usec, (double) i->source_usec, i->resample_method ? i->resample_method : _("n/a"), - pl = pa_proplist_to_string(i->proplist)); + pl = pa_proplist_to_string_sep(i->proplist, "\n\t\t")); pa_xfree(pl); } static void get_sample_info_callback(pa_context *c, const pa_sample_info *i, int is_last, void *userdata) { - char t[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX]; + char t[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; if (is_last < 0) { @@ -449,63 +564,36 @@ static void get_sample_info_callback(pa_context *c, const pa_sample_info *i, int printf("\n"); nl = 1; - pa_bytes_snprint(t, sizeof(t), i->bytes); - printf(_("*** Sample #%u ***\n" - "Name: %s\n" - "Volume: %s\n" - "Sample Specification: %s\n" - "Channel Map: %s\n" - "Duration: %0.1fs\n" - "Size: %s\n" - "Lazy: %s\n" - "Filename: %s\n" - "Properties:\n%s"), + printf(_("Sample #%u\n" + "\tName: %s\n" + "\tSample Specification: %s\n" + "\tChannel Map: %s\n" + "\tVolume: %s\n" + "\t %s\n" + "\t balance %0.2f\n" + "\tDuration: %0.1fs\n" + "\tSize: %s\n" + "\tLazy: %s\n" + "\tFilename: %s\n" + "\tProperties:\n\t\t%s\n"), i->index, i->name, - pa_cvolume_snprint(cv, sizeof(cv), &i->volume), pa_sample_spec_valid(&i->sample_spec) ? pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec) : _("n/a"), pa_sample_spec_valid(&i->sample_spec) ? pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map) : _("n/a"), - (double) i->duration/1000000, + pa_cvolume_snprint(cv, sizeof(cv), &i->volume), + pa_sw_cvolume_snprint_dB(cvdb, sizeof(cvdb), &i->volume), + pa_cvolume_get_balance(&i->volume, &i->channel_map), + (double) i->duration/1000000.0, t, pa_yes_no(i->lazy), i->filename ? i->filename : _("n/a"), - pl = pa_proplist_to_string(i->proplist)); + pl = pa_proplist_to_string_sep(i->proplist, "\n\t\t")); pa_xfree(pl); } -static void get_autoload_info_callback(pa_context *c, const pa_autoload_info *i, int is_last, void *userdata) { - if (is_last < 0) { - fprintf(stderr, _("Failed to get autoload information: %s\n"), pa_strerror(pa_context_errno(c))); - quit(1); - return; - } - - if (is_last) { - complete_action(); - return; - } - - assert(i); - - if (nl) - printf("\n"); - nl = 1; - - printf(_("*** Autoload Entry #%u ***\n" - "Name: %s\n" - "Type: %s\n" - "Module: %s\n" - "Argument: %s\n"), - i->index, - i->name, - i->type == PA_AUTOLOAD_SINK ? _("sink") : _("source"), - i->module, - i->argument ? i->argument : ""); -} - static void simple_callback(pa_context *c, int success, void *userdata) { if (!success) { fprintf(stderr, _("Failure: %s\n"), pa_strerror(pa_context_errno(c))); @@ -619,7 +707,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_autoload_info_list(c, get_autoload_info_callback, NULL)); + pa_operation_unref(pa_context_get_card_info_list(c, get_card_info_callback, NULL)); break; case MOVE_SINK_INPUT: @@ -652,6 +740,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; + 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); } @@ -676,22 +768,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" - "%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 }; @@ -872,7 +965,7 @@ int main(int argc, char *argv[]) { 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; } @@ -885,7 +978,7 @@ int main(int argc, char *argv[]) { 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; } @@ -893,6 +986,17 @@ int main(int argc, char *argv[]) { 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; @@ -954,6 +1058,8 @@ quit: pa_xfree(source_name); pa_xfree(module_args); pa_xfree(client_name); + pa_xfree(card_name); + pa_xfree(profile_name); return ret; } |