00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <errno.h>
00028 #include <stdlib.h>
00029 #include <string.h>
00030
00031 #include <caca.h>
00032
00033 #include <vlc/vlc.h>
00034 #include <vlc/vout.h>
00035 #include <vlc/intf.h>
00036 #include <vlc_keys.h>
00037
00038
00039
00040
00041 static int Create ( vlc_object_t * );
00042 static void Destroy ( vlc_object_t * );
00043
00044 static int Init ( vout_thread_t * );
00045 static void End ( vout_thread_t * );
00046 static int Manage ( vout_thread_t * );
00047 static void Render ( vout_thread_t *, picture_t * );
00048 static void Display ( vout_thread_t *, picture_t * );
00049
00050
00051
00052
00053 vlc_module_begin();
00054 set_shortname( "Caca" );
00055 set_category( CAT_VIDEO );
00056 set_subcategory( SUBCAT_VIDEO_VOUT );
00057 set_description( _("Color ASCII art video output") );
00058 set_capability( "video output", 12 );
00059 set_callbacks( Create, Destroy );
00060 vlc_module_end();
00061
00062
00063
00064
00065
00066
00067
00068 struct vout_sys_t
00069 {
00070 struct caca_bitmap *p_bitmap;
00071 };
00072
00073
00074
00075
00076
00077
00078 static int Create( vlc_object_t *p_this )
00079 {
00080 vout_thread_t *p_vout = (vout_thread_t *)p_this;
00081
00082 #if defined( WIN32 ) && !defined( UNDER_CE )
00083 if( AllocConsole() )
00084 {
00085 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
00086 SMALL_RECT rect;
00087 COORD coord;
00088
00089 HANDLE hstdout =
00090 CreateConsoleScreenBuffer( GENERIC_READ | GENERIC_WRITE,
00091 FILE_SHARE_READ | FILE_SHARE_WRITE,
00092 NULL, CONSOLE_TEXTMODE_BUFFER, NULL );
00093 if( !hstdout || hstdout == INVALID_HANDLE_VALUE )
00094 {
00095 msg_Err( p_vout, "cannot create screen buffer" );
00096 FreeConsole();
00097 return VLC_EGENERIC;
00098 }
00099
00100 if( !SetConsoleActiveScreenBuffer( hstdout) )
00101 {
00102 msg_Err( p_vout, "cannot set active screen buffer" );
00103 FreeConsole();
00104 return VLC_EGENERIC;
00105 }
00106
00107 coord = GetLargestConsoleWindowSize( hstdout );
00108 msg_Dbg( p_vout, "SetConsoleWindowInfo: %ix%i", coord.X, coord.Y );
00109
00110
00111 coord.X = 100;
00112 coord.Y = 40;
00113
00114 if( !SetConsoleScreenBufferSize( hstdout, coord ) )
00115 msg_Warn( p_vout, "SetConsoleScreenBufferSize %i %i",
00116 coord.X, coord.Y );
00117
00118
00119 if( GetConsoleScreenBufferInfo( hstdout, &csbiInfo ) )
00120 {
00121 rect.Top = 0; rect.Left = 0;
00122 rect.Right = csbiInfo.dwMaximumWindowSize.X - 1;
00123 rect.Bottom = csbiInfo.dwMaximumWindowSize.Y - 1;
00124 if( !SetConsoleWindowInfo( hstdout, TRUE, &rect ) )
00125 msg_Dbg( p_vout, "SetConsoleWindowInfo failed: %ix%i",
00126 rect.Right, rect.Bottom );
00127 }
00128 }
00129 else
00130 {
00131 msg_Err( p_vout, "cannot create console" );
00132 return VLC_EGENERIC;
00133 }
00134
00135 #endif
00136
00137
00138 p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
00139 if( p_vout->p_sys == NULL )
00140 {
00141 msg_Err( p_vout, "out of memory" );
00142 return VLC_ENOMEM;
00143 }
00144
00145 if( caca_init() )
00146 {
00147 msg_Err( p_vout, "cannot initialize libcaca" );
00148 free( p_vout->p_sys );
00149 return VLC_EGENERIC;
00150 }
00151
00152 caca_set_window_title( VOUT_TITLE " - Colour AsCii Art (caca)" );
00153
00154 p_vout->pf_init = Init;
00155 p_vout->pf_end = End;
00156 p_vout->pf_manage = Manage;
00157 p_vout->pf_render = Render;
00158 p_vout->pf_display = Display;
00159
00160 return VLC_SUCCESS;
00161 }
00162
00163
00164
00165
00166 static int Init( vout_thread_t *p_vout )
00167 {
00168 int i_index;
00169 picture_t *p_pic = NULL;
00170
00171 I_OUTPUTPICTURES = 0;
00172
00173 p_vout->output.i_chroma = VLC_FOURCC('R','V','3','2');
00174 p_vout->output.i_width = p_vout->render.i_width;
00175 p_vout->output.i_height = p_vout->render.i_height;
00176 p_vout->output.i_aspect = p_vout->render.i_aspect;
00177
00178 p_vout->output.i_rmask = 0x00ff0000;
00179 p_vout->output.i_gmask = 0x0000ff00;
00180 p_vout->output.i_bmask = 0x000000ff;
00181
00182
00183 p_vout->p_sys->p_bitmap =
00184 caca_create_bitmap( 32,
00185 p_vout->output.i_width,
00186 p_vout->output.i_height,
00187 4 * ((p_vout->output.i_width + 15) & ~15),
00188 p_vout->output.i_rmask,
00189 p_vout->output.i_gmask,
00190 p_vout->output.i_bmask,
00191 0x00000000 );
00192 if( !p_vout->p_sys->p_bitmap )
00193 {
00194 msg_Err( p_vout, "could not create libcaca bitmap" );
00195 return VLC_EGENERIC;
00196 }
00197
00198
00199 for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
00200 {
00201 if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
00202 {
00203 p_pic = p_vout->p_picture + i_index;
00204 break;
00205 }
00206 }
00207
00208 if( p_pic == NULL )
00209 {
00210 return VLC_EGENERIC;
00211 }
00212
00213
00214 p_pic->p->i_lines = p_vout->output.i_height;
00215 p_pic->p->i_visible_lines = p_vout->output.i_height;
00216 p_pic->p->i_pitch = 4 * ((p_vout->output.i_width + 15) & ~15);
00217 p_pic->p->i_pixel_pitch = 4;
00218 p_pic->p->i_visible_pitch = 4 * p_vout->output.i_width;
00219 p_pic->i_planes = 1;
00220 p_pic->p->p_pixels = malloc( p_pic->p->i_pitch * p_pic->p->i_lines );
00221
00222 p_pic->i_status = DESTROYED_PICTURE;
00223 p_pic->i_type = DIRECT_PICTURE;
00224
00225 PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
00226 I_OUTPUTPICTURES++;
00227
00228 return VLC_SUCCESS;
00229 }
00230
00231
00232
00233
00234 static void End( vout_thread_t *p_vout )
00235 {
00236 caca_free_bitmap( p_vout->p_sys->p_bitmap );
00237 }
00238
00239
00240
00241
00242
00243
00244 static void Destroy( vlc_object_t *p_this )
00245 {
00246 vout_thread_t *p_vout = (vout_thread_t *)p_this;
00247
00248 caca_end();
00249
00250 #if defined( WIN32 ) && !defined( UNDER_CE )
00251 FreeConsole();
00252 #endif
00253
00254 free( p_vout->p_sys );
00255 }
00256
00257
00258
00259
00260
00261
00262
00263 static int Manage( vout_thread_t *p_vout )
00264 {
00265 int event;
00266 vlc_value_t val;
00267
00268 while(( event = caca_get_event(CACA_EVENT_KEY_PRESS | CACA_EVENT_RESIZE) ))
00269 {
00270 if( event == CACA_EVENT_RESIZE )
00271 {
00272
00273 caca_refresh();
00274 continue;
00275 }
00276
00277 switch( event & 0x00ffffff )
00278 {
00279 case 'q':
00280 val.i_int = KEY_MODIFIER_CTRL | 'q';
00281 break;
00282 case ' ':
00283 val.i_int = KEY_SPACE;
00284 break;
00285 default:
00286 continue;
00287 }
00288
00289 var_Set( p_vout->p_vlc, "key-pressed", val );
00290 }
00291
00292 return VLC_SUCCESS;
00293 }
00294
00295
00296
00297
00298 static void Render( vout_thread_t *p_vout, picture_t *p_pic )
00299 {
00300 caca_clear();
00301 caca_draw_bitmap( 0, 0, caca_get_width() - 1, caca_get_height() - 1,
00302 p_vout->p_sys->p_bitmap, p_pic->p->p_pixels );
00303 }
00304
00305
00306
00307
00308 static void Display( vout_thread_t *p_vout, picture_t *p_pic )
00309 {
00310 caca_refresh();
00311 }
00312