ascii-chat 0.6.0
Real-time terminal-based video chat with ASCII art conversion
Loading...
Searching...
No Matches
Terminal Display

🖥️ Terminal rendering, TTY management, and frame output More...

Files

file  display.c
 💻 Client terminal display: TTY detection, frame rendering, and interactive/stdout output routing
 
file  display.h
 ascii-chat Client Display Management Interface
 

Functions

int display_init ()
 Initialize what is necessary to display ascii frames.
 
bool display_has_tty ()
 Check if display has TTY capability.
 
void display_full_reset ()
 Perform full display reset.
 
void display_reset_for_new_connection ()
 Reset display state for new connection.
 
void display_disable_logging_for_first_frame ()
 Disable terminal logging for first frame.
 
void display_render_frame (const char *frame_data, bool is_snapshot_frame)
 Render ASCII frame to display.
 
void display_cleanup ()
 Cleanup display subsystem.
 

Variables

tty_info_t g_tty_info = {-1, NULL, false}
 Global TTY information structure.
 

Detailed Description

🖥️ Terminal rendering, TTY management, and frame output

Terminal Display

Overview

The terminal display subsystem manages terminal initialization, ASCII frame rendering, TTY capability detection, and terminal cleanup.

Implementation: src/client/display.c, src/client/display.h

Initialization

int display_init(void)
{
// Check if stdout is a TTY
if (!isatty(STDOUT_FILENO)) {
log_warn("stdout is not a TTY - frames may not render correctly");
g_has_tty = false;
return 0;
}
g_has_tty = true;
// Initialize TTY for raw mode
if (tty_init(&g_tty_info) != 0) {
log_error("Failed to initialize TTY");
return -1;
}
return 0;
}
int display_init()
Initialize what is necessary to display ascii frames.
Definition display.c:265
tty_info_t g_tty_info
Global TTY information structure.
Definition display.c:102
#define log_warn(...)
Log a WARN message.
#define log_error(...)
Log an ERROR message.

Frame Rendering

void display_render_frame(const char *frame_data, bool is_snapshot_frame)
{
// Disable logging for first frame to prevent corruption
if (g_is_first_frame) {
g_is_first_frame = false;
}
if (g_has_tty) {
// Clear screen and home cursor
printf("\033[2J\033[H");
fflush(stdout);
}
// Output frame data
printf("%s", frame_data);
fflush(stdout);
// Snapshot mode: leave cursor at end
if (!is_snapshot_frame && g_has_tty) {
// Home cursor for next frame
printf("\033[H");
fflush(stdout);
}
}
void display_disable_logging_for_first_frame()
Disable terminal logging for first frame.
Definition display.c:327
void display_render_frame(const char *frame_data, bool is_snapshot_frame)
Render ASCII frame to display.
Definition display.c:353

First Frame Optimization

Problem: Log messages corrupt first frame display

Solution:

  • Suppress terminal logging before first frame render
  • Re-enable logging after first frame displayed
  • Prevents log messages from appearing in frame area
{
// Temporarily disable terminal logging
logging_set_terminal_enabled(false);
// Will be re-enabled after first frame
}

Display Reset

Full Reset

{
if (g_has_tty) {
printf("\033[2J\033[H"); // Clear screen and home cursor
fflush(stdout);
}
}
void display_full_reset()
Perform full display reset.
Definition display.c:301

Connection Reset

{
// Reset first frame flag for reconnection
g_is_first_frame = true;
}
void display_reset_for_new_connection()
Reset display state for new connection.
Definition display.c:315

Cleanup

void display_cleanup(void)
{
if (g_has_tty) {
// Restore terminal settings
tty_restore(&g_tty_info);
// Clear screen and show cursor
printf("\033[2J\033[H\033[?25h");
fflush(stdout);
}
}
void display_cleanup()
Cleanup display subsystem.
Definition display.c:385
See also
src/client/display.c
src/client/display.h
lib/platform/terminal.h
Client Overview

Function Documentation

◆ display_cleanup()

void display_cleanup ( )

#include <display.c>

Cleanup display subsystem.

Performs graceful cleanup of display resources and terminal state. Restores terminal to original state and closes owned file descriptors.

Definition at line 385 of file display.c.

385 {
386 // Cleanup ASCII rendering
388
389 // Close the controlling terminal if we opened it
390 if (g_tty_info.owns_fd && g_tty_info.fd >= 0) {
392 g_tty_info.fd = -1;
393 g_tty_info.owns_fd = false;
394 }
395
396 g_has_tty = false;
397}
int platform_close(int fd)
Safe file close (close replacement)
void ascii_write_destroy(int fd, bool reset_terminal)
Destroy ASCII write subsystem.
Definition ascii.c:334
bool owns_fd
True if we opened the FD and should close it, false otherwise.
Definition terminal.h:529
int fd
File descriptor for TTY access.
Definition terminal.h:525

References ascii_write_destroy(), tty_info_t::fd, g_tty_info, tty_info_t::owns_fd, and platform_close().

◆ display_disable_logging_for_first_frame()

void display_disable_logging_for_first_frame ( )

#include <display.c>

Disable terminal logging for first frame.

Disables terminal logging before clearing the display for the first frame to prevent log output from interfering with ASCII display.

Call this before clearing the display for the first frame to prevent log output from interfering with ASCII display.

Definition at line 327 of file display.c.

327 {
328 // Disable terminal logging before clearing display and rendering first frame
329 if (atomic_load(&g_is_first_frame_of_connection)) {
331 atomic_store(&g_is_first_frame_of_connection, false);
332 }
333}
void log_set_terminal_output(bool enabled)
Control stderr output to terminal.

References log_set_terminal_output().

◆ display_full_reset()

void display_full_reset ( )

#include <display.c>

Perform full display reset.

Executes complete terminal reset sequence for clean display state. Safe to call multiple times and handles mode-specific behavior.

Definition at line 301 of file display.c.

301 {
302 if (g_tty_info.fd >= 0 && !should_exit()) {
303 full_terminal_reset(g_tty_info.fd);
304 }
305}
bool should_exit()
Check if client should exit.

References tty_info_t::fd, g_tty_info, and should_exit().

Referenced by client_main(), and server_connection_lost().

◆ display_has_tty()

bool display_has_tty ( )

#include <display.c>

Check if display has TTY capability.

Returns
true if TTY is available for interactive output, false otherwise
true if TTY available, false otherwise

Definition at line 289 of file display.c.

289 {
290 return g_has_tty;
291}

◆ display_init()

int display_init ( )

#include <display.c>

Initialize what is necessary to display ascii frames.

Initialize display subsystem.

Performs TTY detection, terminal configuration, and ASCII rendering initialization. Must be called once during client startup.

Initialization Steps:

  1. TTY detection and configuration
  2. Interactive mode determination
  3. ASCII rendering subsystem initialization
  4. Terminal dimension and capability setup
Returns
0 on success, negative on error
0 on success, negative on error

Definition at line 265 of file display.c.

265 {
266 // Get TTY info for direct terminal access (if needed for interactive mode)
267 g_tty_info = display_get_current_tty();
268
269 // Determine if we should use interactive TTY output
270 // For output routing: only consider stdout status (not controlling terminal)
271 // Additional TTY validation: if stdout is redirected but we have a controlling TTY,
272 // we can still show interactive output on the terminal
273 if (g_tty_info.fd >= 0) {
274 g_has_tty = platform_isatty(g_tty_info.fd) != 0; // We have a valid controlling terminal
275 // Initialize ASCII output for this connection (only if we have a valid TTY)
277 }
278
279 return 0;
280}
int platform_isatty(int fd)
Check if a file descriptor is a terminal.
asciichat_error_t ascii_write_init(int fd, bool reset_terminal)
Initialize ASCII write subsystem.
Definition ascii.c:40

References ascii_write_init(), tty_info_t::fd, g_tty_info, and platform_isatty().

◆ display_render_frame()

void display_render_frame ( const char *  frame_data,
bool  is_snapshot_frame 
)

#include <display.c>

Render ASCII frame to display.

Render ASCII frame to display

Handles frame rendering with appropriate output routing based on display mode and snapshot requirements. Manages TTY vs redirect output and snapshot timing coordination.

Rendering Logic:

  • Interactive Mode: Render every frame to TTY
  • Redirect Mode: Only render final snapshot frame
  • Snapshot Mode: Render to both TTY and stdout for final frame
  • Format Control: Add newline terminator for snapshot files
Parameters
frame_dataASCII frame data to render
is_snapshot_frameWhether this is the final snapshot frame
frame_dataASCII frame data to render
is_snapshot_frameWhether this is the final snapshot frame

Definition at line 353 of file display.c.

353 {
354 if (!frame_data) {
355 SET_ERRNO(ERROR_INVALID_PARAM, "Attempted to render NULL frame data");
356 return;
357 }
358
359 // For terminal: print every frame until final snapshot
360 // For non-terminal: only print the final snapshot frame
361 if (g_has_tty || (!g_has_tty && GET_OPTION(snapshot_mode) && is_snapshot_frame)) {
362 if (is_snapshot_frame) {
363 // Write the final frame to the terminal as well, not just to stdout
364 write_frame_to_output(frame_data, true);
365 }
366
367 // The real ASCII data frame write call
368 write_frame_to_output(frame_data, g_has_tty && !is_snapshot_frame);
369
370 if (GET_OPTION(snapshot_mode) && is_snapshot_frame) {
371 // A newline at the end of the snapshot of ASCII art to end the file
372 printf("\n");
373 }
374 }
375}
#define SET_ERRNO(code, context_msg,...)
Set error code with custom context message and log it.
@ ERROR_INVALID_PARAM
#define GET_OPTION(field)
Safely get a specific option field (lock-free read)
Definition options.h:644

References ERROR_INVALID_PARAM, GET_OPTION, and SET_ERRNO.

◆ display_reset_for_new_connection()

void display_reset_for_new_connection ( )

#include <display.c>

Reset display state for new connection.

Resets the first frame tracking flag to prepare for a new connection. Call this when starting a new connection to reset first frame tracking.

Call this when starting a new connection to reset first frame tracking.

Definition at line 315 of file display.c.

315 {
316 atomic_store(&g_is_first_frame_of_connection, true);
317}

Referenced by protocol_start_connection().

Variable Documentation

◆ g_tty_info

tty_info_t g_tty_info = {-1, NULL, false}

#include <display.c>

Global TTY information structure.

Use tty_info_t from platform abstraction

Maintains information about the terminal/TTY device for interactive output. Contains file descriptor, device path, and validity status. Initialized during display subsystem startup.

Note
Not static because it may be accessed from other modules

Definition at line 102 of file display.c.

102{-1, NULL, false};

Referenced by display_cleanup(), display_full_reset(), and display_init().