DungeonCrawl
Loading...
Searching...
No Matches
media_output_handler.h File Reference

Exposes functions for the media output handler. More...

#include <notcurses/notcurses.h>
#include <stdbool.h>

Go to the source code of this file.

Data Structures

struct  loaded_visual_s
 Structure to represent a loaded visual. More...

Typedefs

typedef enum media_blitter media_blitter_t
 Media blitter options (rendering method)
typedef struct loaded_visual_s loaded_visual_t
 Structure to represent a loaded visual.

Enumerations

enum  scale_type_t {
  SCALE_NONE , SCALE_PRESERVE , SCALE_STRETCH , SCALE_CELL ,
  SCALE_FULLSCREEN
}
enum  media_type_t { MEDIA_PNG , MEDIA_GIF , MEDIA_MP4 , MEDIA_UNSUPPORTED }
enum  media_blitter {
  MEDIA_BLITTER_DEFAULT = NCBLIT_DEFAULT , MEDIA_BLITTER_ASCII = NCBLIT_1x1 , MEDIA_BLITTER_HALF = NCBLIT_2x1 , MEDIA_BLITTER_QUAD = NCBLIT_2x2 ,
  MEDIA_BLITTER_BRAILLE = NCBLIT_BRAILLE , MEDIA_BLITTER_PIXEL = NCBLIT_PIXEL
}
 Media blitter options (rendering method) More...

Functions

bool init_media_output (void)
 Initialize the media output handler.
void shutdown_media_output (void)
 Shutdown the media output handler.
void media_cleanup (void)
void destroy_media (loaded_visual_t *media)
 Frees the memory associated with a loaded media resource.
bool refresh_media_display (void)
 Force a refresh of the media display.
loaded_visual_tload_media (const char *filename)
 load a media resource from file they can be different types (PNG, GIF, MP4)
loaded_visual_tready_media (const char *filename, int x, int y, int height, int width, scale_type_t scale_type)
 Prepares a media resource for display.
bool unload_media (const char *filename)
 Unload a specific media resource.
bool preload_media (const char *filename)
 Preload a media file into memory.
bool reload_media_after_resize (void)
 Reload media after terminal resize.
bool media_output_render (loaded_visual_t *media)
 Display a loaded media file on its assigned plane.
bool media_output_render_next_frame (loaded_visual_t *media)
 Display the next frame of an animation or video.
bool media_output_can_display_images (void)
 Check if the notcurses implementation supports image loading.
bool media_output_can_display_videos (void)
 Check if the notcurses implementation supports video loading.
void setup_scaling_options (loaded_visual_t *visual, scale_type_t scale_type, int target_width, int target_height)
 Enable different scaling options for the loaded visual.
bool directory_exists (const char *path)
 checks if a directory exists
media_type_t get_file_type (const char *filename)
 Get the media type based on the file extension.
bool is_file_extension (const char *filename, const char *extension)
 Check if a filename has a specific extension.
char * build_filepath (const char *filename, media_type_t media_type)
 Build a file path for the specified media type.

Detailed Description

Exposes functions for the media output handler.

Definition in file media_output_handler.h.

Typedef Documentation

◆ loaded_visual_t

Structure to represent a loaded visual.

This is an opaque structure that encapsulates a Notcurses visual.

Enumeration Type Documentation

◆ media_blitter

Media blitter options (rendering method)

Definition at line 31 of file media_output_handler.h.

31 {
32 MEDIA_BLITTER_DEFAULT = NCBLIT_DEFAULT,// Use terminal's best option
33 MEDIA_BLITTER_ASCII = NCBLIT_1x1, // Use ASCII only
34 MEDIA_BLITTER_HALF = NCBLIT_2x1, // Use half blocks (▀ ▄)
35 MEDIA_BLITTER_QUAD = NCBLIT_2x2, // Use quadrant blocks (▖ ▗ ▘ ▙)
36 MEDIA_BLITTER_BRAILLE = NCBLIT_BRAILLE,// Use braille (⠀⠁⠂⠃...)
37 MEDIA_BLITTER_PIXEL = NCBLIT_PIXEL, // Use pixel graphics if available
enum media_blitter media_blitter_t
Media blitter options (rendering method)

◆ media_type_t

enum media_type_t

Definition at line 21 of file media_output_handler.h.

21 {
22 MEDIA_PNG,
23 MEDIA_GIF,
24 MEDIA_MP4,
25 MEDIA_UNSUPPORTED
26} media_type_t;

◆ scale_type_t

enum scale_type_t

Definition at line 12 of file media_output_handler.h.

12 {
13 SCALE_NONE, // No scaling, use original size
14 SCALE_PRESERVE, // Scale preserving aspect ratio
15 SCALE_STRETCH, // Stretch to exact dimensions
16 SCALE_CELL, // Scale to fit in a single cell
17 SCALE_FULLSCREEN// Scale to fill the entire screen
18} scale_type_t;

Function Documentation

◆ build_filepath()

char * build_filepath ( const char * filename,
media_type_t media_type )

Build a file path for the specified media type.

Parameters
filenameFile name to build the path for
media_typeType of media (PNG, GIF, MP4)
Returns
Pointer to the constructed file path

Definition at line 433 of file media_output_handler.c.

433 {
434 // Allocate memory for the path
435 char* filepath = malloc(MAX_PATH_LEN);
436 if (!filepath) {
437 log_msg(ERROR, "media_output", "Failed to allocate memory for file path");
438 return NULL;
439 }
440
441 // Build the path based on the media media_type
442 const char* subdir = "";
443 switch (media_type) {
444 case MEDIA_PNG:
445 subdir = "png/";
446 break;
447 case MEDIA_GIF:
448 subdir = "gif/";
449 break;
450 case MEDIA_MP4:
451 subdir = "mp4/";
452 break;
453 default:
454 break;
455 }
456
457 // Construct the full path
458 snprintf(filepath, MAX_PATH_LEN, "%s%s%s", MEDIA_PATH, subdir, filename);
459
460 return filepath;
461}
void log_msg(const log_level_t level, const char *module, const char *format,...)
Logs a formatted message with a specified log level and module.
Definition logger.c:246

◆ destroy_media()

void destroy_media ( loaded_visual_t * media)

Frees the memory associated with a loaded media resource.

Parameters
mediaPointer to the loaded media instance to destroy

Definition at line 76 of file media_output_handler.c.

76 {
77 free_media_resource(media);
78}

◆ directory_exists()

bool directory_exists ( const char * path)

checks if a directory exists

Parameters
pathPath to the directory
Returns
success or failure

◆ get_file_type()

media_type_t get_file_type ( const char * filename)

Get the media type based on the file extension.

Parameters
filenameFile name to check
Returns
Media type (PNG, GIF, MP4, or UNSUPPORTED)

Definition at line 403 of file media_output_handler.c.

403 {
404 if (is_file_extension(filename, ".png")) {
405 return MEDIA_PNG;
406 } else if (is_file_extension(filename, ".gif")) {
407 return MEDIA_GIF;
408 } else if (is_file_extension(filename, ".mp4")) {
409 return MEDIA_MP4;
410 } else {
411 log_msg(ERROR, "media_output", "Unsupported file extension for: %s", filename);
412 return MEDIA_UNSUPPORTED;
413 }
414}
bool is_file_extension(const char *filename, const char *extension)
Check if a filename has a specific extension.

◆ init_media_output()

bool init_media_output ( void )

Initialize the media output handler.

Must be called after the common output handler is initialized.

Returns
true on success, false on failure

Definition at line 37 of file media_output_handler.c.

37 {
38 if (!nc) {
39 log_msg(ERROR, "media_output", "Null Notcurses instance provided");
40 return false;
41 }
42
43 if (!stdplane) {
44 log_msg(ERROR, "media_output", "Null standard plane provided");
45 return false;
46 }
47
48 // Initialize resources array
49 memset(resources, 0, sizeof(resources));
50 resource_count = 0;
51
52 // Ensure the media directory exists
53 //TODO: implement directory_exists function
54 /*if (!directory_exists(MEDIA_PATH)) {
55 log_msg(ERROR, "media_output", "Failed to ensure media directory exists");
56 }*/
57
58 return true;
59}

◆ is_file_extension()

bool is_file_extension ( const char * filename,
const char * extension )

Check if a filename has a specific extension.

Parameters
filenameFile name to check
extensionExtension to check for
Returns
true if the file has the specified extension, false otherwise

Definition at line 417 of file media_output_handler.c.

417 {
418 if (!filename || !extension) {
419 return false;
420 }
421
422 size_t filename_len = strlen(filename);
423 size_t ext_len = strlen(extension);
424
425 if (filename_len < ext_len) {
426 return false;
427 }
428
429 return strncasecmp(filename + filename_len - ext_len, extension, ext_len) == 0;
430}

◆ load_media()

loaded_visual_t * load_media ( const char * filename)

load a media resource from file they can be different types (PNG, GIF, MP4)

Parameters
filenameFile name to load
Returns
Pointer to a loaded visual instance

Definition at line 99 of file media_output_handler.c.

99 {
100 // Validate parameters
101 if (!filename) {
102 log_msg(ERROR, "media_output", "Invalid filename for load_media");
103 return NULL;
104 }
105
106 media_type_t media_type = get_file_type(filename);
107
108 // Build the full file path
109 char* filepath = build_filepath(filename, media_type);
110 if (!filepath) {
111 return NULL;
112 }
113
114 // Check if we already have this resource loaded
115 for (int i = 0; i < resource_count; i++) {
116 if (strcmp(resources[i].path, filepath) == 0) {
117 free(filepath);
118 return &resources[i];// Return existing resource
119 }
120 }
121
122 // Make sure we have space for a new resource
123 if (resource_count >= MAX_RESOURCES) {
124 // Could implement a LRU cache here, but for simplicity, just fail
125 free(filepath);
126 return NULL;
127 }
128
129 // Load the visual from file with detailed error handling
130 struct ncvisual* visual = ncvisual_from_file(filepath);
131 if (!visual) {
132 log_msg(ERROR, "media_output", "Failed to load media: %s (check if file exists)", filepath);
133 return NULL;
134 }
135
136 // Allocate a new resource
137 loaded_visual_t* resource = &resources[resource_count];
138 if (!resource) {
139 log_msg(ERROR, "media_output", "Failed to allocate memory for loaded visual");
140 ncvisual_destroy(visual);
141 return NULL;
142 }
143 resource_count++;
144
145 // Initialize the structure
146 memset(resource, 0, sizeof(loaded_visual_t));
147 resource->visual = visual;
148 resource->plane = NULL;// Will be created when displayed
149
150 // Set resource properties
151 resource->media_type = media_type;
152 resource->is_loaded = true;
153 resource->is_playing = false;
154 resource->path = strdup(filepath);
155 if (!resource->path) {
156 log_msg(ERROR, "media_output", "Failed to store path");
157 ncvisual_destroy(visual);
158 resource_count--;
159 free(filepath);
160 return NULL;
161 }
162
163 // Get visual dimensions
164 struct ncvisual_options vopts = {0};
165 struct ncvgeom geom = {0};
166 int geo_ret = ncvisual_geom(nc, visual, &vopts, &geom);
167
168 if (geo_ret) {
169 log_msg(WARNING, "media_output", "Failed to get visual geometry, using default dimensions");
170 // Use defaults if we can't get the dimensions
171 resource->og_width = 20; // Default width
172 resource->og_height = 20;// Default height
173 } else {
174 // Store dimensions with detailed logging
175 if (geom.pixx <= 0 || geom.pixy <= 0) {
176 log_msg(WARNING, "media_output", "Invalid media dimensions: %dx%d, using defaults",
177 geom.pixx, geom.pixy);
178 resource->og_width = 20; // Default width
179 resource->og_height = 20;// Default height
180 } else {
181 resource->og_width = geom.pixx; // Width in pixels
182 resource->og_height = geom.pixy;// Height in pixels
183 }
184 }
185
186 // set attributes based on media media_type
187 switch (media_type) {
188 case MEDIA_PNG:
189 resource->frames = 1;// Single frame for static images
190 break;
191 case MEDIA_GIF:
192 // Count frames by decoding the whole GIF
193 resource->frames = 0;
194 while (ncvisual_decode(visual) != 1) {
195 resource->frames++;
196 }
197 // Reset to first frame
198 ncvisual_destroy(visual);
199 resource->visual = ncvisual_from_file(filepath);
200 if (!resource->visual) {
201 log_msg(ERROR, "media_output", "Failed to reload GIF after frame counting");
202 free(resource->path);
203 resource_count--;
204 free(filepath);
205 return NULL;
206 }
207 break;
208 case MEDIA_MP4:
209 // MP4 handling would go here
210 log_msg(ERROR, "media_output", "MP4 loading not implemented yet");
211 ncvisual_destroy(visual);
212 resource_count--;
213 free(resource->path);
214 break;
215 default:
216 log_msg(ERROR, "media_output", "Unsupported media media_type");
217 ncvisual_destroy(visual);
218 free(filepath);
219 return NULL;
220 }
221
222 free(filepath);
223 return resource;
224}
media_type_t get_file_type(const char *filename)
Get the media type based on the file extension.
char * build_filepath(const char *filename, media_type_t media_type)
Build a file path for the specified media type.
struct loaded_visual_s loaded_visual_t
Structure to represent a loaded visual.

◆ media_cleanup()

void media_cleanup ( void )

Definition at line 66 of file media_output_handler.c.

66 {
67 // Free all loaded resources
68 for (int i = 0; i < resource_count; i++) {
69 if (resources[i].is_loaded) {
70 free_media_resource(&resources[i]);
71 }
72 }
73 resource_count = 0;
74}

◆ media_output_can_display_images()

bool media_output_can_display_images ( void )

Check if the notcurses implementation supports image loading.

Returns
true if supported, false otherwise

◆ media_output_can_display_videos()

bool media_output_can_display_videos ( void )

Check if the notcurses implementation supports video loading.

Returns
true if supported, false otherwise

◆ media_output_render()

bool media_output_render ( loaded_visual_t * media)

Display a loaded media file on its assigned plane.

Parameters
mediaPointer to a loaded media instance
Returns
true on success, false on failure

◆ media_output_render_next_frame()

bool media_output_render_next_frame ( loaded_visual_t * media)

Display the next frame of an animation or video.

Parameters
mediaPointer to a loaded media instance
Returns
true on success, false on failure or end of media

◆ preload_media()

bool preload_media ( const char * filename)

Preload a media file into memory.

Parameters
filenameFile name to preload
Returns
true on success, false on failure

◆ ready_media()

loaded_visual_t * ready_media ( const char * filename,
int x,
int y,
int height,
int width,
scale_type_t scale_type )

Prepares a media resource for display.

Parameters
filenameFile name to load
xX coordinate in terminal cells
yY coordinate in terminal cells
heightHeight in terminal cells
widthWidth in terminal cells (0 for auto)
scale_typeScaling type to apply
Returns
Pointer to a loaded visual instance

Definition at line 226 of file media_output_handler.c.

226 {
227 // Validate parameters
228 if (!filename) {
229 log_msg(ERROR, "media_output", "Null filename for display_media");
230 return NULL;
231 }
232
233 // Allow height=0 for fullscreen and preserving aspect ratio
234 if (height < 0) {
235 log_msg(ERROR, "media_output", "Invalid height (%d) for display_media", height);
236 return NULL;
237 }
238
239 // Load the media
240 loaded_visual_t* resource = load_media(filename);
241 if (!resource || !resource->is_loaded) {
242 log_msg(ERROR, "media_output", "Failed to load media: %s", filename);
243 return NULL;
244 }
245
246 // Set up scaling
247 setup_scaling_options(resource, scale_type, width, height);
248
249 // Set coordinates
250 resource->options.y = y;
251 resource->options.x = x;
252
253 // Clean up existing plane if needed
254 if (resource->plane) {
255 ncplane_erase(resource->plane);// Clear contents first
256 notcurses_render(nc); // Update display
257 ncplane_destroy(resource->plane);
258 resource->plane = NULL;
259 }
260
261 return resource;
262}
void setup_scaling_options(loaded_visual_t *visual, scale_type_t scale_type, int target_width, int target_height)
Enable different scaling options for the loaded visual.
loaded_visual_t * load_media(const char *filename)
load a media resource from file they can be different types (PNG, GIF, MP4)

◆ refresh_media_display()

bool refresh_media_display ( void )

Force a refresh of the media display.

Returns
bool indicating success or failure

Definition at line 81 of file media_output_handler.c.

81 {
82 //TODO: fix
83
84 // Force a redraw of the terminal with error checking
85 bool result = notcurses_render(nc);
86
87 if (!result) {
88 log_msg(ERROR, "media_output", "Failed to refresh media display");
89 }
90
91 return result;
92}

◆ reload_media_after_resize()

bool reload_media_after_resize ( void )

Reload media after terminal resize.

Returns
true on success, false on failure

◆ setup_scaling_options()

void setup_scaling_options ( loaded_visual_t * visual,
scale_type_t scale_type,
int target_width,
int target_height )

Enable different scaling options for the loaded visual.

Parameters
visualPointer to the loaded visual instance
scale_typeScaling type to apply
target_widthWidth to scale to
target_heightHeight to scale to

Definition at line 333 of file media_output_handler.c.

334 {
335 // Clear options first
336 memset(&visual->options, 0, sizeof(visual->options));
337
338 // Apply scaling based on type
339 switch (scale_type) {
340 case SCALE_PRESERVE:
341 // Scale preserving aspect ratio
342 visual->options.scaling = NCSCALE_SCALE;
343 // When using NCSCALE_SCALE, a zero value for lenx/leny means auto-scale
344 visual->options.leny = target_height > 0 ? target_height : 0;
345 visual->options.lenx = target_width > 0 ? target_width : 0;
346 break;
347
348 case SCALE_STRETCH:
349 // Stretch to exact dimensions
350 if (target_width > 0 && target_height > 0) {
351 visual->options.scaling = NCSCALE_STRETCH;
352 visual->options.leny = target_height;
353 visual->options.lenx = target_width;
354 } else {
355 // Fall back to no scaling if dimensions are invalid
356 visual->options.scaling = NCSCALE_NONE;
357 }
358 break;
359
360 case SCALE_CELL:
361 // Scale to fit in a single cell
362 visual->options.scaling = NCSCALE_SCALE;
363 visual->options.leny = 1;
364 visual->options.lenx = 1;
365 break;
366
367 case SCALE_FULLSCREEN:
368 // Scale to fit the entire terminal
369 visual->options.scaling = NCSCALE_STRETCH;
370 // Get terminal dimensions
371 int screen_width, screen_height;
372 if (get_screen_dimensions(&screen_width, &screen_height)) {
373 visual->options.leny = screen_height;
374 visual->options.lenx = screen_width;
375 } else {
376 // Fallback to original dimensions
377 visual->options.leny = visual->og_height;
378 visual->options.lenx = visual->og_width;
379 log_msg(WARNING, "media_output", "Could not get screen dimensions, using original size");
380 }
381 break;
382
383 case SCALE_NONE:
384 default:
385 // No scaling
386 visual->options.scaling = NCSCALE_NONE;
387 break;
388 }
389
390 // Set blitter to a reliable one
391 visual->options.blitter = NCBLIT_2x1;
392}
bool get_screen_dimensions(int *width, int *height)
Get the dimensions of the standard plane.

◆ shutdown_media_output()

void shutdown_media_output ( void )

Shutdown the media output handler.

Cleans up resources used by the media output handler.

Definition at line 62 of file media_output_handler.c.

62 {
63 media_cleanup();
64}

◆ unload_media()

bool unload_media ( const char * filename)

Unload a specific media resource.

Parameters
filenameFile name to unload
Returns
true on success, false on failure

Definition at line 269 of file media_output_handler.c.

269 {
270 if (!filename) {
271 return false;
272 }
273
274 // Look for the resource in our cache
275 for (int i = 0; i < resource_count; i++) {
276 if (strcmp(resources[i].path, filename) == 0) {
277 free_media_resource(&resources[i]);
278
279 // Shift other resources if this isn't the last one
280 if (i < resource_count - 1) {
281 memmove(&resources[i], &resources[i + 1], (resource_count - i - 1) * sizeof(loaded_visual_t));
282 }
283
284 resource_count--;
285 return true;
286 }
287 }
288
289 return false;
290}