ascii-chat
Binary v0.15.83-53-gb711d8720
Library lib/v0.3.2-701-gb711d8720
Video chat in your terminal
Loading...
Searching...
No Matches
client_like.h File Reference

Shared initialization and teardown for client-like modes (mirror, client, discovery). More...

Go to the source code of this file.

Data Structures

struct  session_client_like_config

Typedefs

typedef enum session_client_like_kind session_client_like_kind_t
typedef asciichat_error_t(* session_client_like_run_fn) (session_capture_ctx_t *capture, session_display_ctx_t *display, void *user_data)
 This is the handoff point for session client like config. Callers fill run_fn, run_user_data, kind, discovery before passing it on; consumers read the values during the operation and return ownership only where the member contract explicitly says they do. Mode-specific main loop callback.
typedef struct session_client_like_config session_client_like_config_t

Enumerations

enum  session_client_like_kind { SESSION_CLIENT_LIKE_KIND_MIRROR = 0 , SESSION_CLIENT_LIKE_KIND_CLIENT , SESSION_CLIENT_LIKE_KIND_DISCOVERY }

Functions

terminal_fd_reader_t * session_client_like_get_stdin_reader (void)
asciichat_error_t session_client_like_run (const session_client_like_config_t *config)

Variables

bool(*)(void *) session_client_like_get_render_should_exit (void)

Detailed Description

Shared initialization and teardown for client-like modes (mirror, client, discovery).

Provides a unified interface for running client-like modes that share common initialization patterns: media source selection, FPS probing, audio initialization, display creation, splash screen management, keepawake handling, and cleanup.

Each mode registers mode-specific callbacks to handle initialization, the main render loop, and keyboard input. The shared layer handles all the boilerplate.

Modes Supported

  • Mirror mode: Local webcam/media playback without networking
  • Client mode: Network client with per-connection initialization
  • Discovery mode: P2P mode with role negotiation

Shared Responsibilities

This layer automatically handles:

  • Terminal output management (stdout piping detection)
  • Keepawake system (platform sleep prevention)
  • Splash screen lifecycle and animation
  • Media source selection and FPS probing
  • Audio initialization and lifecycle
  • Display context creation and management
  • Render loop execution
  • Proper cleanup ordering (critical for PortAudio)

Mode-Specific Responsibilities

Mode files provide:

  • Main loop callback (run_fn) that calls session_render_loop() or custom loop
  • Optional network interrupt callback for socket shutdown
  • Optional custom exit condition for additional shutdown criteria
  • Keyboard handler for interactive controls
  • Terminal behavior preferences (newline on exit)

Memory and Lifecycle

All allocations (capture, display, audio) are owned and cleaned up by session_client_like_run(). Mode callbacks receive initialized, ready-to-use contexts and should not attempt to free them.

Author
Zachary Fogg me@zf.nosp@m.o.gg
Date
February 2026

Definition in file client_like.h.

Typedef Documentation

◆ session_client_like_config_t

Configuration for session_client_like_run()

All media, display, audio, FPS, and snapshot settings are read automatically from GET_OPTION() inside the function. Callers only provide the fields below that differ per mode.

◆ session_client_like_kind_t

◆ session_client_like_run_fn

typedef asciichat_error_t(* session_client_like_run_fn) (session_capture_ctx_t *capture, session_display_ctx_t *display, void *user_data)

This is the handoff point for session client like config. Callers fill run_fn, run_user_data, kind, discovery before passing it on; consumers read the values during the operation and return ownership only where the member contract explicitly says they do. Mode-specific main loop callback.

Called after all shared initialization is complete (capture opened, audio started, display ready, splash done). The mode runs its main loop here and returns when finished. The shared teardown runs after this returns.

Typical pattern:

// For mirror/discovery participant:
return session_render_loop(capture, display, exit_check_fn, NULL, NULL,
keyboard_handler, user_data);
// For client mode (protocol-driven):
while (!should_exit()) {
// protocol loop...
}
return ASCIICHAT_OK;
@ ASCIICHAT_OK
Definition error_codes.h:46
asciichat_error_t session_render_loop(session_capture_ctx_t *capture, session_display_ctx_t *display, session_should_exit_fn should_exit, session_capture_fn capture_cb, session_sleep_for_frame_fn sleep_cb, session_keyboard_handler_fn keyboard_handler, void *user_data)
Unified render loop for all display modes.
bool should_exit(void)
Definition main.c:249
Parameters
captureInitialized capture context. Never NULL.
displayInitialized display context. Never NULL.
user_dataUser data passed through from config.run_user_data
Returns
ASCIICHAT_OK, or error code to abort (cleanup still runs)

Definition at line 100 of file client_like.h.

Enumeration Type Documentation

◆ session_client_like_kind

Enumerator
SESSION_CLIENT_LIKE_KIND_MIRROR 
SESSION_CLIENT_LIKE_KIND_CLIENT 
SESSION_CLIENT_LIKE_KIND_DISCOVERY 

Definition at line 63 of file client_like.h.

63 {
@ SESSION_CLIENT_LIKE_KIND_CLIENT
Definition client_like.h:65
@ SESSION_CLIENT_LIKE_KIND_DISCOVERY
Definition client_like.h:66
@ SESSION_CLIENT_LIKE_KIND_MIRROR
Definition client_like.h:64
enum session_client_like_kind session_client_like_kind_t

Function Documentation

◆ session_client_like_run()

asciichat_error_t session_client_like_run ( const session_client_like_config_t * config)

Run a client-like mode with fully shared initialization and teardown

This function orchestrates the complete lifecycle of client-like modes:

Initialization (automatic from GET_OPTION())

Terminal:

  • Forces stderr when stdout is piped (terminal_should_force_stderr)
  • Disables terminal logging during rendering, re-enables on exit
  • Handles snapshot mode log visibility

Keepawake:

  • Validates –keepawake / –no-keepawake mutual exclusivity
  • Calls platform_enable_keepawake() unless –no-keepawake set
  • Disables keepawake on exit

Splash Screen:

  • Creates temporary display context
  • Calls splash_intro_start() to show splash animation
  • Holds splash visible during media probing and audio init
  • Calls splash_intro_done() when capture and display are ready

Media / Webcam (session_capture_ctx_t):

  • Selects source type from options (priority order):
    1. –url → MEDIA_SOURCE_FILE (FFmpeg handles http/rtsp/rtmp)
    2. –file → MEDIA_SOURCE_FILE; "-" → MEDIA_SOURCE_STDIN
    3. –test-pattern → MEDIA_SOURCE_TEST
    4. (default) → MEDIA_SOURCE_WEBCAM
  • FPS: uses GET_OPTION(fps) if > 0, otherwise probes with temporary media source
  • Applies GET_OPTION(media_seek_timestamp) as initial seek
  • Applies GET_OPTION(media_loop) for file looping
  • Calls session_capture_create() to open webcam or media file
  • Destroys capture on exit

Audio (audio_context_t):

Display (session_display_ctx_t):

  • Calls session_display_create() with snapshot and color settings
  • Passes audio context if initialized
  • Destroys display on exit

Mode-Specific Loop

Calls config->run_fn(capture, display, config->run_user_data) once all initialization is complete. This is where each mode calls session_render_loop() or runs its own protocol-thread-driven loop.

Cleanup (always runs, even on error)

Cleanup sequence (order is critical):

  1. Re-enable terminal logging
  2. audio_terminate_portaudio_final() - Free PortAudio device resources FIRST
  3. audio_stop_duplex() + audio_destroy() + SAFE_FREE
  4. session_display_destroy()
  5. session_capture_destroy()
  6. media_source_destroy() - Free capture buffers and source state
  7. session_log_buffer_destroy()
  8. platform_disable_keepawake()
  9. Print '
    ' to STDOUT_FILENO if print_newline_on_tty_exit && TTY
Parameters
configMode configuration. Must not be NULL. run_fn must not be NULL.
Returns
ASCIICHAT_OK on success, or the first error code from initialization or from run_fn. Cleanup always runs regardless of return value.

Definition at line 889 of file client_like.c.

889 {
890 ASCII_OTEL_SCOPE(SESSION_CLIENT_LIKE_RUN);
891 if (!config || !config->run_fn) {
892 return SET_ERRNO(ERROR_INVALID_PARAM, "config or run_fn is NULL");
893 }
894
895 g_current_config = *config;
896 g_render_should_exit = client_like_display_should_exit_adapter;
897 client_like_state_t state = {0};
899 {
900 ASCII_OTEL_SCOPE(SESSION_INITIALIZE);
901 client_like_setup_terminal_logging();
902 result = client_like_setup_keepawake();
903 if (result != ASCIICHAT_OK) {
904 goto cleanup;
905 }
906 result = client_like_validate_mirror_webcam_selection(config);
907 if (result != ASCIICHAT_OK) {
908 goto cleanup;
909 }
910 result = client_like_create_session_display(&state);
911 if (result != ASCIICHAT_OK) {
912 goto cleanup;
913 }
914 // An accepted update prompt ends the session successfully before media setup.
915 bool stop = false;
916 result = client_like_prepare_session_splash(config, &state, &stop);
917 if (result != ASCIICHAT_OK || stop) {
918 goto cleanup;
919 }
920 client_like_configure_session_logging(config);
921 result = client_like_configure_media_capture(config, &state);
922 if (result != ASCIICHAT_OK) {
923 goto cleanup;
924 }
925 result = client_like_create_network_capture(config, &state);
926 if (result != ASCIICHAT_OK) {
927 goto cleanup;
928 }
929 client_like_prepare_session_audio(&state);
930 if (client_like_finish_session_splash(config)) {
931 goto cleanup;
932 }
933 result = client_like_create_local_capture(&state);
934 if (result != ASCIICHAT_OK) {
935 goto cleanup;
936 }
937 client_like_start_session_audio(config, &state);
938 if (SAFE_GETENV("ASCII_CHAT_MCP_WORKER") && state.should_init_audio &&
939 GET_OPTION(audio_capture_source) == AUDIO_CAPTURE_SOURCE_MIC && !state.audio_available) {
940 result = SET_ERRNO(ERROR_AUDIO, "Requested microphone capture could not start");
941 goto cleanup;
942 }
943 log_debug("[MARKER] Audio setup complete at line 614");
944 }
945 log_debug("[SETUP_COMPLETE] All setup complete, about to start connection loop");
946 result = client_like_run_session_attempts(config, &state);
947
948cleanup:
949 return client_like_cleanup_session(config, &state, result);
950}
#define SET_ERRNO(code,...)
#define SAFE_GETENV(name)
Definition common.h:449
asciichat_error_t
Error and exit codes - unified status values (0-255).
Definition error_codes.h:44
@ ERROR_AUDIO
Definition error_codes.h:62
@ ERROR_INVALID_PARAM
#define log_debug(...)
Log a DEBUG message.
Definition log/log.h:595
#define GET_OPTION(field)
Safely get a specific option field (lock-free read).
Definition options.h:1336
@ AUDIO_CAPTURE_SOURCE_MIC
Definition options.h:292
#define ASCII_OTEL_SCOPE(id)
Definition otel.h:72
session_client_like_run_fn run_fn

References ASCII_OTEL_SCOPE, ASCIICHAT_OK, AUDIO_CAPTURE_SOURCE_MIC, ERROR_AUDIO, ERROR_INVALID_PARAM, GET_OPTION, log_debug, session_client_like_config::run_fn, SAFE_GETENV, and SET_ERRNO.

Referenced by client_main(), discovery_main(), and mirror_main().

Variable Documentation

◆ session_client_like_get_render_should_exit

bool(*)(void *) session_client_like_get_render_should_exit(void) ( void )

Get the render loop should_exit callback set by session_client_like_run().

This is used by mode-specific run_fn callbacks to obtain the proper should_exit callback for passing to session_render_loop(). The callback checks both the global should_exit() flag and any mode-specific custom_should_exit condition.

Returns
Function pointer to the render should_exit callback, or NULL if session_client_like_run() has not been called yet.

Definition at line 250 of file client_like.h.