ascii-chat 0.6.0
Real-time terminal-based video chat with ASCII art conversion
Loading...
Searching...
No Matches
presets.c
Go to the documentation of this file.
1
7#include "builder.h"
8#include "options.h"
9#include "parsers.h"
10#include "actions.h"
11#include "common.h"
12#include "platform/terminal.h"
13#include "video/palette.h"
14#include "log/logging.h"
15
16// ============================================================================
17// Binary-Level Options Helper
18// ============================================================================
19
26static bool parse_verbose_flag(const char *arg, void *dest, char **error_msg) {
27 // If arg is NULL or starts with a flag, just increment
28 // Otherwise try to parse as integer count
29 unsigned short int *verbose_level = (unsigned short int *)dest;
30
31 if (!arg || arg[0] == '\0') {
32 // No argument provided, just increment
33 (*verbose_level)++;
34 return true;
35 }
36
37 // Try to parse as integer count
38 char *endptr;
39 long value = strtol(arg, &endptr, 10);
40 if (*endptr == '\0' && value >= 0 && value <= 100) {
41 *verbose_level = (unsigned short int)value;
42 return true;
43 }
44
45 // If it didn't parse as int, treat as flag increment
46 (*verbose_level)++;
47 return true;
48}
49
56static void add_binary_logging_options(options_builder_t *b) {
57 options_builder_add_string(b, "log-file", 'L', offsetof(options_t, log_file), "", "Redirect logs to FILE", "LOGGING",
58 false, "ASCII_CHAT_LOG_FILE", NULL);
59
60 options_builder_add_callback(b, "log-level", '\0', offsetof(options_t, log_level),
61 &(log_level_t){LOG_INFO}, // Default: info level
63 "Set log level: dev, debug, info, warn, error, fatal", "LOGGING", false, NULL);
64
65 options_builder_add_callback_optional(b, "verbose", 'V', offsetof(options_t, verbose_level),
66 &(unsigned short int){0}, // Default: 0 (no extra verbosity)
67 sizeof(unsigned short int), parse_verbose_flag,
68 "Increase log verbosity (stackable: -VV, -VVV, or --verbose)", "LOGGING", false,
69 NULL,
70 true); // optional_arg = true
71
72 options_builder_add_bool(b, "quiet", 'q', offsetof(options_t, quiet), false,
73 "Disable console logging (log to file only)", "LOGGING", false, NULL);
74}
75
76// ============================================================================
77// Webcam & Display Options Helper (Client + Mirror)
78// ============================================================================
79
84static void add_terminal_dimension_options(options_builder_t *b) {
85 options_builder_add_int(b, "width", 'x', offsetof(options_t, width), OPT_WIDTH_DEFAULT,
86 "Terminal width in characters", "TERMINAL", false, NULL, NULL);
87
88 options_builder_add_int(b, "height", 'y', offsetof(options_t, height), OPT_HEIGHT_DEFAULT,
89 "Terminal height in characters", "TERMINAL", false, NULL, NULL);
90}
91
96static void add_webcam_options(options_builder_t *b) {
97 options_builder_add_int(b, "webcam-index", 'c', offsetof(options_t, webcam_index), OPT_WEBCAM_INDEX_DEFAULT,
98 "Webcam device index", "WEBCAM", false, NULL, NULL);
99
100 options_builder_add_bool(b, "webcam-flip", 'f', offsetof(options_t, webcam_flip), OPT_WEBCAM_FLIP_DEFAULT,
101 "Flip webcam horizontally", "WEBCAM", false, NULL);
102
103 options_builder_add_bool(b, "test-pattern", '\0', offsetof(options_t, test_pattern), false,
104 "Use test pattern instead of webcam", "WEBCAM", false, "WEBCAM_DISABLED");
105}
106
111static void add_display_options(options_builder_t *b) {
112 options_builder_add_callback(b, "color-mode", '\0', offsetof(options_t, color_mode),
113 &(terminal_color_mode_t){TERM_COLOR_AUTO}, // Auto-detect by default
115 "Terminal color level (auto, none, 16, 256, truecolor)", "DISPLAY", false, NULL);
116
117 options_builder_add_callback(b, "render-mode", 'M', offsetof(options_t, render_mode),
118 &(render_mode_t){RENDER_MODE_FOREGROUND}, // Default: foreground
120 "Render mode (foreground, background, half-block)", "DISPLAY", false, NULL);
121
123 b, "palette", 'P', offsetof(options_t, palette_type), &(palette_type_t){PALETTE_STANDARD}, // Default: standard
125 "ASCII palette type (standard, blocks, digital, minimal, cool, custom)", "DISPLAY", false, NULL);
126
127 options_builder_add_callback(b, "palette-chars", 'C', offsetof(options_t, palette_custom), "",
128 sizeof(((options_t *)0)->palette_custom), parse_palette_chars,
129 "Custom palette characters (implies --palette=custom)", "DISPLAY", false, NULL);
130
131 options_builder_add_bool(b, "show-capabilities", '\0', offsetof(options_t, show_capabilities), false,
132 "Show terminal capabilities and exit", "DISPLAY", false, NULL);
133
134 options_builder_add_bool(b, "utf8", '\0', offsetof(options_t, force_utf8), false, "Force UTF-8 support", "DISPLAY",
135 false, NULL);
136
137 options_builder_add_bool(b, "stretch", 's', offsetof(options_t, stretch), false, "Allow aspect ratio distortion",
138 "DISPLAY", false, NULL);
139
140 options_builder_add_bool(b, "strip-ansi", '\0', offsetof(options_t, strip_ansi), false, "Strip ANSI escape sequences",
141 "DISPLAY", false, NULL);
142
143 options_builder_add_int(b, "fps", '\0', offsetof(options_t, fps), 0, "Target framerate (1-144, default: 60)",
144 "DISPLAY", false, NULL, NULL);
145}
146
151static void add_snapshot_options(options_builder_t *b) {
152 options_builder_add_bool(b, "snapshot", 'S', offsetof(options_t, snapshot_mode), false,
153 "Snapshot mode (one frame and exit)", "SNAPSHOT", false, NULL);
154
155 options_builder_add_double(b, "snapshot-delay", 'D', offsetof(options_t, snapshot_delay), SNAPSHOT_DELAY_DEFAULT,
156 "Snapshot delay in seconds", "SNAPSHOT", false, NULL, NULL);
157}
158
159// ============================================================================
160// Compression Options Helper (Client + Server)
161// ============================================================================
162
167static void add_compression_options(options_builder_t *b) {
168 options_builder_add_int(b, "compression-level", '\0', offsetof(options_t, compression_level),
169 OPT_COMPRESSION_LEVEL_DEFAULT, "zstd compression level (1-9)", "PERFORMANCE", false, NULL,
170 NULL);
171
172 options_builder_add_bool(b, "no-compress", '\0', offsetof(options_t, no_compress), false, "Disable compression",
173 "PERFORMANCE", false, NULL);
174
175 options_builder_add_bool(b, "encode-audio", '\0', offsetof(options_t, encode_audio), OPT_ENCODE_AUDIO_DEFAULT,
176 "Enable Opus audio encoding", "PERFORMANCE", false, NULL);
177
178 options_builder_add_bool(b, "no-encode-audio", '\0', offsetof(options_t, encode_audio), !OPT_ENCODE_AUDIO_DEFAULT,
179 "Disable Opus audio encoding", "PERFORMANCE", false, NULL);
180}
181
182// ============================================================================
183// Crypto/Security Options Helper (Client + Server)
184// ============================================================================
185
191static void add_crypto_common_options(options_builder_t *b) {
192 options_builder_add_bool(b, "encrypt", 'E', offsetof(options_t, encrypt_enabled), false, "Enable encryption",
193 "SECURITY", false, NULL);
194
195 options_builder_add_string(b, "key", 'K', offsetof(options_t, encrypt_key), "", "SSH/GPG key file path", "SECURITY",
196 false, "ASCII_CHAT_KEY", NULL);
197
198 options_builder_add_string(b, "password", '\0', offsetof(options_t, password), "",
199 "Shared password for authentication", "SECURITY", false, "ASCII_CHAT_PASSWORD", NULL);
200
201 options_builder_add_string(b, "keyfile", 'F', offsetof(options_t, encrypt_keyfile), "", "Alternative key file path",
202 "SECURITY", false, NULL, NULL);
203}
204
205// ============================================================================
206// Port Option Helper (Server + Client + ACDS)
207// ============================================================================
208
216static void add_port_option(options_builder_t *b, const char *default_port, const char *env_var) {
217 options_builder_add_string(b, "port", 'p', offsetof(options_t, port), default_port, "Server port", "NETWORK", false,
218 env_var, NULL);
219}
220
221// ============================================================================
222// ACDS Discovery Options Helper (Client + Server)
223// ============================================================================
224
229static void add_acds_discovery_options(options_builder_t *b) {
230 options_builder_add_string(b, "acds-server", '\0', offsetof(options_t, acds_server), "127.0.0.1",
231 "ACDS discovery server address (default: 127.0.0.1)", "DISCOVERY", false, NULL, NULL);
232
233 options_builder_add_int(b, "acds-port", '\0', offsetof(options_t, acds_port), 27225, "ACDS discovery server port",
234 "DISCOVERY", false, NULL, NULL);
235
236 options_builder_add_bool(b, "webrtc", '\0', offsetof(options_t, webrtc), false,
237 "Use WebRTC P2P mode (default: Direct TCP)", "DISCOVERY", false, NULL);
238}
239
240// ============================================================================
241// Positional Argument Examples (Programmatic Help)
242// ============================================================================
243
249static const char *g_server_bind_address_examples[] = {
250 "(none) bind to 127.0.0.1 and ::1 (localhost)",
251 "192.168.1.100 bind to IPv4 address only", ":: bind to all IPv6 addresses",
252 "0.0.0.0 bind to all IPv4 addresses",
253 "192.168.1.100 :: bind to IPv4 and IPv6 (dual-stack)"};
254
260static const char *g_client_address_examples[] = {
261 "(none) connect to localhost:27224",
262 "hostname connect to hostname:27224",
263 "hostname:port connect to hostname:port",
264 "192.168.1.1 connect to IPv4:27224",
265 "192.168.1.1:8080 connect to IPv4:port",
266 "::1 connect to IPv6:27224",
267 "[::1]:8080 connect to IPv6:port (brackets required with port)"};
268
269// ============================================================================
270// Binary-Level Options Preset
271// ============================================================================
272
273const options_config_t *options_preset_binary(const char *program_name, const char *description) {
274 // Note: Each call creates a new config (no static caching) since program_name/description vary
276 if (!b)
277 return NULL;
278
279 b->program_name = program_name ? program_name : "ascii-chat";
280 b->description = description ? description : "Video chat in your terminal";
281
282 // Help and version
283 options_builder_add_bool(b, "help", '\0', offsetof(options_t, help), false, "Show this help", "GENERAL", false, NULL);
284
285 options_builder_add_bool(b, "version", '\0', offsetof(options_t, version), false, "Show version information",
286 "GENERAL", false, NULL);
287
288 // Add logging options
289 add_binary_logging_options(b);
290
291 const options_config_t *config = options_builder_build(b);
293 return config;
294}
295
296// ============================================================================
297// Server Mode Options Preset
298// ============================================================================
299
300const options_config_t *options_preset_server(const char *program_name, const char *description) {
301 // Note: Each call creates a new config (no static caching) since program_name/description vary
303 if (!b)
304 return NULL;
305
306 b->program_name = program_name ? program_name : "ascii-chat server";
307 b->description = description ? description : "Start ascii-chat server";
308
309 // Network options
310 // Note: Server bind addresses are positional arguments only, not flags
311 add_port_option(b, OPT_PORT_DEFAULT, "ASCII_CHAT_PORT");
312
313 options_builder_add_int(b, "max-clients", '\0', offsetof(options_t, max_clients), OPT_MAX_CLIENTS_DEFAULT,
314 "Maximum concurrent clients", "NETWORK", false, "ASCII_CHAT_MAX_CLIENTS", NULL);
315
316 // Compression and audio encoding options (shared with client)
317 add_compression_options(b);
318
319 options_builder_add_bool(b, "no-audio-mixer", '\0', offsetof(options_t, no_audio_mixer), false,
320 "Disable audio mixer (debug)", "PERFORMANCE", false, NULL);
321
322 // Security options (common with client, plus server-specific client-keys and no-encrypt)
323 add_crypto_common_options(b);
324
325 options_builder_add_string(b, "client-keys", '\0', offsetof(options_t, client_keys), "",
326 "Allowed client keys whitelist", "SECURITY", false, NULL, NULL);
327
328 options_builder_add_bool(b, "acds-expose-ip", '\0', offsetof(options_t, acds_expose_ip), false,
329 "Explicitly allow public IP disclosure in ACDS sessions (requires ACDS, opt-in only)",
330 "SECURITY", false, NULL);
331
332 options_builder_add_bool(b, "no-encrypt", '\0', offsetof(options_t, no_encrypt), false, "Disable encryption",
333 "SECURITY", false, NULL);
334
335 // ACDS Session Registration
336 options_builder_add_bool(b, "acds", '\0', offsetof(options_t, acds), false,
337 "Enable ACDS session registration (requires --key or --password or --acds-expose-ip)",
338 "DISCOVERY", false, NULL);
339
340 // ACDS Discovery options (shared with client)
341 add_acds_discovery_options(b);
342
343 options_builder_add_bool(b, "upnp", '\0', offsetof(options_t, enable_upnp), true,
344 "Enable UPnP/NAT-PMP for automatic port mapping (enables direct TCP for most home users)",
345 "DISCOVERY", false, "ASCII_CHAT_UPNP");
346
347 options_builder_add_bool(b, "no-upnp", '\0', offsetof(options_t, no_upnp), false,
348 "Disable UPnP/NAT-PMP port mapping (requires manual port forwarding)", "DISCOVERY", false,
349 NULL);
350
351 options_builder_add_bool(b, "no-mdns-advertise", '\0', offsetof(options_t, no_mdns_advertise), false,
352 "Disable mDNS service advertisement on local network (LAN discovery won't find this server)",
353 "DISCOVERY", false, NULL);
354
355 // Add binary-level logging options (--log-file, --log-level, -V, -q)
356 // These work before or after the mode name
357 add_binary_logging_options(b);
358
359 // Dependencies
360 options_builder_add_dependency_conflicts(b, "no-encrypt", "encrypt", "Cannot use --no-encrypt with --encrypt");
361 options_builder_add_dependency_conflicts(b, "no-encrypt", "key", "Cannot use --no-encrypt with --key");
362 options_builder_add_dependency_conflicts(b, "no-encrypt", "password", "Cannot use --no-encrypt with --password");
363 options_builder_add_dependency_conflicts(b, "no-compress", "compression-level",
364 "Cannot use --no-compress with --compression-level");
365 options_builder_add_dependency_conflicts(b, "encode-audio", "no-encode-audio",
366 "Cannot use both --encode-audio and --no-encode-audio");
367
368 // Action options (execute and exit)
369 options_builder_add_action(b, "help", 'h', action_help_server, "Show this help message and exit", "ACTIONS");
370
371 options_builder_add_action(b, "list-webcams", '\0', action_list_webcams, "List available webcam devices and exit",
372 "ACTIONS");
373
374 options_builder_add_action(b, "list-microphones", '\0', action_list_microphones,
375 "List available microphone devices and exit", "ACTIONS");
376
377 options_builder_add_action(b, "list-speakers", '\0', action_list_speakers, "List available speaker devices and exit",
378 "ACTIONS");
379
380 options_builder_add_action(b, "version", 'V', action_show_version, "Show version information and exit", "ACTIONS");
381
382 // Positional arguments: 0-2 bind addresses (IPv4 and/or IPv6)
383 options_builder_add_positional(b, "bind-address", "IPv4 or IPv6 bind address (can specify 0-2 addresses)",
384 false, // Not required (defaults to localhost)
385 "BIND ADDRESS FORMATS", g_server_bind_address_examples,
386 sizeof(g_server_bind_address_examples) / sizeof(g_server_bind_address_examples[0]),
388
389 const options_config_t *config = options_builder_build(b);
391 return config;
392}
393
394// ============================================================================
395// Client Mode Options Preset
396// ============================================================================
397
398const options_config_t *options_preset_client(const char *program_name, const char *description) {
399 // Note: Each call creates a new config (no static caching) since program_name/description vary
401 if (!b)
402 return NULL;
403
404 b->program_name = program_name ? program_name : "ascii-chat client";
405 b->description = description ? description : "Connect to ascii-chat server";
406
407 // Network options
408 // Note: Server address and port are specified via positional argument [address][:port], not flags
409 add_port_option(b, OPT_PORT_DEFAULT, "ASCII_CHAT_PORT");
410
411 options_builder_add_int(b, "reconnect", 'r', offsetof(options_t, reconnect_attempts), OPT_RECONNECT_ATTEMPTS_DEFAULT,
412 "Reconnection attempts (-1=infinite)", "NETWORK", false, NULL, NULL);
413
414 options_builder_add_bool(b, "scan", '\0', offsetof(options_t, lan_discovery), false,
415 "Scan for ASCII-Chat servers on local network (mDNS)", "NETWORK", false, NULL);
416
417 // Terminal dimensions, webcam, display, and snapshot options (shared with mirror)
418 add_terminal_dimension_options(b);
419 add_webcam_options(b);
420 add_display_options(b);
421 add_snapshot_options(b);
422
423 // Audio options
424 options_builder_add_bool(b, "audio", 'A', offsetof(options_t, audio_enabled), false, "Enable audio streaming",
425 "AUDIO", false, NULL);
426
427 options_builder_add_int(b, "microphone-index", '\0', offsetof(options_t, microphone_index),
428 OPT_MICROPHONE_INDEX_DEFAULT, "Microphone device index (-1=default)", "AUDIO", false, NULL,
429 NULL);
430
431 options_builder_add_int(b, "speakers-index", '\0', offsetof(options_t, speakers_index), OPT_SPEAKERS_INDEX_DEFAULT,
432 "Speakers device index (-1=default)", "AUDIO", false, NULL, NULL);
433
434 options_builder_add_bool(b, "audio-analysis", '\0', offsetof(options_t, audio_analysis_enabled), false,
435 "Enable audio analysis (debug)", "AUDIO", false, NULL);
436
437 options_builder_add_bool(b, "no-audio-playback", '\0', offsetof(options_t, audio_no_playback), false,
438 "Disable speaker playback (debug)", "AUDIO", false, NULL);
439
440 // Compression and audio encoding options (shared with server)
441 add_compression_options(b);
442
443 // ACDS Discovery options (shared with server)
444 add_acds_discovery_options(b);
445
446 // WebRTC Connection Strategy Options (Phase 3 fallback control)
447 options_builder_add_bool(b, "prefer-webrtc", '\0', offsetof(options_t, prefer_webrtc), false,
448 "Try WebRTC before Direct TCP (useful when Direct TCP fails)", "NETWORK", false, NULL);
449
450 options_builder_add_bool(b, "no-webrtc", '\0', offsetof(options_t, no_webrtc), false,
451 "Disable WebRTC, use Direct TCP only", "NETWORK", false, NULL);
452
453 options_builder_add_bool(b, "webrtc-skip-stun", '\0', offsetof(options_t, webrtc_skip_stun), false,
454 "Skip WebRTC+STUN stage, go straight to TURN relay", "NETWORK", false, NULL);
455
456 options_builder_add_bool(b, "webrtc-disable-turn", '\0', offsetof(options_t, webrtc_disable_turn), false,
457 "Disable WebRTC+TURN relay, use STUN only", "NETWORK", false, NULL);
458
459 // WebRTC Server Configuration (for testing/debugging - production uses ACDS)
460 // Note: In production, ACDS provides these automatically via SESSION_JOINED response
461 options_builder_add_string(b, "stun-servers", '\0', offsetof(options_t, stun_servers), "",
462 "Comma-separated STUN server URLs (debug/test only - ACDS provides in production)",
463 "WEBRTC", false, "ASCII_CHAT_STUN_SERVERS", NULL);
464
465 options_builder_add_string(b, "turn-servers", '\0', offsetof(options_t, turn_servers), "",
466 "Comma-separated TURN server URLs (debug/test only - ACDS provides in production)",
467 "WEBRTC", false, "ASCII_CHAT_TURN_SERVERS", NULL);
468
469 options_builder_add_string(b, "turn-username", '\0', offsetof(options_t, turn_username), "",
470 "TURN authentication username (debug/test only - ACDS provides in production)", "WEBRTC",
471 false, "ASCII_CHAT_TURN_USERNAME", NULL);
472
473 options_builder_add_string(b, "turn-credential", '\0', offsetof(options_t, turn_credential), "",
474 "TURN authentication credential (debug/test only - ACDS provides in production)", "WEBRTC",
475 false, "ASCII_CHAT_TURN_CREDENTIAL", NULL);
476
477 // Security options (common with server, plus client-specific server-key)
478 add_crypto_common_options(b);
479
480 options_builder_add_string(b, "server-key", '\0', offsetof(options_t, server_key), "", "Expected server public key",
481 "SECURITY", false, NULL, NULL);
482
483 options_builder_add_bool(b, "acds-insecure", '\0', offsetof(options_t, acds_insecure), false,
484 "Skip server key verification (MITM-vulnerable, requires explicit opt-in)", "SECURITY",
485 false, NULL);
486
487 // Add binary-level logging options (--log-file, --log-level, -V, -q)
488 // These work before or after the mode name
489 add_binary_logging_options(b);
490
491 // Dependencies
492 options_builder_add_dependency_requires(b, "snapshot-delay", "snapshot",
493 "Option --snapshot-delay requires --snapshot");
494 options_builder_add_dependency_conflicts(b, "no-compress", "compression-level",
495 "Cannot use --no-compress with --compression-level");
496 options_builder_add_dependency_conflicts(b, "encode-audio", "no-encode-audio",
497 "Cannot use both --encode-audio and --no-encode-audio");
498
499 // Action options (execute and exit)
500 options_builder_add_action(b, "help", 'h', action_help_client, "Show this help message and exit", "ACTIONS");
501
502 options_builder_add_action(b, "list-webcams", '\0', action_list_webcams, "List available webcam devices and exit",
503 "ACTIONS");
504
505 options_builder_add_action(b, "list-microphones", '\0', action_list_microphones,
506 "List available microphone devices and exit", "ACTIONS");
507
508 options_builder_add_action(b, "list-speakers", '\0', action_list_speakers, "List available speaker devices and exit",
509 "ACTIONS");
510
511 options_builder_add_action(b, "show-capabilities", '\0', action_show_capabilities,
512 "Show terminal capabilities and exit", "ACTIONS");
513
514 // Positional argument: [address][:port]
516 b, "address", "[address][:port] - Server address (IPv4, IPv6, or hostname) with optional port",
517 false, // Not required (defaults to localhost:27224)
518 "ADDRESS FORMATS", g_client_address_examples,
519 sizeof(g_client_address_examples) / sizeof(g_client_address_examples[0]), parse_client_address);
520
521 const options_config_t *config = options_builder_build(b);
523 return config;
524}
525
526// ============================================================================
527// Mirror Mode Options Preset
528// ============================================================================
529
530const options_config_t *options_preset_mirror(const char *program_name, const char *description) {
531 // Note: Each call creates a new config (no static caching) since program_name/description vary
533 if (!b)
534 return NULL;
535
536 b->program_name = program_name ? program_name : "ascii-chat mirror";
537 b->description = description ? description : "Local webcam viewing (no network)";
538
539 // Terminal dimensions, webcam, display, and snapshot options (shared with client)
540 add_terminal_dimension_options(b);
541 add_webcam_options(b);
542 add_display_options(b);
543 add_snapshot_options(b);
544
545 // Add binary-level logging options (--log-file, --log-level, -V, -q)
546 // These work before or after the mode name
547 add_binary_logging_options(b);
548
549 // Dependencies
550 options_builder_add_dependency_requires(b, "snapshot-delay", "snapshot",
551 "Option --snapshot-delay requires --snapshot");
552
553 // Action options (execute and exit)
554 options_builder_add_action(b, "help", 'h', action_help_mirror, "Show this help message and exit", "ACTIONS");
555
556 options_builder_add_action(b, "list-webcams", '\0', action_list_webcams, "List available webcam devices and exit",
557 "ACTIONS");
558
559 options_builder_add_action(b, "show-capabilities", '\0', action_show_capabilities,
560 "Show terminal capabilities and exit", "ACTIONS");
561
562 const options_config_t *config = options_builder_build(b);
564 return config;
565}
566
567// ============================================================================
568// ACDS Mode Options Preset
569// ============================================================================
570
571const options_config_t *options_preset_acds(const char *program_name, const char *description) {
572 // Note: Each call creates a new config (no static caching) since program_name/description vary
574 if (!b)
575 return NULL;
576
577 b->program_name = program_name ? program_name : "ascii-chat discovery service";
578 b->description = description ? description : "session management and WebRTC signaling";
579
580 // Help and version
581 options_builder_add_bool(b, "help", 'h', offsetof(options_t, help), false, "Show this help", "GENERAL", false, NULL);
582
583 // Network options
584 // Note: Bind addresses are specified via positional arguments, not flags
585 add_port_option(b, "27225", "ACDS_PORT");
586
587 // ACDS-specific options
588 options_builder_add_string(b, "key", 'k', offsetof(options_t, acds_key_path), "",
589 "Path to ACDS identity key file (default: ~/.ascii-chat/acds_identity)", "ACDS", false,
590 "ACDS_KEY_PATH", NULL);
591
592 options_builder_add_string(b, "database", 'd', offsetof(options_t, acds_database_path), "",
593 "Path to ACDS database file (default: ~/.ascii-chat/acds.db)", "ACDS", false,
594 "ACDS_DATABASE_PATH", NULL);
595
596 // Logging options (binary-level, work before or after mode name)
597 // Note: ACDS uses partial logging options due to short name conflicts with identity verification options
598 options_builder_add_string(b, "log-file", 'L', offsetof(options_t, log_file), "", "Redirect logs to FILE", "LOGGING",
599 false, "ASCII_CHAT_LOG_FILE", NULL);
600
601 options_builder_add_callback(b, "log-level", '\0', offsetof(options_t, log_level), &(log_level_t){LOG_INFO},
603 "Set log level: dev, debug, info, warn, error, fatal", "LOGGING", false, NULL);
604
605 // Encryption options (shared with client and server)
606 options_builder_add_bool(b, "encrypt", 'E', offsetof(options_t, encrypt_enabled), false, "Enable encryption",
607 "SECURITY", false, NULL);
608
609 options_builder_add_string(b, "key", 'K', offsetof(options_t, encrypt_key), "", "SSH/GPG key file path", "SECURITY",
610 false, "ASCII_CHAT_KEY", NULL);
611
612 options_builder_add_string(b, "password", '\0', offsetof(options_t, password), "",
613 "Shared password for authentication", "SECURITY", false, "ASCII_CHAT_PASSWORD", NULL);
614
615 options_builder_add_string(b, "keyfile", 'F', offsetof(options_t, encrypt_keyfile), "", "Alternative key file path",
616 "SECURITY", false, NULL, NULL);
617
618 options_builder_add_bool(b, "no-encrypt", '\0', offsetof(options_t, no_encrypt), false, "Disable encryption",
619 "SECURITY", false, NULL);
620
621 // Identity verification options
622 options_builder_add_bool(b, "require-server-identity", 'S', offsetof(options_t, require_server_identity), false,
623 "Require servers to provide signed Ed25519 identity when creating sessions", "SECURITY",
624 false, NULL);
625
626 options_builder_add_bool(b, "require-client-identity", 'C', offsetof(options_t, require_client_identity), false,
627 "Require clients to provide signed Ed25519 identity when joining sessions", "SECURITY",
628 false, NULL);
629
630 options_builder_add_bool(b, "require-server-verify", 'V', offsetof(options_t, require_server_verify), false,
631 "ACDS policy: require servers to verify client identity during handshake", "SECURITY", false,
632 NULL);
633
634 options_builder_add_bool(b, "require-client-verify", 'c', offsetof(options_t, require_client_verify), false,
635 "ACDS policy: require clients to verify server identity during handshake", "SECURITY", false,
636 NULL);
637
638 // WebRTC connectivity options
639 options_builder_add_string(b, "stun-servers", '\0', offsetof(options_t, stun_servers),
640 "stun:stun.ascii-chat.com:3478,stun:stun.l.google.com:19302",
641 "Comma-separated list of STUN server URLs", "WEBRTC", false, "ASCII_CHAT_STUN_SERVERS",
642 NULL);
643
644 options_builder_add_string(b, "turn-servers", '\0', offsetof(options_t, turn_servers),
645 "turn:turn.ascii-chat.com:3478", "Comma-separated list of TURN server URLs", "WEBRTC",
646 false, "ASCII_CHAT_TURN_SERVERS", NULL);
647
648 options_builder_add_string(b, "turn-username", '\0', offsetof(options_t, turn_username), "ascii",
649 "Username for TURN server authentication", "WEBRTC", false, "ASCII_CHAT_TURN_USERNAME",
650 NULL);
651
652 options_builder_add_string(b, "turn-credential", '\0', offsetof(options_t, turn_credential),
653 "0aa9917b4dad1b01631e87a32b875e09", "Credential/password for TURN server authentication",
654 "WEBRTC", false, "ASCII_CHAT_TURN_CREDENTIAL", NULL);
655
656 options_builder_add_string(b, "turn-secret", '\0', offsetof(options_t, turn_secret), "",
657 "Shared secret for dynamic TURN credential generation (HMAC-SHA1)", "WEBRTC", false,
658 "ASCII_CHAT_TURN_SECRET", NULL);
659
660 options_builder_add_bool(b, "upnp", '\0', offsetof(options_t, enable_upnp), true,
661 "Enable UPnP/NAT-PMP for automatic port mapping (enables direct TCP for most home users)",
662 "WEBRTC", false, "ASCII_CHAT_UPNP");
663
664 options_builder_add_bool(b, "no-upnp", '\0', offsetof(options_t, no_upnp), false,
665 "Disable UPnP/NAT-PMP port mapping (requires manual port forwarding)", "WEBRTC", false,
666 NULL);
667
668 // Action options (execute and exit)
669 options_builder_add_action(b, "version", 'v', action_show_version, "Show version information and exit", "ACTIONS");
670
671 // Positional arguments: 0-2 bind addresses (IPv4 and/or IPv6)
672 options_builder_add_positional(b, "bind-address", "IPv4 or IPv6 bind address (can specify 0-2 addresses)",
673 false, // Not required (defaults to localhost)
674 "BIND ADDRESS FORMATS", g_server_bind_address_examples,
675 sizeof(g_server_bind_address_examples) / sizeof(g_server_bind_address_examples[0]),
677
678 const options_config_t *config = options_builder_build(b);
680 return config;
681}
void action_show_capabilities(void)
Show terminal capabilities and exit.
Definition actions.c:118
void action_help_server(void)
Show server mode help and exit.
Definition actions.c:192
void action_list_microphones(void)
List available microphone devices and exit.
Definition actions.c:58
void action_show_version(void)
Show version information and exit.
Definition actions.c:153
void action_help_mirror(void)
Show mirror mode help and exit.
Definition actions.c:204
void action_list_webcams(void)
List available webcam devices and exit.
Definition actions.c:30
void action_list_speakers(void)
List available speaker devices and exit.
Definition actions.c:86
void action_help_client(void)
Show client mode help and exit.
Definition actions.c:198
Action option callbacks for ascii-chat.
void options_builder_add_double(options_builder_t *builder, const char *long_name, char short_name, size_t offset, double default_value, const char *help_text, const char *group, bool required, const char *env_var_name, bool(*validate)(const void *, char **))
Definition builder.c:436
void options_builder_add_action(options_builder_t *builder, const char *long_name, char short_name, void(*action_fn)(void), const char *help_text, const char *group)
Add action option (executes action and may exit)
Definition builder.c:532
void options_builder_add_callback_optional(options_builder_t *builder, const char *long_name, char short_name, size_t offset, const void *default_value, size_t value_size, bool(*parse_fn)(const char *, void *, char **), const char *help_text, const char *group, bool required, const char *env_var_name, bool optional_arg)
Add callback option with optional argument support.
Definition builder.c:507
void options_builder_add_bool(options_builder_t *builder, const char *long_name, char short_name, size_t offset, bool default_value, const char *help_text, const char *group, bool required, const char *env_var_name)
Add boolean flag option.
Definition builder.c:344
void options_builder_add_dependency_requires(options_builder_t *builder, const char *option_name, const char *depends_on, const char *error_message)
Add dependency: if option_name is set, depends_on must be set.
Definition builder.c:565
void options_builder_add_dependency_conflicts(options_builder_t *builder, const char *option_name, const char *conflicts_with, const char *error_message)
Add anti-dependency: if option_name is set, conflicts_with must NOT be set.
Definition builder.c:577
void options_builder_add_callback(options_builder_t *builder, const char *long_name, char short_name, size_t offset, const void *default_value, size_t value_size, bool(*parse_fn)(const char *, void *, char **), const char *help_text, const char *group, bool required, const char *env_var_name)
Definition builder.c:467
void options_builder_add_int(options_builder_t *builder, const char *long_name, char short_name, size_t offset, int default_value, const char *help_text, const char *group, bool required, const char *env_var_name, bool(*validate)(const void *, char **))
Definition builder.c:367
void options_builder_destroy(options_builder_t *builder)
Free options builder.
Definition builder.c:255
void options_builder_add_string(options_builder_t *builder, const char *long_name, char short_name, size_t offset, const char *default_value, const char *help_text, const char *group, bool required, const char *env_var_name, bool(*validate)(const void *, char **))
Definition builder.c:399
options_config_t * options_builder_build(options_builder_t *builder)
Build immutable options config.
Definition builder.c:265
void options_builder_add_positional(options_builder_t *builder, const char *name, const char *help_text, bool required, const char *section_heading, const char **examples, size_t num_examples, int(*parse_fn)(const char *arg, void *config, char **remaining, int num_remaining, char **error_msg))
Add positional argument descriptor.
Definition builder.c:627
options_builder_t * options_builder_create(size_t struct_size)
Create empty options builder.
Definition builder.c:184
Options builder API for flexible command-line option configuration.
log_level_t
Logging levels enumeration.
Definition log/logging.h:59
#define log_file(...)
File-only logging - writes to log file only, no stderr output.
@ LOG_INFO
Definition log/logging.h:62
#define OPT_MICROPHONE_INDEX_DEFAULT
Default microphone device index (-1 means system default)
Definition options.h:237
#define OPT_ENCODE_AUDIO_DEFAULT
Default audio encoding state (true = Opus encoding enabled)
Definition options.h:255
#define OPT_RECONNECT_ATTEMPTS_DEFAULT
Default reconnect attempts (-1 means auto/infinite)
Definition options.h:243
#define OPT_WEBCAM_FLIP_DEFAULT
Default webcam flip state (true = horizontally flipped)
Definition options.h:246
#define OPT_COMPRESSION_LEVEL_DEFAULT
Default compression level (1-9)
Definition options.h:228
#define OPT_PORT_DEFAULT
Default TCP port for client/server communication.
Definition options.h:216
#define OPT_WEBCAM_INDEX_DEFAULT
Default webcam device index.
Definition options.h:234
#define OPT_HEIGHT_DEFAULT
Default terminal height in characters.
Definition options.h:198
#define SNAPSHOT_DELAY_DEFAULT
Default snapshot delay in seconds.
Definition options.h:212
#define OPT_MAX_CLIENTS_DEFAULT
Default maximum concurrent clients (server only)
Definition options.h:225
#define OPT_SPEAKERS_INDEX_DEFAULT
Default speakers device index (-1 means system default)
Definition options.h:240
#define OPT_WIDTH_DEFAULT
Default terminal width in characters.
Definition options.h:187
palette_type_t
Built-in palette type enumeration.
Definition palette.h:84
@ PALETTE_STANDARD
Standard ASCII palette: " ...',;:clodxkO0KXNWM".
Definition palette.h:86
render_mode_t
Render mode preferences.
Definition terminal.h:467
terminal_color_mode_t
Terminal color support levels.
Definition terminal.h:424
@ RENDER_MODE_FOREGROUND
Foreground colors only (text color)
Definition terminal.h:469
@ TERM_COLOR_AUTO
Auto-detect color support from terminal capabilities.
Definition terminal.h:426
📝 Logging API with multiple log levels and terminal output control
⚙️ Command-line options parsing and configuration management for ascii-chat
ASCII Palette Management for Video-to-ASCII Conversion.
bool parse_render_mode(const char *arg, void *dest, char **error_msg)
Parse render mode option.
Definition parsers.c:131
int parse_server_bind_address(const char *arg, void *config, char **remaining, int num_remaining, char **error_msg)
Parse server bind address positional argument.
Definition parsers.c:306
bool parse_palette_type(const char *arg, void *dest, char **error_msg)
Parse palette type option.
Definition parsers.c:173
bool parse_log_level(const char *arg, void *dest, char **error_msg)
Parse log level option.
Definition parsers.c:233
int parse_client_address(const char *arg, void *config, char **remaining, int num_remaining, char **error_msg)
Parse client address positional argument.
Definition parsers.c:393
bool parse_color_mode(const char *arg, void *dest, char **error_msg)
Parse terminal color level option.
Definition parsers.c:75
bool parse_palette_chars(const char *arg, void *dest, char **error_msg)
Parse custom palette characters option.
Definition parsers.c:534
Custom option parsers for enum types.
const options_config_t * options_preset_client(const char *program_name, const char *description)
Get client mode options preset.
Definition presets.c:398
const options_config_t * options_preset_acds(const char *program_name, const char *description)
Get acds mode options preset.
Definition presets.c:571
const options_config_t * options_preset_mirror(const char *program_name, const char *description)
Get mirror mode options preset.
Definition presets.c:530
const options_config_t * options_preset_server(const char *program_name, const char *description)
Get server mode options preset.
Definition presets.c:300
const options_config_t * options_preset_binary(const char *program_name, const char *description)
Get binary-level options preset.
Definition presets.c:273
Options builder.
Definition builder.h:192
const char * program_name
Program name for usage.
Definition builder.h:206
const char * description
Program description for usage.
Definition builder.h:207
Options configuration.
Definition builder.h:165
Consolidated options structure.
Definition options.h:439
🖥️ Cross-platform terminal interface for ascii-chat
Common SIMD utilities and structures.