mixer: fix lowering hw volume while muted
[mplayer.git] / libvo / vo_caca.c
blob74352397b34e1214ee317c27e3125d85d727e475
1 /*
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.
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <sys/stat.h>
30 #include <unistd.h>
31 #include <string.h>
32 #include <time.h>
33 #include <errno.h>
35 #include "config.h"
36 #include "video_out.h"
37 #include "video_out_internal.h"
38 #include "sub/sub.h"
40 #include "input/keycodes.h"
41 #include "mp_msg.h"
42 #include "mp_fifo.h"
44 #include <caca.h>
45 #ifdef CACA_API_VERSION_1
46 /* Include the pre-1.x compatibility header.
47 * Once libcaca 1.x is widespread, vo_caca should be fully
48 * converted to the new API. A patch exists:
49 * http://lists.mplayerhq.hu/pipermail/mplayer-dev-eng/2006-July/044669.html
51 #include <caca0.h>
52 #endif
54 static const vo_info_t info = {
55 "libcaca",
56 "caca",
57 "Pigeon <pigeon@pigeond.net>",
61 const LIBVO_EXTERN (caca)
63 /* caca stuff */
64 static struct caca_bitmap *cbitmap = NULL;
66 /* image infos */
67 static int image_format;
68 static int image_width;
69 static int image_height;
71 static int screen_w, screen_h;
73 /* We want 24bpp always for now */
74 static unsigned int bpp = 24;
75 static unsigned int depth = 3;
76 static unsigned int rmask = 0xff0000;
77 static unsigned int gmask = 0x00ff00;
78 static unsigned int bmask = 0x0000ff;
79 static unsigned int amask = 0;
81 #define MESSAGE_SIZE 512
82 #define MESSAGE_DURATION 5
84 static time_t stoposd = 0;
85 static int showosdmessage = 0;
86 static char osdmessagetext[MESSAGE_SIZE];
87 static char posbar[MESSAGE_SIZE];
89 static int osdx = 0, osdy = 0;
90 static int posbary = 2;
92 static void osdmessage(int duration, const char *fmt, ...)
95 * for outputting a centered string at the bottom
96 * of our window for a while
98 va_list ar;
99 char m[MESSAGE_SIZE];
101 va_start(ar, fmt);
102 vsprintf(m, fmt, ar);
103 va_end(ar);
104 strcpy(osdmessagetext, m);
106 showosdmessage = 1;
107 stoposd = time(NULL) + duration;
108 osdx = (screen_w - strlen (osdmessagetext)) / 2;
109 posbar[0] = '\0';
112 static void osdpercent(int duration, int min, int max, int val, const char *desc, const char *unit)
115 * prints a bar for setting values
117 float step;
118 int where, i;
120 step = (float)screen_w / (float)(max - min);
121 where = (val - min) * step;
122 osdmessage (duration, "%s: %i%s", desc, val, unit);
123 posbar[0] = '|';
124 posbar[screen_w - 1] = '|';
126 for (i = 0; i < screen_w; i++)
128 if (i == where)
129 posbar[i] = '#';
130 else
131 posbar[i] = '-';
134 if (where != 0)
135 posbar[0] = '|';
137 if (where != (screen_w - 1))
138 posbar[screen_w - 1] = '|';
140 posbar[screen_w] = '\0';
143 static int resize(void)
145 screen_w = caca_get_width();
146 screen_h = caca_get_height();
148 if (cbitmap)
149 caca_free_bitmap(cbitmap);
151 cbitmap = caca_create_bitmap(bpp, image_width, image_height,
152 depth * image_width, rmask, gmask, bmask,
153 amask);
155 if (!cbitmap)
156 mp_msg(MSGT_VO, MSGL_FATAL, "vo_caca: caca_create_bitmap failed!\n");
158 return 0;
161 static int config(uint32_t width, uint32_t height, uint32_t d_width,
162 uint32_t d_height, uint32_t flags, char *title, uint32_t format)
164 image_height = height;
165 image_width = width;
166 image_format = format;
168 showosdmessage = 0;
169 posbar[0] = '\0';
171 return resize ();
174 static int draw_frame(uint8_t *src[])
176 caca_draw_bitmap(0, 0, screen_w, screen_h, cbitmap, src[0]);
177 return 0;
180 static int draw_slice(uint8_t *src[], int stride[], int w, int h, int x, int y)
182 return 0;
185 static void flip_page(void)
188 if (showosdmessage)
190 if (time(NULL) >= stoposd)
192 showosdmessage = 0;
193 if (*posbar)
194 posbar[0] = '\0';
195 } else {
196 caca_putstr(osdx, osdy, osdmessagetext);
198 if (*posbar)
199 caca_putstr(0, posbary, posbar);
203 caca_refresh();
206 static void check_events (void)
208 unsigned int cev;
210 if ((cev = caca_get_event(CACA_EVENT_ANY)))
212 if (cev & CACA_EVENT_RESIZE)
214 caca_refresh();
215 resize();
216 } else if (cev & CACA_EVENT_KEY_RELEASE)
218 int key = (cev & 0x00ffffff);
219 enum caca_feature cf;
221 switch (key) {
222 case 'd':
223 case 'D':
224 /* Toggle dithering method */
225 cf = 1 + caca_get_feature(CACA_DITHERING);
226 if (cf > CACA_DITHERING_MAX)
227 cf = CACA_DITHERING_MIN;
228 caca_set_feature(cf);
229 osdmessage(MESSAGE_DURATION, "Using %s", caca_get_feature_name(cf));
230 break;
232 case 'a':
233 case 'A':
234 /* Toggle antialiasing method */
235 cf = 1 + caca_get_feature(CACA_ANTIALIASING);
236 if (cf > CACA_ANTIALIASING_MAX)
237 cf = CACA_ANTIALIASING_MIN;
238 caca_set_feature(cf);
239 osdmessage(MESSAGE_DURATION, "Using %s", caca_get_feature_name(cf));
240 break;
242 case 'b':
243 case 'B':
244 /* Toggle background method */
245 cf = 1 + caca_get_feature(CACA_BACKGROUND);
246 if (cf > CACA_BACKGROUND_MAX)
247 cf = CACA_BACKGROUND_MIN;
248 caca_set_feature(cf);
249 osdmessage(MESSAGE_DURATION, "Using %s", caca_get_feature_name(cf));
250 break;
252 case CACA_KEY_UP:
253 mplayer_put_key(KEY_UP);
254 break;
255 case CACA_KEY_DOWN:
256 mplayer_put_key(KEY_DOWN);
257 break;
258 case CACA_KEY_LEFT:
259 mplayer_put_key(KEY_LEFT);
260 break;
261 case CACA_KEY_RIGHT:
262 mplayer_put_key(KEY_RIGHT);
263 break;
264 case CACA_KEY_ESCAPE:
265 mplayer_put_key(KEY_ESC);
266 break;
267 case CACA_KEY_PAGEUP:
268 mplayer_put_key(KEY_PAGE_UP);
269 break;
270 case CACA_KEY_PAGEDOWN:
271 mplayer_put_key(KEY_PAGE_DOWN);
272 break;
273 case CACA_KEY_RETURN:
274 mplayer_put_key(KEY_ENTER);
275 break;
276 case CACA_KEY_HOME:
277 mplayer_put_key(KEY_HOME);
278 break;
279 case CACA_KEY_END:
280 mplayer_put_key(KEY_END);
281 break;
282 default:
283 if (key <= 255)
284 mplayer_put_key (key);
285 break;
291 static void uninit(void)
293 caca_free_bitmap(cbitmap);
294 cbitmap = NULL;
295 caca_end();
299 static void draw_osd(void)
301 if (vo_osd_progbar_type != -1)
302 osdpercent(MESSAGE_DURATION, 0, 255,
303 vo_osd_progbar_value, sub_osd_names[vo_osd_progbar_type],
304 "");
307 static int preinit(const char *arg)
309 if (arg)
311 mp_msg(MSGT_VO, MSGL_ERR, "vo_caca: Unknown subdevice: %s\n", arg);
312 return ENOSYS;
315 if (caca_init())
317 mp_msg(MSGT_VO, MSGL_ERR, "vo_caca: failed to initialize\n");
318 return ENOSYS;
321 caca_set_window_title("MPlayer");
323 /* Default libcaca features */
324 caca_set_feature(CACA_ANTIALIASING_PREFILTER);
325 caca_set_feature(CACA_DITHERING_RANDOM);
327 return 0;
330 static int query_format(uint32_t format)
332 if (format == IMGFMT_BGR24)
333 return VFCAP_OSD | VFCAP_CSP_SUPPORTED;
335 return 0;
338 static int control(uint32_t request, void *data)
340 switch(request)
342 case VOCTRL_QUERY_FORMAT:
343 return query_format(*((uint32_t *)data));
344 default:
345 return VO_NOTIMPL;