X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fvideo_output%2Fcaca.c;h=6de1ca19a27898fd10f6947bd3a7eecb2d6bb392;hb=f659703fb4033420e0607d34bc7cd880a5802ea7;hp=d044a3d5ea0aff0a9caac7bfaca1fcddac107233;hpb=55c960749e8f91763e720ac610d5dd56f90fcde1;p=vlc diff --git a/modules/video_output/caca.c b/modules/video_output/caca.c index d044a3d5ea..6de1ca19a2 100644 --- a/modules/video_output/caca.c +++ b/modules/video_output/caca.c @@ -1,10 +1,11 @@ /***************************************************************************** - * caca.c: Color ASCII Art video output plugin using libcaca + * caca.c: Color ASCII Art "vout display" module using libcaca ***************************************************************************** * Copyright (C) 2003-2009 the VideoLAN team * $Id$ * * Authors: Sam Hocevar + * Laurent Aimar * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -31,393 +32,501 @@ #include #include -#include -#include -#include -#include +#include +#include #include -#ifndef CACA_API_VERSION_1 - /* Upward compatibility macros */ - typedef char cucul_canvas_t; - typedef struct caca_bitmap cucul_dither_t; - typedef char caca_display_t; -# define CUCUL_COLOR_DEFAULT CACA_COLOR_LIGHTGRAY -# define CUCUL_COLOR_BLACK CACA_COLOR_BLACK -# define cucul_clear_canvas(x) caca_clear() -# define cucul_create_canvas(x,y) "" /* kinda hacky */ -# define cucul_create_dither caca_create_bitmap -# define cucul_dither_bitmap(x,y,z,t,u,v,w) caca_draw_bitmap(y,z,t,u,v,w) -# define cucul_free_dither caca_free_bitmap -# define cucul_free_canvas(x) -# define cucul_get_canvas_width(x) caca_get_width() -# define cucul_get_canvas_height(x) caca_get_height() -# define cucul_set_color(x,y,z) caca_set_color(y,z) -# define caca_create_display(x) (caca_init() ? NULL : "") /* hacky, too */ -# define caca_free_display(x) caca_end() -# define caca_get_event(x,y,z,t) *(z) = caca_get_event(y) -# define caca_refresh_display(x) caca_refresh() -# define caca_set_display_title(x,y) caca_set_window_title(y) -#endif - -/***************************************************************************** - * Local prototypes - *****************************************************************************/ -static int Create ( vlc_object_t * ); -static void Destroy ( vlc_object_t * ); - -static int Init ( vout_thread_t * ); -static void End ( vout_thread_t * ); -static int Manage ( vout_thread_t * ); -static void Render ( vout_thread_t *, picture_t * ); -static void Display ( vout_thread_t *, picture_t * ); - /***************************************************************************** * Module descriptor *****************************************************************************/ -vlc_module_begin () - set_shortname( "Caca" ) - set_category( CAT_VIDEO ) - set_subcategory( SUBCAT_VIDEO_VOUT ) - set_description( N_("Color ASCII art video output") ) - set_capability( "video output", 12 ) - set_callbacks( Create, Destroy ) -vlc_module_end () +static int Open (vlc_object_t *); +static void Close(vlc_object_t *); + +vlc_module_begin() + set_shortname("Caca") + set_category(CAT_VIDEO) + set_subcategory(SUBCAT_VIDEO_VOUT) + set_description(N_("Color ASCII art video output")) + set_capability("vout display", 12) + set_callbacks(Open, Close) +vlc_module_end() /***************************************************************************** - * vout_sys_t: libcaca video output method descriptor - ***************************************************************************** - * This structure is part of the video output thread descriptor. - * It describes the libcaca specific properties of an output thread. + * Local prototypes *****************************************************************************/ -struct vout_sys_t -{ - cucul_canvas_t *p_cv; - caca_display_t *p_dp; - cucul_dither_t *p_dither; +static picture_pool_t *Pool (vout_display_t *, unsigned); +static void Prepare(vout_display_t *, picture_t *); +static void Display(vout_display_t *, picture_t *); +static int Control(vout_display_t *, int, va_list); + +/* */ +static void Manage(vout_display_t *); +static void Refresh(vout_display_t *); +static void Place(vout_display_t *, vout_display_place_t *); + +/* */ +struct vout_display_sys_t { + cucul_canvas_t *cv; + caca_display_t *dp; + cucul_dither_t *dither; + + picture_pool_t *pool; }; -/***************************************************************************** - * Create: allocates libcaca video output thread - ***************************************************************************** +/** * This function initializes libcaca vout method. - *****************************************************************************/ -static int Create( vlc_object_t *p_this ) + */ +static int Open(vlc_object_t *object) { - vout_thread_t *p_vout = (vout_thread_t *)p_this; + vout_display_t *vd = (vout_display_t *)object; + vout_display_sys_t *sys; -#if defined( WIN32 ) && !defined( UNDER_CE ) +#if defined(WIN32) && !defined(UNDER_CE) CONSOLE_SCREEN_BUFFER_INFO csbiInfo; SMALL_RECT rect; COORD coord; HANDLE hstdout; - if( !AllocConsole() ) - { - msg_Err( p_vout, "cannot create console" ); + if (!AllocConsole()) { + msg_Err(vd, "cannot create console"); return VLC_EGENERIC; } hstdout = - CreateConsoleScreenBuffer( GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, CONSOLE_TEXTMODE_BUFFER, NULL ); - if( !hstdout || hstdout == INVALID_HANDLE_VALUE ) - { - msg_Err( p_vout, "cannot create screen buffer" ); + CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, CONSOLE_TEXTMODE_BUFFER, NULL); + if (!hstdout || hstdout == INVALID_HANDLE_VALUE) { + msg_Err(vd, "cannot create screen buffer"); FreeConsole(); return VLC_EGENERIC; } - if( !SetConsoleActiveScreenBuffer( hstdout) ) - { - msg_Err( p_vout, "cannot set active screen buffer" ); + if (!SetConsoleActiveScreenBuffer(hstdout)) { + msg_Err(vd, "cannot set active screen buffer"); FreeConsole(); return VLC_EGENERIC; } - coord = GetLargestConsoleWindowSize( hstdout ); - msg_Dbg( p_vout, "SetConsoleWindowInfo: %ix%i", coord.X, coord.Y ); + coord = GetLargestConsoleWindowSize(hstdout); + msg_Dbg(vd, "SetConsoleWindowInfo: %ix%i", coord.X, coord.Y); /* Force size for now */ coord.X = 100; coord.Y = 40; - if( !SetConsoleScreenBufferSize( hstdout, coord ) ) - msg_Warn( p_vout, "SetConsoleScreenBufferSize %i %i", - coord.X, coord.Y ); + if (!SetConsoleScreenBufferSize(hstdout, coord)) + msg_Warn(vd, "SetConsoleScreenBufferSize %i %i", + coord.X, coord.Y); /* Get the current screen buffer size and window position. */ - if( GetConsoleScreenBufferInfo( hstdout, &csbiInfo ) ) - { + if (GetConsoleScreenBufferInfo(hstdout, &csbiInfo)) { rect.Top = 0; rect.Left = 0; rect.Right = csbiInfo.dwMaximumWindowSize.X - 1; rect.Bottom = csbiInfo.dwMaximumWindowSize.Y - 1; - if( !SetConsoleWindowInfo( hstdout, TRUE, &rect ) ) - msg_Dbg( p_vout, "SetConsoleWindowInfo failed: %ix%i", - rect.Right, rect.Bottom ); + if (!SetConsoleWindowInfo(hstdout, TRUE, &rect)) + msg_Dbg(vd, "SetConsoleWindowInfo failed: %ix%i", + rect.Right, rect.Bottom); } #endif /* Allocate structure */ - p_vout->p_sys = malloc( sizeof( vout_sys_t ) ); - if( p_vout->p_sys == NULL ) - { -#if defined( WIN32 ) && !defined( UNDER_CE ) - FreeConsole(); -#endif - return VLC_ENOMEM; + vd->sys = sys = calloc(1, sizeof(*sys)); + if (!sys) + goto error; + + sys->cv = cucul_create_canvas(0, 0); + if (!sys->cv) { + msg_Err(vd, "cannot initialize libcucul"); + goto error; } - p_vout->p_sys->p_cv = cucul_create_canvas(0, 0); - if( !p_vout->p_sys->p_cv ) - { - msg_Err( p_vout, "cannot initialize libcucul" ); -#if defined( WIN32 ) && !defined( UNDER_CE ) - FreeConsole(); + const char *driver = NULL; +#ifdef __APPLE__ + // Make sure we don't try to open a window. + driver = "ncurses"; #endif - free( p_vout->p_sys ); - return VLC_EGENERIC; - } - p_vout->p_sys->p_dp = caca_create_display( p_vout->p_sys->p_cv ); - if( !p_vout->p_sys->p_dp ) - { - msg_Err( p_vout, "cannot initialize libcaca" ); - cucul_free_canvas( p_vout->p_sys->p_cv ); -#if defined( WIN32 ) && !defined( UNDER_CE ) - FreeConsole(); -#endif - free( p_vout->p_sys ); - return VLC_EGENERIC; + sys->dp = caca_create_display_with_driver(sys->cv, driver); + if (!sys->dp) { + msg_Err(vd, "cannot initialize libcaca"); + goto error; + } + vout_display_DeleteWindow(vd, NULL); + + if (vd->cfg->display.title) + caca_set_display_title(sys->dp, + vd->cfg->display.title); + else + caca_set_display_title(sys->dp, + VOUT_TITLE "(Colour AsCii Art)"); + + /* Fix format */ + video_format_t fmt = vd->fmt; + if (fmt.i_chroma != VLC_CODEC_RGB32) { + fmt.i_chroma = VLC_CODEC_RGB32; + fmt.i_rmask = 0x00ff0000; + fmt.i_gmask = 0x0000ff00; + fmt.i_bmask = 0x000000ff; } - caca_set_display_title( p_vout->p_sys->p_dp, - VOUT_TITLE " - Colour AsCii Art (caca)" ); + /* TODO */ + vout_display_info_t info = vd->info; + + /* Setup vout_display now that everything is fine */ + vd->fmt = fmt; + vd->info = info; - p_vout->pf_init = Init; - p_vout->pf_end = End; - p_vout->pf_manage = Manage; - p_vout->pf_render = Render; - p_vout->pf_display = Display; + vd->pool = Pool; + vd->prepare = Prepare; + vd->display = Display; + vd->control = Control; + vd->manage = Manage; + + /* Fix initial state */ + vout_display_SendEventFullscreen(vd, false); + Refresh(vd); return VLC_SUCCESS; + +error: + if (sys) { + if (sys->pool) + picture_pool_Delete(sys->pool); + if (sys->dither) + cucul_free_dither(sys->dither); + if (sys->dp) + caca_free_display(sys->dp); + if (sys->cv) + cucul_free_canvas(sys->cv); + + free(sys); + } +#if defined(WIN32) && !defined(UNDER_CE) + FreeConsole(); +#endif + return VLC_EGENERIC; } -/***************************************************************************** - * Init: initialize libcaca video output thread - *****************************************************************************/ -static int Init( vout_thread_t *p_vout ) +/** + * Close a libcaca video output + */ +static void Close(vlc_object_t *object) { - int i_index; - picture_t *p_pic = NULL; - - I_OUTPUTPICTURES = 0; - - p_vout->output.i_chroma = VLC_CODEC_RGB32; - p_vout->output.i_width = p_vout->render.i_width; - p_vout->output.i_height = p_vout->render.i_height; - p_vout->output.i_aspect = p_vout->render.i_aspect; - - p_vout->output.i_rmask = 0x00ff0000; - p_vout->output.i_gmask = 0x0000ff00; - p_vout->output.i_bmask = 0x000000ff; - - /* Create the libcaca dither object */ - p_vout->p_sys->p_dither = cucul_create_dither - ( 32, p_vout->output.i_width, p_vout->output.i_height, - 4 * ((p_vout->output.i_width + 15) & ~15), - p_vout->output.i_rmask, p_vout->output.i_gmask, - p_vout->output.i_bmask, 0x00000000 ); - - if( !p_vout->p_sys->p_dither ) - { - msg_Err( p_vout, "could not create libcaca dither object" ); - return VLC_EGENERIC; - } + vout_display_t *vd = (vout_display_t *)object; + vout_display_sys_t *sys = vd->sys; - /* Find an empty picture slot */ - for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ ) - { - if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE ) - { - p_pic = p_vout->p_picture + i_index; - break; - } - } + if (sys->pool) + picture_pool_Delete(sys->pool); + if (sys->dither) + cucul_free_dither(sys->dither); + caca_free_display(sys->dp); + cucul_free_canvas(sys->cv); - if( p_pic == NULL ) - { - return VLC_EGENERIC; +#if defined(WIN32) && !defined(UNDER_CE) + FreeConsole(); +#endif + + free(sys); +} + +/** + * Return a pool of direct buffers + */ +static picture_pool_t *Pool(vout_display_t *vd, unsigned count) +{ + vout_display_sys_t *sys = vd->sys; + + if (!sys->pool) + sys->pool = picture_pool_NewFromFormat(&vd->fmt, count); + return sys->pool; +} + +/** + * Prepare a picture for display */ +static void Prepare(vout_display_t *vd, picture_t *picture) +{ + vout_display_sys_t *sys = vd->sys; + + if (!sys->dither) { + /* Create the libcaca dither object */ + sys->dither = cucul_create_dither(32, + vd->source.i_visible_width, + vd->source.i_visible_height, + picture->p[0].i_pitch, + vd->fmt.i_rmask, + vd->fmt.i_gmask, + vd->fmt.i_bmask, + 0x00000000); + + if (!sys->dither) { + msg_Err(vd, "could not create libcaca dither object"); + return; + } } - /* Allocate the picture */ - p_pic->p->i_lines = p_vout->output.i_height; - p_pic->p->i_visible_lines = p_vout->output.i_height; - p_pic->p->i_pitch = 4 * ((p_vout->output.i_width + 15) & ~15); - p_pic->p->i_pixel_pitch = 4; - p_pic->p->i_visible_pitch = 4 * p_vout->output.i_width; - p_pic->i_planes = 1; - p_pic->p->p_pixels = malloc( p_pic->p->i_pitch * p_pic->p->i_lines ); + vout_display_place_t place; + Place(vd, &place); - p_pic->i_status = DESTROYED_PICTURE; - p_pic->i_type = DIRECT_PICTURE; + cucul_set_color_ansi(sys->cv, CUCUL_COLOR_DEFAULT, CUCUL_COLOR_BLACK); + cucul_clear_canvas(sys->cv); - PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic; - I_OUTPUTPICTURES++; + const int crop_offset = vd->source.i_y_offset * picture->p->i_pitch + + vd->source.i_x_offset * picture->p->i_pixel_pitch; + cucul_dither_bitmap(sys->cv, place.x, place.y, + place.width, place.height, + sys->dither, + &picture->p->p_pixels[crop_offset]); +} - return VLC_SUCCESS; +/** + * Display a picture + */ +static void Display(vout_display_t *vd, picture_t *picture) +{ + Refresh(vd); + picture_Release(picture); } -/***************************************************************************** - * End: terminate libcaca video output thread - *****************************************************************************/ -static void End( vout_thread_t *p_vout ) +/** + * Control for vout display + */ +static int Control(vout_display_t *vd, int query, va_list args) { - cucul_free_dither( p_vout->p_sys->p_dither ); + vout_display_sys_t *sys = vd->sys; + + switch (query) { + case VOUT_DISPLAY_HIDE_MOUSE: + caca_set_mouse(sys->dp, 0); + return VLC_SUCCESS; + + case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE: { + const vout_display_cfg_t *cfg = va_arg(args, const vout_display_cfg_t *); + + caca_refresh_display(sys->dp); + + /* Not quite good but not sure how to resize it */ + if (cfg->display.width != caca_get_display_width(sys->dp) || + cfg->display.height != caca_get_display_height(sys->dp)) + return VLC_EGENERIC; + return VLC_SUCCESS; + } + + case VOUT_DISPLAY_CHANGE_ZOOM: + case VOUT_DISPLAY_CHANGE_DISPLAY_FILLED: + case VOUT_DISPLAY_CHANGE_SOURCE_ASPECT: + return VLC_SUCCESS; + + case VOUT_DISPLAY_CHANGE_SOURCE_CROP: + if (sys->dither) + cucul_free_dither(sys->dither); + sys->dither = NULL; + return VLC_SUCCESS; + + default: + msg_Err(vd, "Unsupported query in vout display caca"); + return VLC_EGENERIC; + } } -/***************************************************************************** - * Destroy: destroy libcaca video output thread - ***************************************************************************** - * Terminate an output method created by AaCreateOutputMethod - *****************************************************************************/ -static void Destroy( vlc_object_t *p_this ) +/** + * Refresh the display and send resize event + */ +static void Refresh(vout_display_t *vd) { - vout_thread_t *p_vout = (vout_thread_t *)p_this; + vout_display_sys_t *sys = vd->sys; - caca_free_display( p_vout->p_sys->p_dp ); - cucul_free_canvas( p_vout->p_sys->p_cv ); + /* */ + caca_refresh_display(sys->dp); -#if defined( WIN32 ) && !defined( UNDER_CE ) - FreeConsole(); -#endif + /* */ + const unsigned width = caca_get_display_width(sys->dp); + const unsigned height = caca_get_display_height(sys->dp); - free( p_vout->p_sys ); + if (width != vd->cfg->display.width || + height != vd->cfg->display.height) + vout_display_SendEventDisplaySize(vd, width, height, false); } -/***************************************************************************** - * Manage: handle libcaca events - ***************************************************************************** - * This function should be called regularly by video output thread. It manages - * console events. It returns a non null value on error. - *****************************************************************************/ -static int Manage( vout_thread_t *p_vout ) +/** + * Compute the place in canvas unit. + */ +static void Place(vout_display_t *vd, vout_display_place_t *place) { -#ifdef CACA_API_VERSION_1 - struct caca_event ev; -#else - int ev; -#endif + vout_display_sys_t *sys = vd->sys; + + vout_display_PlacePicture(place, &vd->source, vd->cfg, false); + + const int canvas_width = cucul_get_canvas_width(sys->cv); + const int canvas_height = cucul_get_canvas_height(sys->cv); + const int display_width = caca_get_display_width(sys->dp); + const int display_height = caca_get_display_height(sys->dp); + + if (display_width > 0 && display_height > 0) { + place->x = place->x * canvas_width / display_width; + place->y = place->y * canvas_height / display_height; + place->width = (place->width * canvas_width + display_width/2) / display_width; + place->height = (place->height * canvas_height + display_height/2) / display_height; + } else { + place->x = 0; + place->y = 0; + place->width = canvas_width; + place->height = display_height; + } +} - while( caca_get_event(p_vout->p_sys->p_dp, CACA_EVENT_ANY, &ev, 0) ) - { - playlist_t *p_playlist; - vlc_value_t val; - -#ifdef CACA_API_VERSION_1 -#ifdef CACA_EVENT_OPAQUE - switch( caca_get_event_type( &ev ) ) -#else - switch( ev.type ) -#endif /* CACA_EVENT_OPAQUE */ -#else - switch( ev ) -#endif - { - case CACA_EVENT_KEY_RELEASE: -#ifdef CACA_API_VERSION_1 -#ifdef CACA_EVENT_OPAQUE - switch( caca_get_event_key_ch( &ev ) ) -#else - switch( ev.data.key.ch ) -#endif /* CACA_EVENT_OPAQUE */ -#else - switch( ev & 0x00ffffff ) -#endif - { - case 'q': - val.i_int = KEY_MODIFIER_CTRL | 'q'; - break; - case ' ': - val.i_int = KEY_SPACE; - break; - default: - continue; - } +/* */ +static const struct { + int caca; + int vlc; +} keys[] = { + + { CACA_KEY_CTRL_A, KEY_MODIFIER_CTRL | 'a' }, + { CACA_KEY_CTRL_B, KEY_MODIFIER_CTRL | 'b' }, + { CACA_KEY_CTRL_C, KEY_MODIFIER_CTRL | 'c' }, + { CACA_KEY_CTRL_D, KEY_MODIFIER_CTRL | 'd' }, + { CACA_KEY_CTRL_E, KEY_MODIFIER_CTRL | 'e' }, + { CACA_KEY_CTRL_F, KEY_MODIFIER_CTRL | 'f' }, + { CACA_KEY_CTRL_G, KEY_MODIFIER_CTRL | 'g' }, + { CACA_KEY_BACKSPACE, KEY_BACKSPACE }, + { CACA_KEY_TAB, KEY_TAB }, + { CACA_KEY_CTRL_J, KEY_MODIFIER_CTRL | 'j' }, + { CACA_KEY_CTRL_K, KEY_MODIFIER_CTRL | 'k' }, + { CACA_KEY_CTRL_L, KEY_MODIFIER_CTRL | 'l' }, + { CACA_KEY_RETURN, KEY_ENTER }, + + { CACA_KEY_CTRL_N, KEY_MODIFIER_CTRL | 'n' }, + { CACA_KEY_CTRL_O, KEY_MODIFIER_CTRL | 'o' }, + { CACA_KEY_CTRL_P, KEY_MODIFIER_CTRL | 'p' }, + { CACA_KEY_CTRL_Q, KEY_MODIFIER_CTRL | 'q' }, + { CACA_KEY_CTRL_R, KEY_MODIFIER_CTRL | 'r' }, + + { CACA_KEY_PAUSE, -1 }, + { CACA_KEY_CTRL_T, KEY_MODIFIER_CTRL | 't' }, + { CACA_KEY_CTRL_U, KEY_MODIFIER_CTRL | 'u' }, + { CACA_KEY_CTRL_V, KEY_MODIFIER_CTRL | 'v' }, + { CACA_KEY_CTRL_W, KEY_MODIFIER_CTRL | 'w' }, + { CACA_KEY_CTRL_X, KEY_MODIFIER_CTRL | 'x' }, + { CACA_KEY_CTRL_Y, KEY_MODIFIER_CTRL | 'y' }, + { CACA_KEY_CTRL_Z, KEY_MODIFIER_CTRL | 'z' }, + + { CACA_KEY_ESCAPE, KEY_ESC }, + { CACA_KEY_DELETE, KEY_DELETE }, + + { CACA_KEY_F1, KEY_F1 }, + { CACA_KEY_F2, KEY_F2 }, + { CACA_KEY_F3, KEY_F3 }, + { CACA_KEY_F4, KEY_F4 }, + { CACA_KEY_F5, KEY_F5 }, + { CACA_KEY_F6, KEY_F6 }, + { CACA_KEY_F7, KEY_F7 }, + { CACA_KEY_F8, KEY_F8 }, + { CACA_KEY_F9, KEY_F9 }, + { CACA_KEY_F10, KEY_F10 }, + { CACA_KEY_F11, KEY_F11 }, + { CACA_KEY_F12, KEY_F12 }, + { CACA_KEY_F13, -1 }, + { CACA_KEY_F14, -1 }, + { CACA_KEY_F15, -1 }, + + { CACA_KEY_UP, KEY_UP }, + { CACA_KEY_DOWN, KEY_DOWN }, + { CACA_KEY_LEFT, KEY_LEFT }, + { CACA_KEY_RIGHT, KEY_RIGHT }, + + { CACA_KEY_INSERT, KEY_INSERT }, + { CACA_KEY_HOME, KEY_HOME }, + { CACA_KEY_END, KEY_END }, + { CACA_KEY_PAGEUP, KEY_PAGEUP }, + { CACA_KEY_PAGEDOWN,KEY_PAGEDOWN }, + + /* */ + { -1, -1 } +}; - var_Set( p_vout->p_libvlc, "key-pressed", val ); +static const struct { + int caca; + int vlc; +} mouses[] = { + { 1, MOUSE_BUTTON_LEFT }, + { 2, MOUSE_BUTTON_CENTER }, + { 3, MOUSE_BUTTON_RIGHT }, + { 4, MOUSE_BUTTON_WHEEL_UP }, + { 5, MOUSE_BUTTON_WHEEL_DOWN }, + + /* */ + { -1, -1 } +}; + +/** + * Proccess pending event + */ +static void Manage(vout_display_t *vd) +{ + vout_display_sys_t *sys = vd->sys; + + struct caca_event ev; + while (caca_get_event(sys->dp, CACA_EVENT_ANY, &ev, 0) > 0) { + switch (caca_get_event_type(&ev)) { + case CACA_EVENT_KEY_PRESS: { + const int caca = caca_get_event_key_ch(&ev); + + for (int i = 0; keys[i].caca != -1; i++) { + if (keys[i].caca == caca) { + const int vlc = keys[i].vlc; + + if (vlc >= 0) + vout_display_SendEventKey(vd, vlc); + return; + } + } + if (caca >= 0x20 && caca <= 0x7f) { + vout_display_SendEventKey(vd, caca); + return; + } break; + } case CACA_EVENT_RESIZE: - /* Acknowledge the resize */ - caca_refresh_display( p_vout->p_sys->p_dp ); - break; -#ifdef CACA_API_VERSION_1 - case CACA_EVENT_MOUSE_MOTION: - val.i_int = -#ifdef CACA_EVENT_OPAQUE - caca_get_event_mouse_x( &ev ) -#else - ev.data.mouse.x -#endif /* CACA_EVENT_OPAQUE */ - * p_vout->render.i_width - / cucul_get_canvas_width( p_vout->p_sys->p_cv ); - var_Set( p_vout, "mouse-x", val ); - val.i_int = -#ifdef CACA_EVENT_OPAQUE - caca_get_event_mouse_y( &ev ) -#else - ev.data.mouse.y -#endif /* CACA_EVENT_OPAQUE */ - * p_vout->render.i_height - / cucul_get_canvas_height( p_vout->p_sys->p_cv ); - var_Set( p_vout, "mouse-y", val ); - var_SetBool( p_vout, "mouse-moved", true ); + vout_display_SendEventDisplaySize(vd, caca_get_event_resize_width(&ev), + caca_get_event_resize_height(&ev), false); break; - case CACA_EVENT_MOUSE_RELEASE: - var_SetBool( p_vout, "mouse-clicked", true ); + case CACA_EVENT_MOUSE_MOTION: { + vout_display_place_t place; + Place(vd, &place); + + const unsigned x = vd->source.i_x_offset + + (int64_t)(caca_get_event_mouse_x(&ev) - place.x) * + vd->source.i_visible_width / place.width; + const unsigned y = vd->source.i_y_offset + + (int64_t)(caca_get_event_mouse_y(&ev) - place.y) * + vd->source.i_visible_height / place.height; + + caca_set_mouse(sys->dp, 1); + vout_display_SendEventMouseMoved(vd, x, y); break; - case CACA_EVENT_QUIT: - { - p_playlist = pl_Hold( p_vout ); - if( p_playlist ) - { - playlist_Stop( p_playlist ); - pl_Release( p_vout ); + } + case CACA_EVENT_MOUSE_PRESS: + case CACA_EVENT_MOUSE_RELEASE: { + caca_set_mouse(sys->dp, 1); + const int caca = caca_get_event_mouse_button(&ev); + for (int i = 0; mouses[i].caca != -1; i++) { + if (mouses[i].caca == caca) { + if (caca_get_event_type(&ev) == CACA_EVENT_MOUSE_PRESS) + vout_display_SendEventMousePressed(vd, mouses[i].vlc); + else + vout_display_SendEventMouseReleased(vd, mouses[i].vlc); + return; + } } - libvlc_Quit( p_vout->p_libvlc ); break; } -#endif + case CACA_EVENT_QUIT: + vout_display_SendEventClose(vd); + break; default: break; } } - - return VLC_SUCCESS; -} - -/***************************************************************************** - * Render: render previously calculated output - *****************************************************************************/ -static void Render( vout_thread_t *p_vout, picture_t *p_pic ) -{ - cucul_set_color_ansi( p_vout->p_sys->p_cv, - CUCUL_COLOR_DEFAULT, CUCUL_COLOR_BLACK ); - cucul_clear_canvas( p_vout->p_sys->p_cv ); - cucul_dither_bitmap( p_vout->p_sys->p_cv, 0, 0, - cucul_get_canvas_width( p_vout->p_sys->p_cv ) - 1, - cucul_get_canvas_height( p_vout->p_sys->p_cv ) - 1, - p_vout->p_sys->p_dither, p_pic->p->p_pixels ); -} - -/***************************************************************************** - * Display: displays previously rendered output - *****************************************************************************/ -static void Display( vout_thread_t *p_vout, picture_t *p_pic ) -{ - VLC_UNUSED(p_pic); - caca_refresh_display( p_vout->p_sys->p_dp ); }