source: libcaca/trunk/caca/caca.c @ 1208

Last change on this file since 1208 was 1208, checked in by Sam Hocevar, 14 years ago
  • Added a --enable-plugins configure flag that builds the GL and X11 drivers as plugins. This way, libcaca does not directly depend on those libraries.
  • Property svn:keywords set to Id
File size: 6.2 KB
RevLine 
[35]1/*
[672]2 *  libcaca       Colour ASCII-Art library
[699]3 *  Copyright (c) 2006 Sam Hocevar <sam@zoy.org>
[268]4 *                All Rights Reserved
[35]5 *
[769]6 *  $Id: caca.c 1208 2006-10-19 22:43:17Z sam $
7 *
[268]8 *  This library is free software; you can redistribute it and/or
[522]9 *  modify it under the terms of the Do What The Fuck You Want To
10 *  Public License, Version 2, as published by Sam Hocevar. See
11 *  http://sam.zoy.org/wtfpl/COPYING for more details.
[35]12 */
[17]13
[769]14/*
[268]15 *  This file contains the main functions used by \e libcaca applications to
16 *  initialise the library, get the screen properties, set the framerate and
17 *  so on.
[205]18 */
19
[63]20#include "config.h"
[859]21#include "common.h"
[63]22
[565]23#if !defined(__KERNEL__)
24#   include <stdlib.h>
25#   include <string.h>
[1208]26#   include <stdio.h>
[1006]27#   if defined(HAVE_ERRNO_H)
28#       include <errno.h>
29#   endif
[1208]30#   if defined(USE_PLUGINS)
31#       if defined(HAVE_DLFCN_H)
32#           include <dlfcn.h>
33#       endif
34#   endif
[565]35#endif
[17]36
[524]37#include "cucul.h"
38#include "cucul_internals.h"
[185]39#include "caca.h"
40#include "caca_internals.h"
[17]41
[1208]42#if defined(USE_PLUGINS)
43#   define gl_install(p) caca_plugin_install("gl", p)
44#   define x11_install(p) caca_plugin_install("x11", p)
45#endif
[227]46
[1208]47static int caca_select_driver(caca_display_t *);
48#if defined(USE_PLUGINS)
49static int caca_plugin_install(char const *, caca_display_t *);
50#endif
51
[810]52/** \brief Attach a caca graphical context to a cucul canvas.
[540]53 *
54 *  Create a graphical context using device-dependent features (ncurses for
55 *  terminals, an X11 window, a DOS command window...) that attaches to a
56 *  libcucul canvas. Everything that gets drawn in the libcucul canvas can
57 *  then be displayed by the libcaca driver.
58 *
[1006]59 *  If an error occurs, NULL is returned and \b errno is set accordingly:
60 *  - \c ENOMEM Not enough memory.
61 *  - \c ENODEV Graphical device could not be initialised.
62 *
[811]63 *  \param cv The cucul cavas.
[540]64 *  \return The caca graphical context or NULL if an error occurred.
65 */
[819]66caca_display_t * caca_create_display(cucul_canvas_t * cv)
[17]67{
[811]68    caca_display_t *dp = malloc(sizeof(caca_display_t));
[524]69
[1006]70    if(!dp)
71    {
72#if defined(HAVE_ERRNO_H)
73        errno = ENOMEM;
74#endif
75        return NULL;
76    }
77
[811]78    dp->cv = cv;
[1208]79#if defined(USE_PLUGINS)
80    dp->plugin = NULL;
81#endif
[232]82
[1006]83    if(caca_select_driver(dp))
[539]84    {
[1208]85#if defined(USE_PLUGINS)
86        if(dp->plugin)
87            dlclose(dp->plugin);
88#endif
[811]89        free(dp);
[1006]90#if defined(HAVE_ERRNO_H)
91        errno = ENODEV;
92#endif
[524]93        return NULL;
[265]94    }
[79]95
[811]96    if(dp->drv.init_graphics(dp))
[335]97    {
[1208]98#if defined(USE_PLUGINS)
99        if(dp->plugin)
100            dlclose(dp->plugin);
101#endif
[811]102        free(dp);
[1006]103#if defined(HAVE_ERRNO_H)
104        errno = ENODEV;
105#endif
[539]106        return NULL;
[483]107    }
[213]108
[540]109    /* Attached! */
[811]110    dp->cv->refcount++;
[540]111
112    /* Graphics stuff */
[811]113    dp->delay = 0;
114    dp->rendertime = 0;
[540]115
116    /* Events stuff */
117#if defined(USE_SLANG) || defined(USE_NCURSES)
[811]118    dp->events.key_timer.last_sec = 0;
119    dp->events.key_timer.last_usec = 0;
120    dp->events.last_key_ticks = 0;
121    dp->events.autorepeat_ticks = 0;
122    dp->events.last_key_event.type = CACA_EVENT_NONE;
[540]123#endif
[681]124#if defined(USE_SLANG) || defined(USE_NCURSES) || defined(USE_CONIO) || defined(USE_GL)
[811]125    dp->events.queue = 0;
[593]126#endif
[527]127
[811]128    dp->timer.last_sec = 0;
129    dp->timer.last_usec = 0;
130    dp->lastticks = 0;
[527]131
[553]132    /* Mouse position */
[811]133    dp->mouse.x = dp->cv->width / 2;
134    dp->mouse.y = dp->cv->height / 2;
[541]135
[553]136    /* Resize events */
[811]137    dp->resize.resized = 0;
[306]138
[811]139    return dp;
[17]140}
141
[540]142/** \brief Detach a caca graphical context from a cucul backend context.
143 *
144 *  Detach a graphical context from its cucul backend and destroy it. The
145 *  libcucul canvas continues to exist and other graphical contexts can be
146 *  attached to it afterwards.
147 *
[1006]148 *  This function never fails.
149 *
[811]150 *  \param dp The libcaca graphical context.
[1006]151 *  \return This function always returns 0.
[540]152 */
[1006]153int caca_free_display(caca_display_t *dp)
[17]154{
[811]155    dp->drv.end_graphics(dp);
[1208]156#if defined(USE_PLUGINS)
157    if(dp->plugin)
158        dlclose(dp->plugin);
159#endif
[811]160    dp->cv->refcount--;
161    free(dp);
[1006]162
163    return 0;
[17]164}
165
[268]166/*
167 * XXX: The following functions are local.
168 */
169
[1006]170static int caca_select_driver(caca_display_t *dp)
[265]171{
172#if defined(HAVE_GETENV) && defined(HAVE_STRCASECMP)
173    char *var = getenv("CACA_DRIVER");
[586]174   
[265]175    /* If the environment variable was set, use it */
176    if(var && *var)
[623]177    {
[335]178#if defined(USE_WIN32)
[811]179        if(!strcasecmp(var, "win32")) return win32_install(dp);
[335]180#endif
[265]181#if defined(USE_CONIO)
[811]182        if(!strcasecmp(var, "conio")) return conio_install(dp);
[265]183#endif
[285]184#if defined(USE_X11)
[811]185        if(!strcasecmp(var, "x11")) return x11_install(dp);
[265]186#endif
[483]187#if defined(USE_GL)
[811]188        if(!strcasecmp(var, "gl")) return gl_install(dp);
[483]189#endif
[1054]190#if !defined(__KERNEL__)
[811]191        if(!strcasecmp(var, "raw")) return raw_install(dp);
[1054]192#endif
[265]193#if defined(USE_SLANG)
[811]194        if(!strcasecmp(var, "slang")) return slang_install(dp);
[265]195#endif
[285]196#if defined(USE_NCURSES)
[811]197        if(!strcasecmp(var, "ncurses")) return ncurses_install(dp);
[265]198#endif
[565]199#if defined(USE_VGA)
[811]200        if(!strcasecmp(var, "vga")) return vga_install(dp);
[565]201#endif
[684]202        return -1;
[265]203    }
204#endif
205
[335]206#if defined(USE_WIN32)
[811]207    if(win32_install(dp) == 0) return 0;
[335]208#endif
[265]209#if defined(USE_CONIO)
[811]210    if(conio_install(dp) == 0) return 0;
[265]211#endif
[565]212#if defined(USE_VGA)
[811]213    if(vga_install(dp) == 0) return 0;
[565]214#endif
[285]215#if defined(USE_X11)
[811]216    if(x11_install(dp) == 0) return 0;
[265]217#endif
[483]218#if defined(USE_GL)
[811]219    if(gl_install(dp) == 0) return 0;
[483]220#endif
[984]221    /* ncurses has a higher priority than slang because it has better colour
222     * support across terminal types, despite being slightly slower. */
223#if defined(USE_NCURSES)
224    if(ncurses_install(dp) == 0) return 0;
225#endif
[265]226#if defined(USE_SLANG)
[811]227    if(slang_install(dp) == 0) return 0;
[265]228#endif
[487]229
[539]230    return -1;
[265]231}
232
[1208]233#if defined(USE_PLUGINS)
234static int caca_plugin_install(char const *name, caca_display_t *dp)
235{
236    char buf[512];
237    int (*sym) (caca_display_t *);
238
239    sprintf(buf, "%s/lib%s_plugin.so", PLUGINDIR, name);
240    dp->plugin = dlopen(buf, RTLD_NOW);
241    if(!dp->plugin)
242    {
243        sprintf(buf, "lib%s_plugin.so", name);
244        dp->plugin = dlopen(buf, RTLD_NOW);
245        if(!dp->plugin)
246            return -1;
247    }
248
249    sprintf(buf, "%s_install", name);
250    sym = dlsym(dp->plugin, buf);
251    if(!sym)
252    {
253        dlclose(dp->plugin);
254        return -1;
255    }
256
257    return sym(dp);
258}
259#endif
260
Note: See TracBrowser for help on using the repository browser.