2 * video output driver for libcaca
4 * by Pigeon <pigeon@pigeond.net>
6 * Some functions/codes/ideas are from x11 and aalib vo
8 * TODO: support draw_alpha?
10 * This file is part of MPlayer.
12 * MPlayer is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * MPlayer is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License along
23 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
36 #include "video_out.h"
37 #include "video_out_internal.h"
40 #include "osdep/keycodes.h"
46 static const vo_info_t info
= {
49 "Pigeon <pigeon@pigeond.net>",
53 const LIBVO_EXTERN (caca
)
56 static caca_canvas_t
*canvas
;
57 static caca_display_t
*display
;
58 static caca_dither_t
*dither
= NULL
;
59 static const char *dither_antialias
= "default";
60 static const char *dither_charset
= "default";
61 static const char *dither_color
= "default";
62 static const char *dither_algo
= "none";
65 static int image_format
;
66 static int image_width
;
67 static int image_height
;
69 static int screen_w
, screen_h
;
71 /* We want 24bpp always for now */
72 static unsigned int bpp
= 24;
73 static unsigned int depth
= 3;
74 static unsigned int rmask
= 0xff0000;
75 static unsigned int gmask
= 0x00ff00;
76 static unsigned int bmask
= 0x0000ff;
77 static unsigned int amask
= 0;
79 #define MESSAGE_SIZE 512
80 #define MESSAGE_DURATION 5
82 static time_t stoposd
= 0;
83 static int showosdmessage
= 0;
84 static char osdmessagetext
[MESSAGE_SIZE
];
85 static char posbar
[MESSAGE_SIZE
];
87 static int osdx
= 0, osdy
= 0;
88 static int posbary
= 2;
90 static void osdmessage(int duration
, const char *fmt
, ...)
93 * for outputting a centered string at the bottom
94 * of our window for a while
100 vsprintf(m
, fmt
, ar
);
102 strcpy(osdmessagetext
, m
);
105 stoposd
= time(NULL
) + duration
;
106 osdx
= (screen_w
- strlen (osdmessagetext
)) / 2;
110 static void osdpercent(int duration
, int min
, int max
, int val
, const char *desc
, const char *unit
)
113 * prints a bar for setting values
118 step
= (float)screen_w
/ (float)(max
- min
);
119 where
= (val
- min
) * step
;
120 osdmessage (duration
, "%s: %i%s", desc
, val
, unit
);
122 posbar
[screen_w
- 1] = '|';
124 for (i
= 0; i
< screen_w
; i
++)
135 if (where
!= (screen_w
- 1))
136 posbar
[screen_w
- 1] = '|';
138 posbar
[screen_w
] = '\0';
141 static int resize(void)
143 screen_w
= caca_get_canvas_width(canvas
);
144 screen_h
= caca_get_canvas_height(canvas
);
147 caca_free_dither(dither
);
149 dither
= caca_create_dither(bpp
, image_width
, image_height
,
150 depth
* image_width
, rmask
, gmask
, bmask
,
153 /* Default libcaca features */
154 caca_set_dither_antialias(dither
, dither_antialias
);
155 caca_set_dither_charset(dither
, dither_charset
);
156 caca_set_dither_color(dither
, dither_color
);
157 caca_set_dither_algorithm(dither
, dither_algo
);
160 mp_msg(MSGT_VO
, MSGL_FATAL
, "vo_caca: caca_create_dither failed!\n");
164 static int config(uint32_t width
, uint32_t height
, uint32_t d_width
,
165 uint32_t d_height
, uint32_t flags
, char *title
, uint32_t format
)
167 image_height
= height
;
169 image_format
= format
;
177 static int draw_frame(uint8_t *src
[])
179 caca_dither_bitmap(canvas
, 0, 0, screen_w
, screen_h
, dither
, src
[0]);
183 static int draw_slice(uint8_t *src
[], int stride
[], int w
, int h
, int x
, int y
)
188 static void flip_page(void)
193 if (time(NULL
) >= stoposd
)
199 caca_put_str(canvas
, osdx
, osdy
, osdmessagetext
);
201 caca_put_str(canvas
, 0, posbary
, posbar
);
204 caca_refresh_display(display
);
207 static void set_next_str(const char * const *list
, const char ** str
,
210 for(ind
= 0; list
[ind
]; ind
+=2) {
211 if(strcmp(list
[ind
], *str
) == 0)
213 if(list
[ind
+2] == NULL
)
225 static void check_events (void)
228 if (!caca_get_event(display
, CACA_EVENT_ANY
, &cev
, 1))
233 case CACA_EVENT_RESIZE
:
234 caca_refresh_display(display
);
238 case CACA_EVENT_KEY_RELEASE
:
240 int key
= cev
.data
.key
.ch
;
241 const char *msg_name
;
247 /* Toggle dithering algorithm */
248 set_next_str(caca_get_dither_algorithm_list(dither
), &dither_algo
, &msg_name
);
249 caca_set_dither_algorithm(dither
, dither_algo
);
250 osdmessage(MESSAGE_DURATION
, "Using %s", msg_name
);
255 /* Toggle antialiasing method */
256 set_next_str(caca_get_dither_antialias_list(dither
), &dither_antialias
, &msg_name
);
257 caca_set_dither_antialias(dither
, dither_antialias
);
258 osdmessage(MESSAGE_DURATION
, "Using %s", msg_name
);
263 /* Toggle charset method */
264 set_next_str(caca_get_dither_charset_list(dither
), &dither_charset
, &msg_name
);
265 caca_set_dither_charset(dither
, dither_charset
);
266 osdmessage(MESSAGE_DURATION
, "Using %s", msg_name
);
271 /* Toggle color method */
272 set_next_str(caca_get_dither_color_list(dither
), &dither_color
, &msg_name
);
273 caca_set_dither_color(dither
, dither_color
);
274 osdmessage(MESSAGE_DURATION
, "Using %s", msg_name
);
278 mplayer_put_key(KEY_UP
);
281 mplayer_put_key(KEY_DOWN
);
284 mplayer_put_key(KEY_LEFT
);
287 mplayer_put_key(KEY_RIGHT
);
289 case CACA_KEY_ESCAPE
:
290 mplayer_put_key(KEY_ESC
);
292 case CACA_KEY_PAGEUP
:
293 mplayer_put_key(KEY_PAGE_UP
);
295 case CACA_KEY_PAGEDOWN
:
296 mplayer_put_key(KEY_PAGE_DOWN
);
298 case CACA_KEY_RETURN
:
299 mplayer_put_key(KEY_ENTER
);
302 mplayer_put_key(KEY_HOME
);
305 mplayer_put_key(KEY_END
);
309 mplayer_put_key (key
);
316 static void uninit(void)
318 caca_free_dither(dither
);
320 caca_free_display(display
);
321 caca_free_canvas(canvas
);
325 static void draw_osd(void)
327 if (vo_osd_progbar_type
!= -1)
328 osdpercent(MESSAGE_DURATION
, 0, 255,
329 vo_osd_progbar_value
, sub_osd_names
[vo_osd_progbar_type
],
333 static int preinit(const char *arg
)
335 const char *caca_driver
= NULL
;
338 char const * const *list
= caca_get_display_driver_list();
340 for (i
=0; list
[i
]; i
+=2)
342 if (strcmp(arg
, "list"))
344 if (strcmp(arg
, list
[i
])) continue;
348 mp_msg(MSGT_VO
, MSGL_INFO
, "vo_caca: %s\t%s\n", list
[i
], list
[i
+1]);
350 if (!strcmp(arg
, "list")) return ENOSYS
;
353 mp_msg(MSGT_VO
, MSGL_ERR
, "vo_caca: invalid subdevice, use -vo caca:list to display available drivers\n");
358 if ((canvas
= caca_create_canvas(0, 0)) == NULL
)
360 mp_msg(MSGT_VO
, MSGL_ERR
, "vo_caca: failed to create canvas\n");
366 if ((display
= caca_create_display_with_driver(canvas
, caca_driver
)) == NULL
)
368 mp_msg(MSGT_VO
, MSGL_ERR
, "vo_caca: failed to create display\n");
373 if ((display
= caca_create_display(canvas
)) == NULL
)
375 mp_msg(MSGT_VO
, MSGL_ERR
, "vo_caca: failed to create display\n");
379 caca_set_display_title(display
, "MPlayer");
384 static int query_format(uint32_t format
)
386 if (format
== IMGFMT_BGR24
)
387 return VFCAP_OSD
| VFCAP_CSP_SUPPORTED
;
392 static int control(uint32_t request
, void *data
)
396 case VOCTRL_QUERY_FORMAT
:
397 return query_format(*((uint32_t *)data
));