ascii-chat 0.8.38
Real-time terminal-based video chat with ASCII art conversion
Loading...
Searching...
No Matches
actions.c File Reference

Action option callbacks for ascii-chat. More...

Go to the source code of this file.

Functions

void actions_defer (deferred_action_t action, const action_args_t *args)
 
deferred_action_t actions_get_deferred (void)
 
const action_args_t * actions_get_args (void)
 
void action_list_webcams (void)
 
void action_list_microphones (void)
 
void action_list_speakers (void)
 
void action_show_capabilities_immediate (void)
 Execute show capabilities immediately (for early binary-level execution)
 
void action_show_capabilities (void)
 
void action_check_update_immediate (void)
 Execute update check immediately (for early binary-level execution)
 
void action_check_update (void)
 
void action_show_version (void)
 
void action_help_server (void)
 
void action_help_client (void)
 
void action_help_mirror (void)
 
void action_help_acds (void)
 
void action_help_discovery (void)
 
void action_create_manpage (const char *output_path)
 
void action_create_config (const char *output_path)
 
void action_completions (const char *shell_name, const char *output_path)
 
void actions_execute_deferred (void)
 

Detailed Description

Action option callbacks for ascii-chat.

Action options are deferred until after all options are fully parsed and initialized. This ensures that options like –width and –height are properly reflected in action output (e.g., –show-capabilities displays the final terminal dimensions).

Examples: –list-webcams, –list-microphones, –list-speakers, –show-capabilities

Definition in file options/parsing/actions.c.

Function Documentation

◆ action_check_update()

void action_check_update ( void  )

Definition at line 348 of file options/parsing/actions.c.

348 {
349 // Defer execution until after options are fully parsed
350 actions_defer(ACTION_CHECK_UPDATE, NULL);
351}
void actions_defer(deferred_action_t action, const action_args_t *args)

References actions_defer().

Referenced by options_registry_add_all_to_builder().

◆ action_check_update_immediate()

void action_check_update_immediate ( void  )

Execute update check immediately (for early binary-level execution)

Definition at line 330 of file options/parsing/actions.c.

330 {
331 printf("Checking for updates...\n");
332 update_check_result_t result;
333 asciichat_error_t err = update_check_perform(&result);
334 if (err != ASCIICHAT_OK) {
335 printf("\nFailed to check for updates.\n\n");
336 action_exit(1);
337 }
338 if (result.update_available) {
339 char notification[1024];
340 update_check_format_notification(&result, notification, sizeof(notification));
341 printf("\n%s\n\n", notification);
342 } else {
343 printf("\nYou are already on the latest version: %s (%.8s)\n\n", result.current_version, result.current_sha);
344 }
345 action_exit(0);
346}
asciichat_error_t update_check_perform(update_check_result_t *result)
void update_check_format_notification(const update_check_result_t *result, char *buffer, size_t buffer_size)

References update_check_format_notification(), and update_check_perform().

Referenced by options_init().

◆ action_completions()

void action_completions ( const char *  shell_name,
const char *  output_path 
)

Definition at line 590 of file options/parsing/actions.c.

590 {
591 if (!shell_name || strlen(shell_name) == 0) {
592 log_plain_stderr("Error: --completions requires shell name (bash, fish, zsh, powershell)");
593 action_exit(ERROR_USAGE);
594 }
595
596 completion_format_t format = completions_parse_shell_name(shell_name);
597 if (format == COMPLETION_FORMAT_UNKNOWN) {
598 log_plain_stderr("Error: Unknown shell '%s' (supported: bash, fish, zsh, powershell)", shell_name);
599 action_exit(ERROR_USAGE);
600 }
601
602 FILE *output = stdout;
603 bool should_close = false;
604
605 // Determine output: use provided path if given and not "-", otherwise stdout
606 if (output_path && strlen(output_path) > 0 && strcmp(output_path, "-") != 0) {
607 // Check if file already exists and prompt for confirmation
608 struct stat st;
609 if (stat(output_path, &st) == 0) {
610 // File exists - ask user if they want to overwrite
611 log_plain("Completions file already exists: %s", output_path);
612
613 bool overwrite = platform_prompt_yes_no("Overwrite", false); // Default to No
614 if (!overwrite) {
615 log_plain("Completions generation cancelled.");
616 action_exit(0);
617 }
618
619 log_plain("Overwriting existing completions file...");
620 }
621
622 output = platform_fopen(output_path, "w");
623 if (!output) {
624 log_plain_stderr("Error: Failed to open %s for writing", output_path);
625 action_exit(ERROR_FILE_OPERATION);
626 }
627 should_close = true;
628 }
629
630 asciichat_error_t result = completions_generate_for_shell(format, output);
631
632 if (should_close) {
633 fclose(output);
634 }
635
636 if (result != ASCIICHAT_OK) {
637 log_plain_stderr("Error: Failed to generate %s completions", completions_get_shell_name(format));
638 action_exit(ERROR_USAGE);
639 }
640
641 // Silently exit - completions are written (either to file or stdout)
642 action_exit(0);
643}
completion_format_t completions_parse_shell_name(const char *shell_name)
Definition completions.c:54
asciichat_error_t completions_generate_for_shell(completion_format_t format, FILE *output)
Definition completions.c:20
const char * completions_get_shell_name(completion_format_t format)
Definition completions.c:39
bool platform_prompt_yes_no(const char *question, bool default_yes)
Definition util.c:81
FILE * platform_fopen(const char *filename, const char *mode)

References completions_generate_for_shell(), completions_get_shell_name(), completions_parse_shell_name(), platform_fopen(), and platform_prompt_yes_no().

Referenced by options_init().

◆ action_create_config()

void action_create_config ( const char *  output_path)

Definition at line 543 of file options/parsing/actions.c.

543 {
544 // Build the schema first so config_create_default can generate options from it
545 const options_config_t *unified_config = options_preset_unified(NULL, NULL);
546 if (unified_config) {
547 asciichat_error_t schema_build_result = config_schema_build_from_configs(&unified_config, 1);
548 if (schema_build_result != ASCIICHAT_OK) {
549 // Schema build failed, but continue anyway
550 (void)schema_build_result;
551 }
552 // options_config_destroy(unified_config);
553 }
554
555 const char *config_path = NULL;
556
557 // Determine output path: use provided path, or NULL for stdout
558 if (output_path && strlen(output_path) > 0 && strcmp(output_path, "-") != 0) {
559 // User provided explicit path - use it as-is
560 config_path = output_path;
561 } else {
562 // No path or "-" means stdout
563 config_path = NULL;
564 }
565
566 // Create config with default options
567 asciichat_error_t result = config_create_default(config_path);
568 if (result != ASCIICHAT_OK) {
569 asciichat_error_context_t err_ctx;
570 if (HAS_ERRNO(&err_ctx)) {
571 log_plain_stderr("Error creating config: %s", err_ctx.context_message);
572 } else {
573 log_plain_stderr("Error: Failed to create config file");
574 }
575 action_exit(ERROR_CONFIG);
576 }
577
578 if (config_path) {
579 log_plain_stderr("Created default config file at: %s", config_path);
580 } else {
581 log_plain_stderr("Config written to stdout");
582 }
583 action_exit(0);
584}
asciichat_error_t config_create_default(const char *config_path)
Definition config.c:1250
options_config_t * options_preset_unified(const char *program_name, const char *description)
Build unified options config with ALL options (binary + all modes)
Definition presets.c:51
asciichat_error_t config_schema_build_from_configs(const options_config_t **configs, size_t num_configs)
Definition schema.c:242

References config_create_default(), config_schema_build_from_configs(), and options_preset_unified().

Referenced by options_init().

◆ action_create_manpage()

void action_create_manpage ( const char *  output_path)

Definition at line 494 of file options/parsing/actions.c.

494 {
495 // Get binary-level config
496 const options_config_t *config = options_preset_unified(NULL, NULL);
497
498 if (!config) {
499 log_plain_stderr("Error: Failed to get binary options config");
500 action_exit(ERROR_FILE_OPERATION);
501 }
502
503 // Determine output path: use provided path, or NULL for stdout
504 const char *path_to_use = NULL;
505 if (output_path && strlen(output_path) > 0 && strcmp(output_path, "-") != 0) {
506 // User provided explicit path - use it
507 path_to_use = output_path;
508 } else {
509 // No path or "-" means stdout
510 path_to_use = NULL;
511 }
512
513 // Generate merged man page from embedded or filesystem resources
514 // Resources are loaded automatically based on build type:
515 // - Production (Release): From embedded binary data
516 // - Development (Debug): From filesystem files
517 asciichat_error_t err =
518 options_config_generate_manpage_merged(config, "ascii-chat", NULL, path_to_use, "Video chat in your terminal");
519
520 if (err != ASCIICHAT_OK) {
521 asciichat_error_context_t err_ctx;
522 if (HAS_ERRNO(&err_ctx)) {
523 log_plain_stderr("Error: %s", err_ctx.context_message);
524 } else {
525 log_plain_stderr("Error: Failed to generate man page");
526 }
527 action_exit(ERROR_FILE_OPERATION);
528 }
529
530 if (path_to_use) {
531 log_plain_stderr("Man page written to: %s", path_to_use);
532 } else {
533 log_plain_stderr("Man page written to stdout");
534 }
535
536 action_exit(0);
537}
asciichat_error_t options_config_generate_manpage_merged(const options_config_t *config, const char *program_name, const char *mode_name, const char *output_path, const char *brief_description)

References options_config_generate_manpage_merged(), and options_preset_unified().

Referenced by options_init().

◆ action_help_acds()

void action_help_acds ( void  )

Definition at line 480 of file options/parsing/actions.c.

480 {
481 usage(stdout, MODE_DISCOVERY_SERVICE);
482 action_exit(0);
483}
void usage(FILE *desc, asciichat_mode_t mode)

References usage().

◆ action_help_client()

void action_help_client ( void  )

Definition at line 470 of file options/parsing/actions.c.

470 {
471 usage(stdout, MODE_CLIENT);
472 action_exit(0);
473}

References usage().

◆ action_help_discovery()

void action_help_discovery ( void  )

Definition at line 485 of file options/parsing/actions.c.

485 {
486 usage(stdout, MODE_DISCOVERY);
487 action_exit(0);
488}

References usage().

◆ action_help_mirror()

void action_help_mirror ( void  )

Definition at line 475 of file options/parsing/actions.c.

475 {
476 usage(stdout, MODE_MIRROR);
477 action_exit(0);
478}

References usage().

◆ action_help_server()

void action_help_server ( void  )

Definition at line 465 of file options/parsing/actions.c.

465 {
466 usage(stdout, MODE_SERVER);
467 action_exit(0);
468}

References usage().

◆ action_list_microphones()

void action_list_microphones ( void  )

Definition at line 148 of file options/parsing/actions.c.

148 {
149 // Defer execution until after options are fully parsed
150 actions_defer(ACTION_LIST_MICROPHONES, NULL);
151}

References actions_defer().

Referenced by options_init(), and options_registry_add_all_to_builder().

◆ action_list_speakers()

void action_list_speakers ( void  )

Definition at line 194 of file options/parsing/actions.c.

194 {
195 // Defer execution until after options are fully parsed
196 actions_defer(ACTION_LIST_SPEAKERS, NULL);
197}

References actions_defer().

Referenced by options_init(), and options_registry_add_all_to_builder().

◆ action_list_webcams()

void action_list_webcams ( void  )

Definition at line 108 of file options/parsing/actions.c.

108 {
109 // Defer execution until after options are fully parsed
110 actions_defer(ACTION_LIST_WEBCAMS, NULL);
111}

References actions_defer().

Referenced by options_init(), and options_registry_add_all_to_builder().

◆ action_show_capabilities()

void action_show_capabilities ( void  )

Definition at line 317 of file options/parsing/actions.c.

317 {
318 // Defer execution until after options are fully parsed and dimensions updated
319 // This ensures --width and --height flags are properly reflected in the output
320 actions_defer(ACTION_SHOW_CAPABILITIES, NULL);
321}

References actions_defer().

Referenced by options_registry_add_all_to_builder().

◆ action_show_capabilities_immediate()

void action_show_capabilities_immediate ( void  )

Execute show capabilities immediately (for early binary-level execution)

Definition at line 247 of file options/parsing/actions.c.

247 {
248 terminal_capabilities_t caps = detect_terminal_capabilities();
249
250 // Determine if we should use colored output
251 bool use_colors = terminal_should_color_output(STDOUT_FILENO);
252
253 // Override color level if colors should not be shown
254 if (!use_colors) {
255 caps.color_level = TERM_COLOR_NONE;
256 caps.color_count = 0;
257 caps.capabilities &= ~((uint32_t)(TERM_CAP_COLOR_TRUE | TERM_CAP_COLOR_256 | TERM_CAP_COLOR_16));
258 }
259
260 // Use detected terminal size (immediate execution doesn't have parsed options yet)
261 terminal_size_t size;
262 terminal_get_size(&size);
263 unsigned short width = size.cols;
264 unsigned short height = size.rows;
265
266 log_color_t label_color = use_colors ? LOG_COLOR_GREY : LOG_COLOR_GREY;
267 log_color_t string_color = use_colors ? LOG_COLOR_DEBUG : LOG_COLOR_GREY;
268 log_color_t good_color = use_colors ? LOG_COLOR_INFO : LOG_COLOR_GREY;
269 log_color_t bad_color = use_colors ? LOG_COLOR_ERROR : LOG_COLOR_GREY;
270 log_color_t number_color = use_colors ? LOG_COLOR_FATAL : LOG_COLOR_GREY;
271
272 printf("%s\n", colored_string(LOG_COLOR_WARN, "Terminal Capabilities:"));
273
274 char size_buf[64];
275 snprintf(size_buf, sizeof(size_buf), "%ux%u", width, height);
276 printf(" %s: %s\n", colored_string(label_color, "Terminal Size"), colored_string(number_color, size_buf));
277
278 const char *color_level_name = terminal_color_level_name(caps.color_level);
279 log_color_t color_level_color = (caps.color_level == TERM_COLOR_NONE) ? bad_color : string_color;
280 printf(" %s: %s\n", colored_string(label_color, "Color Level"),
281 colored_string(color_level_color, (char *)color_level_name));
282
283 char colors_buf[64];
284 snprintf(colors_buf, sizeof(colors_buf), "%u", caps.color_count);
285 printf(" %s: %s\n", colored_string(label_color, "Max Colors"), colored_string(number_color, colors_buf));
286
287 log_color_t utf8_color = caps.utf8_support ? good_color : bad_color;
288 printf(" %s: %s\n", colored_string(label_color, "UTF-8 Support"),
289 colored_string(utf8_color, (char *)(caps.utf8_support ? "Yes" : "No")));
290
291 const char *render_mode_str = "unknown";
292 if (caps.render_mode == RENDER_MODE_FOREGROUND) {
293 render_mode_str = "foreground";
294 } else if (caps.render_mode == RENDER_MODE_BACKGROUND) {
295 render_mode_str = "background";
296 } else if (caps.render_mode == RENDER_MODE_HALF_BLOCK) {
297 render_mode_str = "half-block";
298 }
299 printf(" %s: %s\n", colored_string(label_color, "Render Mode"),
300 colored_string(string_color, (char *)render_mode_str));
301 printf(" %s: %s\n", colored_string(label_color, "TERM"), colored_string(string_color, (char *)caps.term_type));
302 printf(" %s: %s\n", colored_string(label_color, "COLORTERM"),
303 colored_string(string_color, (char *)(strlen(caps.colorterm) ? caps.colorterm : "(not set)")));
304
305 log_color_t reliable_color = caps.detection_reliable ? good_color : bad_color;
306 printf(" %s: %s\n", colored_string(label_color, "Detection Reliable"),
307 colored_string(reliable_color, (char *)(caps.detection_reliable ? "Yes" : "No")));
308
309 char bitmask_buf[64];
310 snprintf(bitmask_buf, sizeof(bitmask_buf), "0x%08x", caps.capabilities);
311 printf(" %s: %s\n", colored_string(label_color, "Capabilities Bitmask"), colored_string(number_color, bitmask_buf));
312
313 fflush(stdout);
314 action_exit(0);
315}
bool terminal_should_color_output(int fd)
Determine if color output should be used.
asciichat_error_t terminal_get_size(terminal_size_t *size)
terminal_capabilities_t detect_terminal_capabilities(void)
const char * colored_string(log_color_t color, const char *text)

References colored_string(), detect_terminal_capabilities(), terminal_get_size(), and terminal_should_color_output().

Referenced by options_init().

◆ action_show_version()

void action_show_version ( void  )

Definition at line 447 of file options/parsing/actions.c.

447 {
448 bool use_colors = terminal_should_color_output(STDOUT_FILENO);
449 if (use_colors) {
450 printf("%s %s (%s, %s)\n", colored_string(LOG_COLOR_WARN, "ascii-chat"),
451 colored_string(LOG_COLOR_INFO, (char *)ASCII_CHAT_VERSION_FULL),
452 colored_string(LOG_COLOR_DEBUG, (char *)ASCII_CHAT_BUILD_TYPE),
453 colored_string(LOG_COLOR_GREY, (char *)ASCII_CHAT_BUILD_DATE));
454 } else {
455 printf("ascii-chat %s (%s, %s)\n", ASCII_CHAT_VERSION_FULL, ASCII_CHAT_BUILD_TYPE, ASCII_CHAT_BUILD_DATE);
456 }
457
458 action_exit(0);
459}

References colored_string(), and terminal_should_color_output().

Referenced by main().

◆ actions_defer()

void actions_defer ( deferred_action_t  action,
const action_args_t *  args 
)

Definition at line 76 of file options/parsing/actions.c.

76 {
77 // Only remember the first action found
78 if (g_deferred_action_state.has_action) {
79 return; // Action already deferred, ignore subsequent actions
80 }
81
82 g_deferred_action_state.action = action;
83 g_deferred_action_state.has_action = true;
84
85 // Copy arguments if provided
86 if (args) {
87 memcpy(&g_deferred_action_state.args, args, sizeof(action_args_t));
88 } else {
89 memset(&g_deferred_action_state.args, 0, sizeof(action_args_t));
90 }
91}
action_args_t args
deferred_action_t action

References action, and args.

Referenced by action_check_update(), action_list_microphones(), action_list_speakers(), action_list_webcams(), and action_show_capabilities().

◆ actions_execute_deferred()

void actions_execute_deferred ( void  )

Definition at line 681 of file options/parsing/actions.c.

681 {
682 deferred_action_t action = actions_get_deferred();
683
684 switch (action) {
685 case ACTION_NONE:
686 // No action to execute
687 break;
688
689 case ACTION_LIST_WEBCAMS:
690 execute_list_webcams();
691 break;
692
693 case ACTION_LIST_MICROPHONES:
694 execute_list_microphones();
695 break;
696
697 case ACTION_LIST_SPEAKERS:
698 execute_list_speakers();
699 break;
700
701 case ACTION_SHOW_CAPABILITIES:
702 execute_show_capabilities();
703 break;
704
705 case ACTION_CHECK_UPDATE:
706 execute_check_update();
707 break;
708
709 default:
710 log_warn("Unknown deferred action: %d", action);
711 break;
712 }
713}
deferred_action_t actions_get_deferred(void)

References action, and actions_get_deferred().

Referenced by options_init().

◆ actions_get_args()

const action_args_t * actions_get_args ( void  )

Definition at line 97 of file options/parsing/actions.c.

97 {
98 if (!g_deferred_action_state.has_action) {
99 return NULL;
100 }
101 return &g_deferred_action_state.args;
102}

◆ actions_get_deferred()

deferred_action_t actions_get_deferred ( void  )

Definition at line 93 of file options/parsing/actions.c.

93 {
94 return g_deferred_action_state.action;
95}

Referenced by actions_execute_deferred().

Variable Documentation

◆ action

deferred_action_t action

Definition at line 67 of file options/parsing/actions.c.

Referenced by actions_defer(), and actions_execute_deferred().

◆ args

◆ has_action

bool has_action

Definition at line 69 of file options/parsing/actions.c.

Referenced by options_init().