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

Go to the source code of this file.

Functions

asciichat_error_t webcam_init (unsigned short int webcam_index)
 
image_t * webcam_read (void)
 
void webcam_destroy (void)
 
void webcam_flush (void)
 
void webcam_print_init_error_help (asciichat_error_t error_code)
 
asciichat_error_t webcam_init_context (webcam_context_t **ctx, unsigned short int device_index)
 
void webcam_cleanup_context (webcam_context_t *ctx)
 
void webcam_flush_context (webcam_context_t *ctx)
 
image_t * webcam_read_context (webcam_context_t *ctx)
 
asciichat_error_t webcam_get_dimensions (webcam_context_t *ctx, int *width, int *height)
 
asciichat_error_t webcam_list_devices (webcam_device_info_t **out_devices, unsigned int *out_count)
 
void webcam_free_device_list (webcam_device_info_t *devices)
 

Function Documentation

◆ webcam_cleanup_context()

void webcam_cleanup_context ( webcam_context_t *  ctx)

Definition at line 246 of file video/webcam/webcam.c.

246 {
247 (void)ctx;
248 log_warn("Webcam cleanup called on unsupported platform");
249}

Referenced by media_source_destroy(), and webcam_destroy().

◆ webcam_destroy()

void webcam_destroy ( void  )

Definition at line 131 of file video/webcam/webcam.c.

131 {
132 // Free cached webcam frame if it was allocated (from test pattern or real webcam)
133 if (cached_webcam_frame) {
134 image_destroy(cached_webcam_frame);
135 cached_webcam_frame = NULL;
136 }
137
138 if (GET_OPTION(test_pattern)) {
139 log_debug("Test pattern mode - webcam context cleanup skipped");
140 return;
141 }
142
143 if (global_webcam_ctx) {
144 webcam_cleanup_context(global_webcam_ctx);
145 global_webcam_ctx = NULL;
146 // log_info("Webcam resources released");
147 } else {
148 log_dev("Webcam was not opened, nothing to release");
149 }
150}
void image_destroy(image_t *p)
Definition video/image.c:85
void webcam_cleanup_context(webcam_context_t *ctx)

References image_destroy(), and webcam_cleanup_context().

Referenced by ascii_read_destroy(), asciichat_shared_destroy(), and session_client_like_run().

◆ webcam_flush()

void webcam_flush ( void  )

Definition at line 152 of file video/webcam/webcam.c.

152 {
153 if (GET_OPTION(test_pattern)) {
154 return; // Test pattern doesn't need flushing
155 }
156
157 if (global_webcam_ctx) {
158 webcam_flush_context(global_webcam_ctx);
159 }
160}
void webcam_flush_context(webcam_context_t *ctx)

References webcam_flush_context().

◆ webcam_flush_context()

void webcam_flush_context ( webcam_context_t *  ctx)

Definition at line 251 of file video/webcam/webcam.c.

251 {
252 (void)ctx;
253 // No-op on unsupported platforms
254}

Referenced by webcam_flush().

◆ webcam_free_device_list()

void webcam_free_device_list ( webcam_device_info_t *  devices)

Definition at line 277 of file video/webcam/webcam.c.

277 {
278 (void)devices;
279 // No-op on unsupported platforms
280}

◆ webcam_get_dimensions()

asciichat_error_t webcam_get_dimensions ( webcam_context_t *  ctx,
int *  width,
int *  height 
)

Definition at line 262 of file video/webcam/webcam.c.

262 {
263 (void)ctx;
264 (void)width;
265 (void)height;
266 return SET_ERRNO(ERROR_WEBCAM, "Webcam get dimensions not supported on this platform");
267}

Referenced by webcam_init().

◆ webcam_init()

asciichat_error_t webcam_init ( unsigned short int  webcam_index)

Definition at line 20 of file video/webcam/webcam.c.

20 {
21 // Check if test pattern mode is enabled
22 if (GET_OPTION(test_pattern)) {
23 log_info("Test pattern mode enabled - not opening real webcam");
24 log_info("Test pattern resolution: 320x240");
25 return ASCIICHAT_OK;
26 }
27
28#ifdef __linux__
29 log_info("Initializing webcam with V4L2 (Linux)");
30 log_info("Attempting to open webcam with index %d using V4L2 (Linux)...", webcam_index);
31#elif defined(__APPLE__)
32 log_info("Initializing webcam with AVFoundation (macOS)");
33 log_info("Attempting to open webcam with index %d using AVFoundation (macOS)...", webcam_index);
34#elif defined(_WIN32)
35 log_info("Initializing webcam with Media Foundation (Windows)");
36 log_info("Attempting to open webcam with index %d using Media Foundation (Windows)...", webcam_index);
37#else
38 log_info("Initializing webcam with Unknown platform");
39 log_info("Attempting to open webcam with index %d using Unknown platform...", webcam_index);
40#endif
41
42 asciichat_error_t result = webcam_init_context(&global_webcam_ctx, webcam_index);
43 if (result != ASCIICHAT_OK) {
44 SET_ERRNO(result, "Failed to connect to webcam (error code: %d)", result);
45 return result;
46 }
47
48 // Get image dimensions
49 int width, height;
50 if (webcam_get_dimensions(global_webcam_ctx, &width, &height) == ASCIICHAT_OK) {
51 log_info("Webcam opened successfully! Resolution: %dx%d", width, height);
52 } else {
53 SET_ERRNO(ERROR_WEBCAM, "Webcam opened but failed to get dimensions");
54 }
55
56 return result;
57}
asciichat_error_t webcam_init_context(webcam_context_t **ctx, unsigned short int device_index)
asciichat_error_t webcam_get_dimensions(webcam_context_t *ctx, int *width, int *height)

References webcam_get_dimensions(), and webcam_init_context().

Referenced by ascii_read_init().

◆ webcam_init_context()

asciichat_error_t webcam_init_context ( webcam_context_t **  ctx,
unsigned short int  device_index 
)

Definition at line 239 of file video/webcam/webcam.c.

239 {
240 (void)ctx;
241 (void)device_index;
242 SET_ERRNO(ERROR_WEBCAM, "Webcam platform not supported on this system");
243 return ERROR_WEBCAM;
244}

Referenced by media_source_create(), and webcam_init().

◆ webcam_list_devices()

asciichat_error_t webcam_list_devices ( webcam_device_info_t **  out_devices,
unsigned int *  out_count 
)

Definition at line 269 of file video/webcam/webcam.c.

269 {
270 if (out_devices)
271 *out_devices = NULL;
272 if (out_count)
273 *out_count = 0;
274 return SET_ERRNO(ERROR_WEBCAM, "Webcam device enumeration not supported on this platform");
275}

◆ webcam_print_init_error_help()

void webcam_print_init_error_help ( asciichat_error_t  error_code)

Definition at line 162 of file video/webcam/webcam.c.

162 {
163 // Platform-specific error messages and troubleshooting help
164#ifdef __linux__
165 safe_fprintf(stderr, "\n");
166
167 if (error_code == ERROR_WEBCAM) {
168 safe_fprintf(stderr, "Webcam initialization failed on Linux.\n\n");
169 safe_fprintf(stderr, "Common solutions:\n");
170 safe_fprintf(stderr, " 1. Check if a camera is connected:\n");
171 safe_fprintf(stderr, " ls /dev/video*\n\n");
172 safe_fprintf(stderr, " 2. If no camera is available, use test pattern mode:\n");
173 safe_fprintf(stderr, " ascii-chat client --test-pattern\n\n");
174 safe_fprintf(stderr, " 3. Install V4L2 drivers if needed:\n");
175 safe_fprintf(stderr, " sudo apt-get install v4l-utils\n");
176 } else if (error_code == ERROR_WEBCAM_PERMISSION) {
177 safe_fprintf(stderr, "Camera permission denied.\n\n");
178 safe_fprintf(stderr, "Fix permissions with:\n");
179 safe_fprintf(stderr, " sudo usermod -a -G video $USER\n");
180 safe_fprintf(stderr, "Then log out and log back in for changes to take effect.\n");
181 } else if (error_code == ERROR_WEBCAM_IN_USE) {
182 safe_fprintf(stderr, "Camera is already in use by another application.\n\n");
183 safe_fprintf(stderr, "Try closing other camera apps or use test pattern mode:\n");
184 safe_fprintf(stderr, " ascii-chat client --test-pattern\n");
185 } else {
186 safe_fprintf(stderr, "Webcam error on Linux.\n\n");
187 safe_fprintf(stderr, "General troubleshooting:\n");
188 safe_fprintf(stderr, "* Check camera: ls /dev/video*\n");
189 safe_fprintf(stderr, "* Check permissions: groups | grep video\n");
190 safe_fprintf(stderr, "* Use test pattern: ascii-chat client --test-pattern\n");
191 }
192 (void)fflush(stderr);
193#elif defined(__APPLE__)
194 (void)error_code;
195 safe_fprintf(stderr, "\n");
196 safe_fprintf(stderr, "On macOS, you may need to grant camera permissions:\n");
197 safe_fprintf(stderr,
198 "* Say \"yes\" to the popup about system camera access that you see when running this program for the "
199 "first time.\n");
201 stderr, "* If you said \"no\" to the popup, go to System Preferences > Security & Privacy > Privacy > Camera.\n");
202 safe_fprintf(stderr,
203 " Now flip the switch next to your terminal application in that privacy list to allow ascii-chat to "
204 "access your camera.\n");
205 safe_fprintf(stderr, " Then just run this program again.\n");
206 (void)fflush(stderr);
207#elif defined(_WIN32)
208 if (error_code == ERROR_WEBCAM_IN_USE) {
209 // Device is in use by another application - this is a fatal error on Windows
210 safe_fprintf(stderr, "\n");
211 safe_fprintf(stderr, "Webcam is already in use by another application.\n");
212 safe_fprintf(stderr, "Windows allows only one application to access the webcam at a time.\n");
213 safe_fprintf(stderr, "\n");
214 safe_fprintf(stderr, "To use ascii-chat with multiple clients, try these alternatives:\n");
215 safe_fprintf(stderr, " --test-pattern Generate a colorful test pattern instead of using webcam\n");
216 safe_fprintf(stderr, " --file VIDEO.mp4 Use a video file as input (to be implemented)\n");
217 safe_fprintf(stderr, "\n");
218 safe_fprintf(stderr, "Example: ascii-chat client --test-pattern\n");
219 (void)fflush(stderr);
220 } else {
221 // Other webcam errors - general failure
222 safe_fprintf(stderr, "\n");
223 safe_fprintf(stderr, "On Windows, this might be because:\n");
224 safe_fprintf(stderr, "* Camera permissions are not granted\n");
225 safe_fprintf(stderr, "* Camera driver issues\n");
226 safe_fprintf(stderr, "* No webcam device found\n");
227 (void)fflush(stderr);
228 }
229#else
230 // Unknown platform
231 (void)error_code;
232 safe_fprintf(stderr, "\nWebcam initialization failed on unsupported platform.\n");
233 (void)fflush(stderr);
234#endif
235}
asciichat_error_t error_code
int safe_fprintf(FILE *stream, const char *format,...)
Safe formatted output to file stream.
Definition system.c:480

References error_code, and safe_fprintf().

Referenced by client_main().

◆ webcam_read()

image_t * webcam_read ( void  )

Definition at line 59 of file video/webcam/webcam.c.

59 {
60 // Check if test pattern mode is enabled
61 if (GET_OPTION(test_pattern)) {
62 // Allocate cached frame once (like FFmpeg's current_image)
63 // Reuse same buffer for each call to avoid repeated allocations
64 if (!cached_webcam_frame) {
65 cached_webcam_frame = image_new(320, 240);
66 if (!cached_webcam_frame) {
67 SET_ERRNO(ERROR_MEMORY, "Failed to allocate test pattern frame");
68 return NULL;
69 }
70 }
71
72 // Generate animated test pattern each frame
73 // Animation is based on frame counter, respects FPS setting
74 unsigned int animation_phase = frame_counter / 2; // Slow down animation
75 frame_counter++;
76
77 for (int y = 0; y < cached_webcam_frame->h; y++) {
78 for (int x = 0; x < cached_webcam_frame->w; x++) {
79 rgb_pixel_t *pixel = &cached_webcam_frame->pixels[y * cached_webcam_frame->w + x];
80
81 // Animated color bars that shift based on frame counter
82 int animated_x = (x + animation_phase) % cached_webcam_frame->w;
83 int grid_x = animated_x / 40;
84
85 // Base pattern: color bars that animate horizontally
86 switch (grid_x % 3) {
87 case 0: // Red
88 pixel->r = 255;
89 pixel->g = 0;
90 pixel->b = 0;
91 break;
92 case 1: // Green
93 pixel->r = 0;
94 pixel->g = 255;
95 pixel->b = 0;
96 break;
97 case 2: // Blue
98 default:
99 pixel->r = 0;
100 pixel->g = 0;
101 pixel->b = 255;
102 break;
103 }
104
105 // Add animated grid lines
106 if (animated_x % 40 == 0 || y % 30 == 0) {
107 pixel->r = 0;
108 pixel->g = 0;
109 pixel->b = 0;
110 }
111 }
112 }
113
114 return cached_webcam_frame;
115 }
116
117 if (!global_webcam_ctx) {
118 SET_ERRNO(ERROR_WEBCAM, "Webcam not initialized - global_webcam_ctx is NULL");
119 return NULL;
120 }
121
122 image_t *frame = webcam_read_context(global_webcam_ctx);
123
124 if (!frame) {
125 return NULL;
126 }
127
128 return frame;
129}
image_t * image_new(size_t width, size_t height)
Definition video/image.c:36
image_t * webcam_read_context(webcam_context_t *ctx)

References image_new(), and webcam_read_context().

Referenced by media_source_read_video().

◆ webcam_read_context()

image_t * webcam_read_context ( webcam_context_t *  ctx)

Definition at line 256 of file video/webcam/webcam.c.

256 {
257 (void)ctx;
258 SET_ERRNO(ERROR_WEBCAM, "Webcam read not supported on this platform");
259 return NULL;
260}

Referenced by media_source_read_video(), and webcam_read().