瀏覽代碼

* Implemented caca_set_display_driver() to change driver at runtime.

tags/v0.99.beta14
Sam Hocevar sam 17 年之前
父節點
當前提交
b7a785ff38
共有 3 個檔案被更改,包括 182 行新增126 行删除
  1. +139
    -99
      caca/caca.c
  2. +2
    -1
      caca/caca.h
  3. +41
    -26
      examples/driver.c

+ 139
- 99
caca/caca.c 查看文件

@@ -42,6 +42,8 @@
#endif

static int caca_can_resize(caca_display_t *);
static int caca_install_driver(caca_display_t *, char const *);
static int caca_uninstall_driver(caca_display_t *);
static int caca_select_driver(caca_display_t *, char const *);
#if defined(USE_PLUGINS)
static int caca_plugin_install(char const *, caca_display_t *);
@@ -72,7 +74,7 @@ caca_display_t * caca_create_display(cucul_canvas_t *cv)
return caca_create_display_with_driver(cv, NULL);
}

/** \brief Attach a caca graphical context to a cucul canvas.
/** \brief Attach a specific caca graphical context to a cucul canvas.
*
* Create a graphical context using device-dependent features (ncurses for
* terminals, an X11 window, a DOS command window...) that attaches to a
@@ -83,6 +85,9 @@ caca_display_t * caca_create_display(cucul_canvas_t *cv)
* retrieved using caca_get_canvas() and it is automatically destroyed when
* caca_free_display() is called.
*
* If no driver name is provided, \e libcaca will try to autodetect the best
* output driver it can.
*
* See also caca_create_display().
*
* If an error occurs, NULL is returned and \b errno is set accordingly:
@@ -121,16 +126,8 @@ caca_display_t * caca_create_display_with_driver(cucul_canvas_t *cv,
return NULL;
}

#if defined(USE_PLUGINS)
dp->plugin = NULL;
#endif

if(caca_select_driver(dp, driver))
if(caca_install_driver(dp, driver))
{
#if defined(USE_PLUGINS)
if(dp->plugin)
dlclose(dp->plugin);
#endif
cucul_unmanage_canvas(cv, (int (*)(void *))caca_can_resize, (void *)dp);
if(dp->autorelease)
cucul_free_canvas(dp->cv);
@@ -139,52 +136,59 @@ caca_display_t * caca_create_display_with_driver(cucul_canvas_t *cv,
return NULL;
}

if(dp->drv.init_graphics(dp))
return dp;
}

/** \brief Get available display drivers
*
* Return a list of available display drivers. The list is a NULL-terminated
* array of strings, interleaving a string containing the internal value for
* the display driver, and a string containing the natural language
* description for that driver.
*
* This function never fails.
*
* \param dp Display object.
* \return An array of strings.
*/
char const * const * caca_get_display_driver_list(void)
{
static char const * const list[] =
{
#if defined(USE_PLUGINS)
if(dp->plugin)
dlclose(dp->plugin);
#if defined(USE_COCOA)
"cocoa", "Mac OS X Cocoa",
#endif
cucul_unmanage_canvas(cv, (int (*)(void *))caca_can_resize, (void *)dp);
if(dp->autorelease)
cucul_free_canvas(dp->cv);
free(dp);
seterrno(ENODEV);
return NULL;
}

/* Graphics stuff */
dp->delay = 0;
dp->rendertime = 0;

/* Events stuff */
#if defined(USE_SLANG) || defined(USE_NCURSES)
dp->events.key_timer.last_sec = 0;
dp->events.key_timer.last_usec = 0;
dp->events.last_key_ticks = 0;
dp->events.autorepeat_ticks = 0;
dp->events.last_key_event.type = CACA_EVENT_NONE;
#if defined(USE_WIN32)
"win32", "Windows console",
#endif
#if defined(USE_SLANG) || defined(USE_NCURSES) || defined(USE_CONIO) || defined(USE_GL)
dp->events.queue = 0;
#if defined(USE_CONIO)
"conio", "MS-DOS conio",
#endif
#if defined(USE_X11)
"x11", "X11 graphical window",
#endif
#if defined(USE_GL)
"gl", "OpenGL window",
#endif
#if defined(USE_SLANG)
"slang", "S-Lang console library",
#endif
#if defined(USE_NCURSES)
"ncurses", "ncurses console library",
#endif
#if defined(USE_VGA)
"vga", "direct VGA memory",
#endif
#if !defined(__KERNEL__)
"raw", "raw libcaca output",
#endif
NULL, NULL
};

dp->timer.last_sec = 0;
dp->timer.last_usec = 0;
dp->lastticks = 0;

/* Mouse position */
dp->mouse.x = cucul_get_canvas_width(dp->cv) / 2;
dp->mouse.y = cucul_get_canvas_height(dp->cv) / 2;

/* Resize events */
dp->resize.resized = 0;
dp->resize.allow = 0;

return dp;
return list;
}

/** \brief Return the current output driver
/** \brief Return a caca graphical context's current output driver.
*
* Return the given display's current output driver.
*
@@ -198,6 +202,29 @@ char const * caca_get_display_driver(caca_display_t *dp)
return dp->drv.driver;
}

/** \brief Set the output driver.
*
* Dynamically change the given display's output driver.
*
* FIXME: decide what to do in case of failure
*
* \param dp The caca display.
* \param driver A string describing the desired output driver or NULL to
* choose the best driver automatically.
* \return 0 in case of success, -1 if an error occurred.
*/
int caca_set_display_driver(caca_display_t *dp, char const *driver)
{
caca_uninstall_driver(dp);
if(caca_install_driver(dp, driver))
{
seterrno(ENODEV);
return -1;
}

return 0;
}

/** \brief Detach a caca graphical context from a cucul backend context.
*
* Detach a graphical context from its cucul backend and destroy it. The
@@ -214,11 +241,7 @@ char const * caca_get_display_driver(caca_display_t *dp)
*/
int caca_free_display(caca_display_t *dp)
{
dp->drv.end_graphics(dp);
#if defined(USE_PLUGINS)
if(dp->plugin)
dlclose(dp->plugin);
#endif
caca_uninstall_driver(dp);
cucul_unmanage_canvas(dp->cv, (int (*)(void *))caca_can_resize, (void *)dp);
if(dp->autorelease)
cucul_free_canvas(dp->cv);
@@ -255,62 +278,79 @@ char const * caca_get_version(void)
return VERSION;
}

/** \brief Get available display drivers
*
* Return a list of available display drivers. The list is a NULL-terminated
* array of strings, interleaving a string containing the internal value for
* the display driver, and a string containing the natural language
* description for that driver.
*
* This function never fails.
*
* \param dp Display object.
* \return An array of strings.
/*
* XXX: The following functions are local.
*/
char const * const * caca_get_display_driver_list(void)

static int caca_can_resize(caca_display_t *dp)
{
static char const * const list[] =
{
#if defined(USE_COCOA)
"cocoa", "Mac OS X Cocoa",
#endif
#if defined(USE_WIN32)
"win32", "Windows console",
#endif
#if defined(USE_CONIO)
"conio", "MS-DOS conio",
#endif
#if defined(USE_X11)
"x11", "X11 graphical window",
#endif
#if defined(USE_GL)
"gl", "OpenGL window",
return dp->resize.allow;
}

static int caca_install_driver(caca_display_t *dp, char const *driver)
{
#if defined(USE_PLUGINS)
dp->plugin = NULL;
#endif
#if !defined(__KERNEL__)
"raw", "raw libcaca output",

if(caca_select_driver(dp, driver))
{
#if defined(USE_PLUGINS)
if(dp->plugin)
dlclose(dp->plugin);
#endif
#if defined(USE_SLANG)
"slang", "S-Lang console library",
return -1;
}

if(dp->drv.init_graphics(dp))
{
#if defined(USE_PLUGINS)
if(dp->plugin)
dlclose(dp->plugin);
#endif
#if defined(USE_NCURSES)
"ncurses", "ncurses console library",
return -1;
}

/* Graphics stuff */
dp->delay = 0;
dp->rendertime = 0;

/* Events stuff */
#if defined(USE_SLANG) || defined(USE_NCURSES)
dp->events.key_timer.last_sec = 0;
dp->events.key_timer.last_usec = 0;
dp->events.last_key_ticks = 0;
dp->events.autorepeat_ticks = 0;
dp->events.last_key_event.type = CACA_EVENT_NONE;
#endif
#if defined(USE_VGA)
"vga", "direct VGA memory",
#if defined(USE_SLANG) || defined(USE_NCURSES) || defined(USE_CONIO) || defined(USE_GL)
dp->events.queue = 0;
#endif
NULL, NULL
};

return list;
}
dp->timer.last_sec = 0;
dp->timer.last_usec = 0;
dp->lastticks = 0;

/*
* XXX: The following functions are local.
*/
/* Mouse position */
dp->mouse.x = cucul_get_canvas_width(dp->cv) / 2;
dp->mouse.y = cucul_get_canvas_height(dp->cv) / 2;

static int caca_can_resize(caca_display_t *dp)
/* Resize events */
dp->resize.resized = 0;
dp->resize.allow = 0;

return 0;
}

static int caca_uninstall_driver(caca_display_t *dp)
{
return dp->resize.allow;
dp->drv.end_graphics(dp);
#if defined(USE_PLUGINS)
if(dp->plugin)
dlclose(dp->plugin);
#endif

return 0;
}

static int caca_select_driver(caca_display_t *dp, char const *driver)


+ 2
- 1
caca/caca.h 查看文件

@@ -156,11 +156,12 @@ enum caca_key
__extern caca_display_t * caca_create_display(cucul_canvas_t *);
__extern caca_display_t * caca_create_display_with_driver(cucul_canvas_t *,
char const *);
__extern char const * const * caca_get_display_driver_list(void);
__extern char const * caca_get_display_driver(caca_display_t *);
__extern int caca_set_display_driver(caca_display_t *, char const *);
__extern int caca_free_display(caca_display_t *);
__extern cucul_canvas_t * caca_get_canvas(caca_display_t *);
__extern int caca_refresh_display(caca_display_t *);
__extern char const * const * caca_get_display_driver_list(void);
__extern int caca_set_display_time(caca_display_t *, unsigned int);
__extern unsigned int caca_get_display_time(caca_display_t const *);
__extern unsigned int caca_get_display_width(caca_display_t const *);


+ 41
- 26
examples/driver.c 查看文件

@@ -16,6 +16,7 @@
#include "common.h"

#if !defined(__KERNEL__)
# include <string.h>
# include <stdio.h>
#endif

@@ -24,47 +25,61 @@

int main(int argc, char *argv[])
{
char const * const * list;
char const * const *list;
caca_display_t *dp;
cucul_canvas_t *cv;

list = caca_get_display_driver_list();
if(argc <= 1)
{
printf("Available drivers:\n");

while(*list)
{
printf(" %s (%s)\n", list[0], list[1]);
list += 2;
}

return 0;
}

cv = cucul_create_canvas(0, 0);
if(cv == NULL)
{
printf("cannot create canvas\n");
return -1;
}
dp = caca_create_display_with_driver(cv, argv[1]);
dp = caca_create_display(NULL);
if(dp == NULL)
{
printf("cannot create display\n");
return -1;
}

cucul_set_color_ansi(cv, CUCUL_WHITE, CUCUL_BLUE);
cucul_draw_line(cv, 0, 0, 9999, 0, ' ');
cucul_printf(cv, 1, 0, "Current driver: %s", argv[1]);
cv = caca_get_canvas(dp);
cucul_set_color_ansi(cv, CUCUL_WHITE, CUCUL_BLACK);

while(1)
{
char const *driver;
int i, cur = 0;

cucul_put_str(cv, 1, 0, "Available drivers:");

driver = caca_get_display_driver(dp);

for(i = 0; list[i]; i += 2)
{
int match = !strcmp(list[i], driver);

if(match)
cur = i;
cucul_draw_line(cv, 0, i + 2, 9999, i + 2, ' ');
cucul_printf(cv, 2, i + 2, "%c %s (%s)",
match ? '*' : ' ', list[i], list[i + 1]);
}

caca_refresh_display(dp);
cucul_put_str(cv, 1, i + 2, "Switching driver in 5 seconds");

caca_get_event(dp, CACA_EVENT_KEY_PRESS, NULL, -1);
caca_refresh_display(dp);

if(caca_get_event(dp, CACA_EVENT_KEY_PRESS, NULL, 5000000))
break;

do
{
cur += 2;
if(list[cur] && !strcmp(list[cur], "raw"))
cur += 2;
if(!list[cur])
cur = 0;
}
while(caca_set_display_driver(dp, list[cur]));
}

caca_free_display(dp);
cucul_free_canvas(cv);

return 0;
}


Loading…
取消
儲存