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

Last change on this file since 1208 was 1208, checked in by Sam Hocevar, 13 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
Line 
1/*
2 *  libcaca       Colour ASCII-Art library
3 *  Copyright (c) 2006 Sam Hocevar <sam@zoy.org>
4 *                All Rights Reserved
5 *
6 *  $Id: caca.c 1208 2006-10-19 22:43:17Z sam $
7 *
8 *  This library is free software; you can redistribute it and/or
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.
12 */
13
14/*
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.
18 */
19
20#include "config.h"
21#include "common.h"
22
23#if !defined(__KERNEL__)
24#   include <stdlib.h>
25#   include <string.h>
26#   include <stdio.h>
27#   if defined(HAVE_ERRNO_H)
28#       include <errno.h>
29#   endif
30#   if defined(USE_PLUGINS)
31#       if defined(HAVE_DLFCN_H)
32#           include <dlfcn.h>
33#       endif
34#   endif
35#endif
36
37#include "cucul.h"
38#include "cucul_internals.h"
39#include "caca.h"
40#include "caca_internals.h"
41
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
46
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
52/** \brief Attach a caca graphical context to a cucul canvas.
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 *
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 *
63 *  \param cv The cucul cavas.
64 *  \return The caca graphical context or NULL if an error occurred.
65 */
66caca_display_t * caca_create_display(cucul_canvas_t * cv)
67{
68    caca_display_t *dp = malloc(sizeof(caca_display_t));
69
70    if(!dp)
71    {
72#if defined(HAVE_ERRNO_H)
73        errno = ENOMEM;
74#endif
75        return NULL;
76    }
77
78    dp->cv = cv;
79#if defined(USE_PLUGINS)
80    dp->plugin = NULL;
81#endif
82
83    if(caca_select_driver(dp))
84    {
85#if defined(USE_PLUGINS)
86        if(dp->plugin)
87            dlclose(dp->plugin);
88#endif
89        free(dp);
90#if defined(HAVE_ERRNO_H)
91        errno = ENODEV;
92#endif
93        return NULL;
94    }
95
96    if(dp->drv.init_graphics(dp))
97    {
98#if defined(USE_PLUGINS)
99        if(dp->plugin)
100            dlclose(dp->plugin);
101#endif
102        free(dp);
103#if defined(HAVE_ERRNO_H)
104        errno = ENODEV;
105#endif
106        return NULL;
107    }
108
109    /* Attached! */
110    dp->cv->refcount++;
111
112    /* Graphics stuff */
113    dp->delay = 0;
114    dp->rendertime = 0;
115
116    /* Events stuff */
117#if defined(USE_SLANG) || defined(USE_NCURSES)
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;
123#endif
124#if defined(USE_SLANG) || defined(USE_NCURSES) || defined(USE_CONIO) || defined(USE_GL)
125    dp->events.queue = 0;
126#endif
127
128    dp->timer.last_sec = 0;
129    dp->timer.last_usec = 0;
130    dp->lastticks = 0;
131
132    /* Mouse position */
133    dp->mouse.x = dp->cv->width / 2;
134    dp->mouse.y = dp->cv->height / 2;
135
136    /* Resize events */
137    dp->resize.resized = 0;
138
139    return dp;
140}
141
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 *
148 *  This function never fails.
149 *
150 *  \param dp The libcaca graphical context.
151 *  \return This function always returns 0.
152 */
153int caca_free_display(caca_display_t *dp)
154{
155    dp->drv.end_graphics(dp);
156#if defined(USE_PLUGINS)
157    if(dp->plugin)
158        dlclose(dp->plugin);
159#endif
160    dp->cv->refcount--;
161    free(dp);
162
163    return 0;
164}
165
166/*
167 * XXX: The following functions are local.
168 */
169
170static int caca_select_driver(caca_display_t *dp)
171{
172#if defined(HAVE_GETENV) && defined(HAVE_STRCASECMP)
173    char *var = getenv("CACA_DRIVER");
174   
175    /* If the environment variable was set, use it */
176    if(var && *var)
177    {
178#if defined(USE_WIN32)
179        if(!strcasecmp(var, "win32")) return win32_install(dp);
180#endif
181#if defined(USE_CONIO)
182        if(!strcasecmp(var, "conio")) return conio_install(dp);
183#endif
184#if defined(USE_X11)
185        if(!strcasecmp(var, "x11")) return x11_install(dp);
186#endif
187#if defined(USE_GL)
188        if(!strcasecmp(var, "gl")) return gl_install(dp);
189#endif
190#if !defined(__KERNEL__)
191        if(!strcasecmp(var, "raw")) return raw_install(dp);
192#endif
193#if defined(USE_SLANG)
194        if(!strcasecmp(var, "slang")) return slang_install(dp);
195#endif
196#if defined(USE_NCURSES)
197        if(!strcasecmp(var, "ncurses")) return ncurses_install(dp);
198#endif
199#if defined(USE_VGA)
200        if(!strcasecmp(var, "vga")) return vga_install(dp);
201#endif
202        return -1;
203    }
204#endif
205
206#if defined(USE_WIN32)
207    if(win32_install(dp) == 0) return 0;
208#endif
209#if defined(USE_CONIO)
210    if(conio_install(dp) == 0) return 0;
211#endif
212#if defined(USE_VGA)
213    if(vga_install(dp) == 0) return 0;
214#endif
215#if defined(USE_X11)
216    if(x11_install(dp) == 0) return 0;
217#endif
218#if defined(USE_GL)
219    if(gl_install(dp) == 0) return 0;
220#endif
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
226#if defined(USE_SLANG)
227    if(slang_install(dp) == 0) return 0;
228#endif
229
230    return -1;
231}
232
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.