]> git.sesse.net Git - vlc/blob - modules/video_output/aa.c
f691ba53f4206127d6eae69c77a69dd62be5af9f
[vlc] / modules / video_output / aa.c
1 /*****************************************************************************
2  * aa.c: "vout display" module using aalib
3  *****************************************************************************
4  * Copyright (C) 2002-2009 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Sigmund Augdal Helberg <dnumgis@videolan.org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <vlc_common.h>
32 #include <vlc_plugin.h>
33 #include <vlc_vout_display.h>
34 #include <vlc_picture_pool.h>
35 #include "keythread.h"
36
37 #include <assert.h>
38 #include <aalib.h>
39
40 /* TODO
41  * - what about RGB palette ?
42  */
43 /*****************************************************************************
44  * Module descriptor
45  *****************************************************************************/
46 static int  Open (vlc_object_t *);
47 static void Close(vlc_object_t *);
48
49 vlc_module_begin()
50     set_shortname(N_("ASCII Art"))
51     set_category(CAT_VIDEO)
52     set_subcategory(SUBCAT_VIDEO_VOUT)
53     set_description(N_("ASCII-art video output"))
54     set_capability("vout display", 10)
55     add_shortcut("aalib")
56     set_callbacks(Open, Close)
57 vlc_module_end()
58
59 /*****************************************************************************
60  * Local prototypes
61  *****************************************************************************/
62 static picture_pool_t *Pool   (vout_display_t *, unsigned);
63 static void            Prepare(vout_display_t *, picture_t *);
64 static void            Display(vout_display_t *, picture_t *);
65 static int             Control(vout_display_t *, int, va_list);
66
67 /* */
68 static void Manage(vout_display_t *);
69
70 /* */
71 struct vout_display_sys_t {
72     struct aa_context*  aa_context;
73     aa_palette          palette;
74
75     vout_display_cfg_t  state;
76     picture_pool_t      *pool;
77     key_thread_t        *keys;
78 };
79
80 /**
81  * This function allocates and initializes a aa vout method.
82  */
83 static int Open(vlc_object_t *object)
84 {
85     vout_display_t *vd = (vout_display_t *)object;
86     vout_display_sys_t *sys;
87
88     /* Allocate structure */
89     vd->sys = sys = calloc(1, sizeof(*sys));
90     if (!sys)
91         return VLC_ENOMEM;
92
93     /* Don't parse any options, but take $AAOPTS into account */
94     aa_parseoptions(NULL, NULL, NULL, NULL);
95
96     /* */
97     sys->aa_context = aa_autoinit(&aa_defparams);
98     if (!sys->aa_context) {
99         msg_Err(vd, "cannot initialize aalib");
100         goto error;
101     }
102     vout_display_DeleteWindow(vd, NULL);
103
104     aa_autoinitkbd(sys->aa_context, 0);
105     aa_autoinitmouse(sys->aa_context, AA_MOUSEALLMASK);
106
107     /* */
108     video_format_t fmt = vd->fmt;
109     fmt.i_chroma = VLC_CODEC_RGB8;
110     fmt.i_width  = aa_imgwidth(sys->aa_context);
111     fmt.i_height = aa_imgheight(sys->aa_context);
112
113     /* */
114     vout_display_info_t info = vd->info;
115     info.has_pictures_invalid = true;
116
117     /* Setup vout_display now that everything is fine */
118     vd->fmt = fmt;
119     vd->info = info;
120
121     vd->pool    = Pool;
122     vd->prepare = Prepare;
123     vd->display = Display;
124     vd->control = Control;
125     vd->manage  = Manage;
126
127     /* Inspect initial configuration and send correction events
128      * FIXME how to handle aspect ratio with aa ? */
129     sys->state = *vd->cfg;
130     sys->state.is_fullscreen = false;
131     vout_display_SendEventFullscreen(vd, false);
132     vout_display_SendEventDisplaySize(vd, fmt.i_width, fmt.i_height, false);
133
134     sys->keys = vlc_CreateKeyThread(vd);
135     return VLC_SUCCESS;
136
137 error:
138     if (sys && sys->aa_context)
139         aa_close(sys->aa_context);
140     free(sys);
141     return VLC_EGENERIC;
142 }
143
144 /**
145  * Close a aa video output method
146  */
147 static void Close(vlc_object_t *object)
148 {
149     vout_display_t *vd = (vout_display_t *)object;
150     vout_display_sys_t *sys = vd->sys;
151
152     vlc_DestroyKeyTread(sys->keys);
153     if (sys->pool)
154         picture_pool_Delete(sys->pool);
155     aa_close(sys->aa_context);
156     free(sys);
157 }
158
159 /**
160  * Return a pool of direct buffers
161  */
162 static picture_pool_t *Pool(vout_display_t *vd, unsigned count)
163 {
164     vout_display_sys_t *sys = vd->sys;
165     VLC_UNUSED(count);
166
167     if (!sys->pool) {
168         picture_resource_t rsc;
169
170         memset(&rsc, 0, sizeof(rsc));
171         rsc.p[0].p_pixels = aa_image(sys->aa_context);
172         rsc.p[0].i_pitch = aa_imgwidth(sys->aa_context);
173         rsc.p[0].i_lines = aa_imgheight(sys->aa_context);
174
175         picture_t *p_picture = picture_NewFromResource(&vd->fmt, &rsc);
176         if (!p_picture)
177             return NULL;
178
179         sys->pool = picture_pool_New(1, &p_picture);
180     }
181     return sys->pool;
182 }
183
184 /**
185  * Prepare a picture for display */
186 static void Prepare(vout_display_t *vd, picture_t *picture)
187 {
188     vout_display_sys_t *sys = vd->sys;
189
190     assert(vd->fmt.i_width  == aa_imgwidth(sys->aa_context) &&
191            vd->fmt.i_height == aa_imgheight(sys->aa_context));
192
193 #if 0
194     if (picture->format.p_palette) {
195         for (int i = 0; i < 256; i++) {
196             aa_setpalette(vd->sys->palette, 256 - i,
197                            red[ i ], green[ i ], blue[ i ]);
198         }
199     }
200 #else
201     VLC_UNUSED(picture);
202 #endif
203
204     aa_fastrender(sys->aa_context, 0, 0,
205                   vd->fmt.i_width, vd->fmt.i_height);
206 }
207
208 /**
209  * Display a picture
210  */
211 static void Display(vout_display_t *vd, picture_t *picture)
212 {
213     vout_display_sys_t *sys = vd->sys;
214
215     aa_flush(sys->aa_context);
216     picture_Release(picture);
217 }
218
219 /**
220  * Control for vout display
221  */
222 static int Control(vout_display_t *vd, int query, va_list args)
223 {
224     VLC_UNUSED(args);
225     vout_display_sys_t *sys = vd->sys;
226
227     switch (query) {
228     case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE:
229         /* We have to ignore what is requested */
230         vout_display_SendEventPicturesInvalid(vd);
231         return VLC_SUCCESS;
232
233     case VOUT_DISPLAY_RESET_PICTURES:
234         if (sys->pool)
235             picture_pool_Delete(sys->pool);
236         sys->pool = NULL;
237
238         vd->fmt.i_width  = aa_imgwidth(sys->aa_context);
239         vd->fmt.i_height = aa_imgheight(sys->aa_context);
240         return VLC_SUCCESS;
241
242     case VOUT_DISPLAY_HIDE_MOUSE:
243         aa_hidemouse(sys->aa_context);
244         return VLC_SUCCESS;
245
246     default:
247         msg_Err(vd, "Unsupported query in vout display aalib");
248         return VLC_EGENERIC;
249     }
250 }
251
252
253 /**
254  * Proccess pending event
255  */
256 static void Manage(vout_display_t *vd)
257 {
258     vout_display_sys_t *sys = vd->sys;
259
260     for (;;) {
261         const int event = aa_getevent(sys->aa_context, 0);
262         if (!event)
263             return;
264
265         switch (event) {
266         case AA_MOUSE: {
267             int x, y;
268             int button;
269             int vlc;
270             aa_getmouse(sys->aa_context, &x, &y, &button);
271
272             vlc = 0;
273             if (button & AA_BUTTON1)
274                 vlc |= 1 << MOUSE_BUTTON_LEFT;
275             if (button & AA_BUTTON2)
276                 vlc |= 1 << MOUSE_BUTTON_CENTER;
277             if (button & AA_BUTTON3)
278                 vlc |= 1 << MOUSE_BUTTON_RIGHT;
279
280             vout_display_SendEventMouseState(vd, x, y, vlc);
281
282             aa_showcursor(sys->aa_context); /* Not perfect, we show it on click too */
283             break;
284         }
285
286         case AA_RESIZE:
287             aa_resize(sys->aa_context);
288             vout_display_SendEventDisplaySize(vd,
289                                               aa_imgwidth(sys->aa_context),
290                                               aa_imgheight(sys->aa_context), false);
291             break;
292
293         /* TODO keys support to complete */
294         case AA_UP:
295             vlc_EmitKey(sys->keys, KEY_UP);
296             break;
297         case AA_DOWN:
298             vlc_EmitKey(sys->keys, KEY_DOWN);
299             break;
300         case AA_RIGHT:
301             vlc_EmitKey(sys->keys, KEY_RIGHT);
302             break;
303         case AA_LEFT:
304             vlc_EmitKey(sys->keys, KEY_LEFT);
305             break;
306         case AA_BACKSPACE:
307             vlc_EmitKey(sys->keys, KEY_BACKSPACE);
308             break;
309         case AA_ESC:
310             vlc_EmitKey(sys->keys, KEY_ESC);
311             break;
312         default:
313             if (event >= 0x20 && event <= 0x7f)
314                 vlc_EmitKey(sys->keys, event);
315             break;
316         }
317     }
318 }
319