54 SET_ERRNO(ERROR_MEMORY,
"Failed to create options builder");
58 b->program_name = program_name ? program_name :
"ascii-chat";
59 b->description = description ? description :
"Video chat in your terminal";
63 if (err != ASCIICHAT_OK) {
65 SET_ERRNO(err,
"Failed to add all options to builder");
75 static char session_buf1[SESSION_STRING_BUFFER_SIZE];
76 static char session_buf2[SESSION_STRING_BUFFER_SIZE];
77 static char session_buf3[SESSION_STRING_BUFFER_SIZE];
78 static char session_buf4[SESSION_STRING_BUFFER_SIZE];
79 static char session_buf5[SESSION_STRING_BUFFER_SIZE];
80 static char session_buf6[SESSION_STRING_BUFFER_SIZE];
81 static char session_buf7[SESSION_STRING_BUFFER_SIZE];
82 static char session_buf8[SESSION_STRING_BUFFER_SIZE];
83 static char session_buf9[SESSION_STRING_BUFFER_SIZE];
84 static char session_buf10[SESSION_STRING_BUFFER_SIZE];
87 char *example_session_string1 =
"adjective-noun-noun";
88 char *example_session_string2 =
"adjective-noun-noun";
89 char *example_session_string3 =
"adjective-noun-noun";
90 char *example_session_string4 =
"adjective-noun-noun";
91 char *example_session_string5 =
"adjective-noun-noun";
92 char *example_session_string6 =
"adjective-noun-noun";
93 char *example_session_string7 =
"adjective-noun-noun";
94 char *example_session_string8 =
"adjective-noun-noun";
95 char *example_session_string9 =
"adjective-noun-noun";
96 char *example_session_string10 =
"adjective-noun-noun";
100 if (session_buf1[0] !=
'\0') {
101 example_session_string1 = session_buf1;
104 if (session_buf2[0] !=
'\0') {
105 example_session_string2 = session_buf2;
108 if (session_buf3[0] !=
'\0') {
109 example_session_string3 = session_buf3;
112 if (session_buf4[0] !=
'\0') {
113 example_session_string4 = session_buf4;
116 if (session_buf5[0] !=
'\0') {
117 example_session_string5 = session_buf5;
120 if (session_buf6[0] !=
'\0') {
121 example_session_string6 = session_buf6;
124 if (session_buf7[0] !=
'\0') {
125 example_session_string7 = session_buf7;
128 if (session_buf8[0] !=
'\0') {
129 example_session_string8 = session_buf8;
132 if (session_buf9[0] !=
'\0') {
133 example_session_string9 = session_buf9;
136 if (session_buf10[0] !=
'\0') {
137 example_session_string10 = session_buf10;
142 static char example_buf1[SESSION_STRING_BUFFER_SIZE];
143 static char example_buf2[SESSION_STRING_BUFFER_SIZE];
144 static char example_buf3[SESSION_STRING_BUFFER_SIZE];
145 static char example_buf4[SESSION_STRING_BUFFER_SIZE];
146 static char example_buf5[SESSION_STRING_BUFFER_SIZE];
147 static char example_buf6[SESSION_STRING_BUFFER_SIZE];
148 static char example_buf7[SESSION_STRING_BUFFER_SIZE];
149 static char example_buf8[SESSION_STRING_BUFFER_SIZE];
150 static char example_buf9[SESSION_STRING_BUFFER_SIZE];
151 static char example_buf10[SESSION_STRING_BUFFER_SIZE];
153 safe_snprintf(example_buf1,
sizeof(example_buf1),
"%s", example_session_string1);
154 safe_snprintf(example_buf2,
sizeof(example_buf2),
"%s --discovery-service discovery.example.com",
155 example_session_string2);
156 safe_snprintf(example_buf3,
sizeof(example_buf3),
"%s -f video.mp4", example_session_string3);
157 safe_snprintf(example_buf4,
sizeof(example_buf4),
"%s --url 'https://youtu.be/7ynHVGCehoM'", example_session_string4);
158 safe_snprintf(example_buf5,
sizeof(example_buf5),
"%s -f '-'", example_session_string5);
159 safe_snprintf(example_buf6,
sizeof(example_buf6),
"%s --palette-chars '@%%#*+=-:. '", example_session_string6);
160 safe_snprintf(example_buf7,
sizeof(example_buf7),
"%s", example_session_string7);
161 safe_snprintf(example_buf8,
sizeof(example_buf8),
"%s", example_session_string8);
162 safe_snprintf(example_buf9,
sizeof(example_buf9),
"%s", example_session_string9);
163 safe_snprintf(example_buf10,
sizeof(example_buf10),
"%s --matrix --color-filter rainbow", example_session_string10);
166 static const char *client_examples[] = {
"localhost",
171 "[2001:db8::42]:27224",
172 "233.27.48.203:27224",
173 "62fb:759e:2bce:21d7:9e5d:13f8:3c11:5084:27224",
174 "ws://example.com:8080",
175 "wss://secure.example.com:443"};
178 static const char *discovery_examples[] = {
"(empty) start new session", (
const char *)example_buf7,
179 (
const char *)example_buf8, (
const char *)example_buf9,
180 (
const char *)example_buf10};
182 b,
"session-string",
"(optional) Random three words in format adjective-noun-noun that connect you to a call.",
183 false,
"POSITIONAL ARGUMENTS", discovery_examples, ARRAY_SIZE(discovery_examples), OPTION_MODE_DISCOVERY,
187 static const char *server_examples[] = {
"localhost",
192 "9631:54e7:5b5c:80dc:0f62:1f01:7ccf:5512",
193 "105.137.19.11 3a08:7276:ccb4:7b31:e934:5330:9b3a:9598",
194 "::1 192.168.1.100"};
196 "(optional) 0-2 addresses for a server to bind to, one IPv4 and the other IPv6.",
197 false,
"POSITIONAL ARGUMENTS", server_examples, ARRAY_SIZE(server_examples),
201 "POSITIONAL ARGUMENTS", client_examples, ARRAY_SIZE(client_examples),
209 "Start server (can specify 0-2 bind addresses, one IPv4 and the other IPv6)");
213 "Start discovery service (can specify 0-2 bind addresses, one IPv4 and the other IPv6)");
223 "Join session and stream media from stdin (cat file.mov | ascii-chat ... -f '-')",
true);
231 "0.0.0.0 ::",
"Start on all IPv4 and IPv6 interfaces (dual-stack)",
false);
236 "Start with identity key and discovery registration",
false);
240 "Stream from YouTube URL (also supports RTSP, HTTP, and HTTPS URLs)",
false);
242 "Stream Ludwig from videogames on Twitch",
false);
245 "Custom palette characters to use. UTF-8 is allowed.",
false);
247 b, OPTION_MODE_CLIENT_LIKE,
"--snapshot",
248 "Print ascii art for --snapshot-delay's value of seconds then print the last frame and exit. "
249 "In snapshot mode, --width, --height, and --color are NOT autodetected when piping stdin in or redirecting "
253 "Apply cyan color filter and cool palette",
false);
260 "Connect with custom display options",
false);
264 b, OPTION_MODE_MIRROR, NULL,
265 "View the webcam or files or URLs as ASCII art. Like client mode but without network connectivity or a server.",
269 "View webcam with green monochromatic color filter",
false);
271 "Matrix rain effect with rainbow colors cycling over 3.5s",
false);
273 "Stream media from stdin (cat file.gif | ascii-chat mirror -f '-')",
false);
275 "Stream .avi from stdin, looped, seeking to 00:30",
true);
277 "Start playback at exactly 22:10 (also works with --url)",
false);
279 "Print a single frame from a YouTube video at exactly 5:12 and exit",
false);
281 "Capture single ASCII frame to clipboard (macOS) and file",
false);
283 "View ASCII frame from clipboard (macOS)",
true);
287 "Enforce identity verification for all parties",
false);
297 "Available in ascii-chat client, mirror, and discovery modes. "
298 "While rendering, press '?' to display a keyboard shortcuts help menu showing:\n"
299 " - Available keybindings (?, Space, arrows, m, c, f, r)\n"
300 " - Current settings (volume, color mode, audio status, etc.)",
301 OPTION_MODE_CLIENT_LIKE);
306 "All command-line flags that accept values have corresponding environment variables.\n"
307 " Format: ASCII_CHAT_<FLAG_NAME> where FLAG_NAME is uppercase with hyphens replaced by underscores\n"
308 " Example: --color-filter maps to ASCII_CHAT_COLOR_FILTER\n"
310 " Configuration precedence (lowest to highest):\n"
311 " 1. Config file values (~/.ascii-chat/config.toml)\n"
312 " 2. Environment variables (ASCII_CHAT_*)\n"
313 " 3. Command-line flags (--flag-name)\n"
315 " Additional environment variables are documented in the ascii-chat(1) man page.",
322 "Option --url cannot be used with --file (--url takes priority)");
324 b,
"url",
"loop",
"Option --url cannot be used with --loop (network streams cannot be looped)");
329 "Cannot use --no-compress with --compression-level");
332 "Cannot use both --encode-audio and --no-encode-audio");
335 "Option --snapshot-delay requires --snapshot");