]> git.sesse.net Git - vlc/blob - plugins/fb/vout_fb.c
* Ported the framebuffer plugin to the new module API. As for most of the
[vlc] / plugins / fb / vout_fb.c
1 /*****************************************************************************
2  * vout_fb.c: framebuffer video output display method
3  *****************************************************************************
4  * Copyright (C) 1998, 1999, 2000, 2001 VideoLAN
5  *
6  * Authors: Samuel Hocevar <sam@zoy.org>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  * 
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
21  *****************************************************************************/
22
23 /*****************************************************************************
24  * Preamble
25  *****************************************************************************/
26 #include "defs.h"
27
28 #include <errno.h>                                                 /* ENOMEM */
29 #include <signal.h>                                      /* SIGUSR1, SIGUSR2 */
30 #include <stdlib.h>                                                /* free() */
31 #include <string.h>                                            /* strerror() */
32 #include <fcntl.h>                                                 /* open() */
33 #include <unistd.h>                                               /* close() */
34
35 #include <termios.h>                                       /* struct termios */
36 #include <sys/ioctl.h>
37 #include <sys/mman.h>                                              /* mmap() */
38
39 #include <linux/fb.h>
40 #include <linux/vt.h>                                                /* VT_* */
41 #include <linux/kd.h>                                                 /* KD* */
42
43 #include "config.h"
44 #include "common.h"
45 #include "threads.h"
46 #include "mtime.h"
47 #include "tests.h"
48 #include "modules.h"
49
50 #include "video.h"
51 #include "video_output.h"
52
53 #include "intf_msg.h"
54 #include "main.h"
55
56 /*****************************************************************************
57  * vout_sys_t: video output framebuffer method descriptor
58  *****************************************************************************
59  * This structure is part of the video output thread descriptor.
60  * It describes the FB specific properties of an output thread.
61  *****************************************************************************/
62 typedef struct vout_sys_s
63 {
64     /* System informations */
65     int                 i_tty_dev;                      /* tty device handle */
66     struct termios      old_termios;
67
68     /* Original configuration informations */
69     struct sigaction            sig_usr1;           /* USR1 previous handler */
70     struct sigaction            sig_usr2;           /* USR2 previous handler */
71     struct vt_mode              vt_mode;                 /* previous VT mode */
72
73     /* Framebuffer information */
74     int                         i_fb_dev;                   /* device handle */
75     struct fb_var_screeninfo    old_info;      /* original mode informations */
76     struct fb_var_screeninfo    var_info;       /* current mode informations */
77     boolean_t                   b_pan;     /* does device supports panning ? */
78     struct fb_cmap              fb_cmap;                /* original colormap */
79     u16                         *fb_palette;             /* original palette */
80
81     /* Video memory */
82     byte_t *                    p_video;                      /* base adress */
83     size_t                      i_page_size;                    /* page size */
84
85 } vout_sys_t;
86
87 /*****************************************************************************
88  * Local prototypes.
89  *****************************************************************************/
90 static int  vout_Probe     ( probedata_t *p_data );
91 static int  vout_Create    ( struct vout_thread_s * );
92 static int  vout_Init      ( struct vout_thread_s * );
93 static void vout_End       ( struct vout_thread_s * );
94 static void vout_Destroy   ( struct vout_thread_s * );
95 static int  vout_Manage    ( struct vout_thread_s * );
96 static void vout_Display   ( struct vout_thread_s * );
97 static void vout_SetPalette( p_vout_thread_t p_vout, u16 *red, u16 *green,
98                              u16 *blue, u16 *transp );
99
100 static int  FBOpenDisplay  ( struct vout_thread_s * );
101 static void FBCloseDisplay ( struct vout_thread_s * );
102 static void FBSwitchDisplay( int i_signal );
103 static void FBTextMode     ( int i_tty_dev );
104 static void FBGfxMode      ( int i_tty_dev );
105
106 /*****************************************************************************
107  * Functions exported as capabilities. They are declared as static so that
108  * we don't pollute the namespace too much.
109  *****************************************************************************/
110 void vout_getfunctions( function_list_t * p_function_list )
111 {
112     p_function_list->pf_probe = vout_Probe;
113     p_function_list->functions.vout.pf_create     = vout_Create;
114     p_function_list->functions.vout.pf_init       = vout_Init;
115     p_function_list->functions.vout.pf_end        = vout_End;
116     p_function_list->functions.vout.pf_destroy    = vout_Destroy;
117     p_function_list->functions.vout.pf_manage     = vout_Manage;
118     p_function_list->functions.vout.pf_display    = vout_Display;
119     p_function_list->functions.vout.pf_setpalette = vout_SetPalette;
120 }
121
122 /*****************************************************************************
123  * vout_Probe: probe the video driver and return a score
124  *****************************************************************************
125  * This function tries to open the framebuffer and returns a score to the
126  * plugin manager so that it can select the best plugin.
127  *****************************************************************************/
128 static int vout_Probe( probedata_t *p_data )
129 {
130     int i_fd;
131
132     if( TestMethod( VOUT_METHOD_VAR, "fb" ) )
133     {
134         return( 999 );
135     }
136
137     i_fd = open( main_GetPszVariable( VOUT_FB_DEV_VAR,
138                                       VOUT_FB_DEV_DEFAULT ), O_RDWR );
139     if( i_fd == -1 )
140     {
141         return( 0 );
142     }
143     close( i_fd );
144
145     return( 30 );
146 }
147
148 /*****************************************************************************
149  * vout_Create: allocates FB video thread output method
150  *****************************************************************************
151  * This function allocates and initializes a FB vout method.
152  *****************************************************************************/
153 static int vout_Create( vout_thread_t *p_vout )
154 {
155     struct sigaction    sig_tty;                 /* sigaction for tty change */
156     struct vt_mode      vt_mode;                          /* vt current mode */
157     struct termios      new_termios;
158
159     /* Allocate instance and initialize some members */
160     p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
161     if( p_vout->p_sys == NULL )
162     {
163         return( 1 );
164     };
165
166     /* Set tty and fb devices */
167     p_vout->p_sys->i_tty_dev = 0;       /* 0 == /dev/tty0 == current console */
168
169     FBGfxMode( p_vout->p_sys->i_tty_dev );
170
171     /* Set keyboard settings */
172     if (tcgetattr(0, &p_vout->p_sys->old_termios) == -1)
173     {
174         intf_ErrMsg( "intf error: tcgetattr" );
175     }
176
177     if (tcgetattr(0, &new_termios) == -1)
178     {
179         intf_ErrMsg( "intf error: tcgetattr" );
180     }
181
182  /* new_termios.c_lflag &= ~ (ICANON | ISIG);
183     new_termios.c_lflag |= (ECHO | ECHOCTL); */
184     new_termios.c_lflag &= ~ (ICANON);
185     new_termios.c_lflag &= ~(ECHO | ECHOCTL);
186     new_termios.c_iflag = 0;
187     new_termios.c_cc[VMIN] = 1;
188     new_termios.c_cc[VTIME] = 0;
189
190     if (tcsetattr(0, TCSAFLUSH, &new_termios) == -1)
191     {
192         intf_ErrMsg( "intf error: tcsetattr" );
193     }
194
195     ioctl(p_vout->p_sys->i_tty_dev, VT_RELDISP, VT_ACKACQ);
196
197     /* Set-up tty signal handler to be aware of tty changes */
198     memset( &sig_tty, 0, sizeof( sig_tty ) );
199     sig_tty.sa_handler = FBSwitchDisplay;
200     sigemptyset( &sig_tty.sa_mask );
201     if( sigaction( SIGUSR1, &sig_tty, &p_vout->p_sys->sig_usr1 ) ||
202         sigaction( SIGUSR2, &sig_tty, &p_vout->p_sys->sig_usr2 ) )
203     {
204         intf_ErrMsg( "intf error: can't set up signal handler (%s)",
205                      strerror(errno) );
206         tcsetattr(0, 0, &p_vout->p_sys->old_termios);
207         FBTextMode( p_vout->p_sys->i_tty_dev );
208         free( p_vout->p_sys );
209         return( 1 );
210     }
211
212     /* Set-up tty according to new signal handler */
213     if( ioctl(p_vout->p_sys->i_tty_dev, VT_GETMODE, &p_vout->p_sys->vt_mode)
214         == -1 )
215     {
216         intf_ErrMsg( "intf error: cant get terminal mode (%s)",
217                      strerror(errno) );
218         sigaction( SIGUSR1, &p_vout->p_sys->sig_usr1, NULL );
219         sigaction( SIGUSR2, &p_vout->p_sys->sig_usr2, NULL );
220         tcsetattr(0, 0, &p_vout->p_sys->old_termios);
221         FBTextMode( p_vout->p_sys->i_tty_dev );
222         free( p_vout->p_sys );
223         return( 1 );
224     }
225     memcpy( &vt_mode, &p_vout->p_sys->vt_mode, sizeof( vt_mode ) );
226     vt_mode.mode   = VT_PROCESS;
227     vt_mode.waitv  = 0;
228     vt_mode.relsig = SIGUSR1;
229     vt_mode.acqsig = SIGUSR2;
230
231     if( ioctl(p_vout->p_sys->i_tty_dev, VT_SETMODE, &vt_mode) == -1 )
232     {
233         intf_ErrMsg( "intf error: can't set terminal mode (%s)",
234                      strerror(errno) );
235         sigaction( SIGUSR1, &p_vout->p_sys->sig_usr1, NULL );
236         sigaction( SIGUSR2, &p_vout->p_sys->sig_usr2, NULL );
237         tcsetattr(0, 0, &p_vout->p_sys->old_termios);
238         FBTextMode( p_vout->p_sys->i_tty_dev );
239         free( p_vout->p_sys );
240         return( 1 );
241     }
242
243     if( FBOpenDisplay( p_vout ) )
244     {
245         ioctl(p_vout->p_sys->i_tty_dev, VT_SETMODE, &p_vout->p_sys->vt_mode);
246         sigaction( SIGUSR1, &p_vout->p_sys->sig_usr1, NULL );
247         sigaction( SIGUSR2, &p_vout->p_sys->sig_usr2, NULL );
248         tcsetattr(0, 0, &p_vout->p_sys->old_termios);
249         FBTextMode( p_vout->p_sys->i_tty_dev );
250         free( p_vout->p_sys );
251         return( 1 );
252     }
253
254     return( 0 );
255 }
256
257 /*****************************************************************************
258  * vout_Init: initialize framebuffer video thread output method
259  *****************************************************************************/
260 static int vout_Init( vout_thread_t *p_vout )
261 {
262     /* Clear the screen */
263     memset( p_vout->p_sys->p_video, 0, p_vout->p_sys->i_page_size * 2 );
264
265     return( 0 );
266 }
267
268 /*****************************************************************************
269  * vout_End: terminate framebuffer video thread output method
270  *****************************************************************************/
271 static void vout_End( vout_thread_t *p_vout )
272 {
273     /* Clear the screen */
274     memset( p_vout->p_sys->p_video, 0, p_vout->p_sys->i_page_size * 2 );
275 }
276
277 /*****************************************************************************
278  * vout_Destroy: destroy FB video thread output method
279  *****************************************************************************
280  * Terminate an output method created by vout_CreateOutputMethod
281  *****************************************************************************/
282 static void vout_Destroy( vout_thread_t *p_vout )
283 {
284     FBCloseDisplay( p_vout );
285
286     /* Reset the terminal */
287     ioctl(p_vout->p_sys->i_tty_dev, VT_SETMODE, &p_vout->p_sys->vt_mode);
288
289     /* Remove signal handlers */
290     sigaction( SIGUSR1, &p_vout->p_sys->sig_usr1, NULL );
291     sigaction( SIGUSR2, &p_vout->p_sys->sig_usr2, NULL );
292
293     /* Reset the keyboard state */
294     tcsetattr( 0, 0, &p_vout->p_sys->old_termios );
295
296     /* Return to text mode */
297     FBTextMode( p_vout->p_sys->i_tty_dev );
298
299     /* Destroy structure */
300     free( p_vout->p_sys );
301 }
302
303 /*****************************************************************************
304  * vout_Manage: handle FB events
305  *****************************************************************************
306  * This function should be called regularly by video output thread. It manages
307  * console events. It returns a non null value on error.
308  *****************************************************************************/
309 static int vout_Manage( vout_thread_t *p_vout )
310 {
311 #if 0
312     u8 buf;
313
314     if ( read(0, &buf, 1) == 1)
315     {
316         switch( buf )
317         {
318         case 'q':
319             p_main->p_intf->b_die = 1;
320             break;
321
322         default:
323             break;
324         }
325     }
326 #endif
327
328     /*
329      * Size change
330      */
331     if( p_vout->i_changes & VOUT_SIZE_CHANGE )
332     {
333         intf_WarnMsg( 1, "vout: reinitializing framebuffer screen" );
334         p_vout->i_changes &= ~VOUT_SIZE_CHANGE;
335
336         /* Destroy XImages to change their size */
337         vout_End( p_vout );
338
339         /* Recreate XImages. If SysInit failed, the thread can't go on. */
340         if( vout_Init( p_vout ) )
341         {
342             intf_ErrMsg("error: cannot reinit framebuffer screen" );
343             return( 1 );
344         }
345
346         /* Clear screen */
347         memset( p_vout->p_sys->p_video, 0, p_vout->p_sys->i_page_size * 2 );
348
349 #if 1
350         /* Tell the video output thread that it will need to rebuild YUV
351          * tables. This is needed since conversion buffer size may have changed */
352         p_vout->i_changes |= VOUT_YUV_CHANGE;
353 #endif
354     }
355
356     return 0;
357 }
358
359 /*****************************************************************************
360  * vout_Display: displays previously rendered output
361  *****************************************************************************
362  * This function send the currently rendered image to FB image, waits until
363  * it is displayed and switch the two rendering buffers, preparing next frame.
364  *****************************************************************************/
365 static void vout_Display( vout_thread_t *p_vout )
366 {
367     /* swap the two Y offsets if the drivers supports panning */
368     if( p_vout->p_sys->b_pan )
369     {
370         p_vout->p_sys->var_info.yoffset =
371             p_vout->i_buffer_index ? p_vout->p_sys->var_info.yres : 0;
372    
373         /* the X offset should be 0, but who knows ...
374          * some other app might have played with the framebuffer */
375         p_vout->p_sys->var_info.xoffset = 0;
376
377         ioctl( p_vout->p_sys->i_fb_dev,
378                FBIOPAN_DISPLAY, &p_vout->p_sys->var_info );
379     }
380 }
381
382 /*****************************************************************************
383  * vout_SetPalette: sets an 8 bpp palette
384  *****************************************************************************
385  * This function sets the palette given as an argument. It does not return
386  * anything, but could later send information on which colors it was unable
387  * to set.
388  *****************************************************************************/
389 static void vout_SetPalette( p_vout_thread_t p_vout,
390                              u16 *red, u16 *green, u16 *blue, u16 *transp )
391 {
392     struct fb_cmap cmap = { 0, 256, red, green, blue, transp };
393
394     ioctl( p_vout->p_sys->i_fb_dev, FBIOPUTCMAP, &cmap );
395 }
396
397 /* following functions are local */
398
399 /*****************************************************************************
400  * FBOpenDisplay: initialize framebuffer
401  *****************************************************************************/
402 static int FBOpenDisplay( vout_thread_t *p_vout )
403 {
404     char *psz_device;                             /* framebuffer device path */
405     struct fb_fix_screeninfo    fix_info;     /* framebuffer fix information */
406
407     /* Open framebuffer device */
408     psz_device = main_GetPszVariable( VOUT_FB_DEV_VAR, VOUT_FB_DEV_DEFAULT );
409     p_vout->p_sys->i_fb_dev = open( psz_device, O_RDWR);
410     if( p_vout->p_sys->i_fb_dev == -1 )
411     {
412         intf_ErrMsg("vout error: can't open %s (%s)", psz_device, strerror(errno) );
413         return( 1 );
414     }
415
416     /* Get framebuffer device informations */
417     if( ioctl( p_vout->p_sys->i_fb_dev, FBIOGET_VSCREENINFO, &p_vout->p_sys->var_info ) )
418     {
419         intf_ErrMsg("vout error: can't get fb info (%s)", strerror(errno) );
420         close( p_vout->p_sys->i_fb_dev );
421         return( 1 );
422     }
423
424     if( ioctl( p_vout->p_sys->i_fb_dev, FBIOGET_VSCREENINFO, &p_vout->p_sys->old_info ) )
425     {
426         intf_ErrMsg("vout error: can't get 2nd fb info (%s)", strerror(errno) );
427         close( p_vout->p_sys->i_fb_dev );
428         return( 1 );
429     }
430
431     /* Set some attributes */
432     p_vout->p_sys->var_info.activate = FB_ACTIVATE_NXTOPEN;
433     p_vout->p_sys->var_info.xoffset =  0;
434     p_vout->p_sys->var_info.yoffset =  0;
435
436     if( ioctl( p_vout->p_sys->i_fb_dev, FBIOPUT_VSCREENINFO, &p_vout->p_sys->var_info ) )
437     {
438         intf_ErrMsg(" vout error: can't set fb info (%s)", strerror(errno) );
439         close( p_vout->p_sys->i_fb_dev );
440         return( 1 );
441     }
442
443     /* Get some informations again, in the definitive configuration */
444     if( ioctl( p_vout->p_sys->i_fb_dev, FBIOGET_FSCREENINFO, &fix_info ) ||
445         ioctl( p_vout->p_sys->i_fb_dev, FBIOGET_VSCREENINFO, &p_vout->p_sys->var_info ) )
446     {
447         intf_ErrMsg(" vout error: can't get additional fb info (%s)", strerror(errno) );
448
449         /* Restore fb config */
450         ioctl( p_vout->p_sys->i_fb_dev, FBIOPUT_VSCREENINFO, &p_vout->p_sys->var_info );
451
452         close( p_vout->p_sys->i_fb_dev );
453         return( 1 );
454     }
455
456     /* FIXME: if the image is full-size, it gets cropped on the left
457      * because of the xres / xres_virtual slight difference */
458     intf_WarnMsg( 1, "vout: %ix%i (virtual %ix%i)",
459                   p_vout->p_sys->var_info.xres,
460                   p_vout->p_sys->var_info.yres,
461                   p_vout->p_sys->var_info.xres_virtual,
462                   p_vout->p_sys->var_info.yres_virtual );
463
464     p_vout->i_height = p_vout->p_sys->var_info.yres;
465     p_vout->i_width  = p_vout->p_sys->var_info.xres_virtual ?
466                            p_vout->p_sys->var_info.xres_virtual
467                            : p_vout->p_sys->var_info.xres;
468
469     p_vout->i_screen_depth = p_vout->p_sys->var_info.bits_per_pixel;
470
471     p_vout->p_sys->fb_palette = NULL;
472     p_vout->p_sys->b_pan = ( fix_info.ypanstep || fix_info.ywrapstep );
473
474     switch( p_vout->i_screen_depth )
475     {
476     case 8:                                                         /* 8 bpp */
477         p_vout->p_sys->fb_palette = malloc( 8 * 256 * sizeof( u16 ) );
478         p_vout->p_sys->fb_cmap.start = 0;
479         p_vout->p_sys->fb_cmap.len = 256;
480         p_vout->p_sys->fb_cmap.red = p_vout->p_sys->fb_palette;
481         p_vout->p_sys->fb_cmap.green = p_vout->p_sys->fb_palette + 256 * sizeof( u16 );
482         p_vout->p_sys->fb_cmap.blue = p_vout->p_sys->fb_palette + 2 * 256 * sizeof( u16 );
483         p_vout->p_sys->fb_cmap.transp = p_vout->p_sys->fb_palette + 3 * 256 * sizeof( u16 );
484
485         /* Save the colormap */
486         ioctl( p_vout->p_sys->i_fb_dev, FBIOGETCMAP, &p_vout->p_sys->fb_cmap );
487
488         p_vout->i_bytes_per_pixel = 1;
489         p_vout->i_bytes_per_line = p_vout->i_width;
490         break;
491
492     case 15:                      /* 15 bpp (16bpp with a missing green bit) */
493     case 16:                                        /* 16 bpp (65536 colors) */
494         p_vout->i_bytes_per_pixel = 2;
495         p_vout->i_bytes_per_line = p_vout->i_width * 2;
496         break;
497
498     case 24:                                  /* 24 bpp (millions of colors) */
499         p_vout->i_bytes_per_pixel = 3;
500         p_vout->i_bytes_per_line = p_vout->i_width * 3;
501         break;
502
503     case 32:                                  /* 32 bpp (millions of colors) */
504         p_vout->i_bytes_per_pixel = 4;
505         p_vout->i_bytes_per_line = p_vout->i_width * 4;
506         break;
507
508     default:                                     /* unsupported screen depth */
509         intf_ErrMsg( "vout error: screen depth %d is not supported",
510                      p_vout->i_screen_depth);
511
512         /* Restore fb config */
513         ioctl( p_vout->p_sys->i_fb_dev, FBIOPUT_VSCREENINFO, &p_vout->p_sys->var_info );
514
515         close( p_vout->p_sys->i_fb_dev );
516         return( 1 );
517         break;
518     }
519
520     switch( p_vout->i_screen_depth )
521     {
522     case 15:
523     case 16:
524     case 24:
525     case 32:
526         p_vout->i_red_mask =    ( (1 << p_vout->p_sys->var_info.red.length) - 1 )
527                                     << p_vout->p_sys->var_info.red.offset;
528         p_vout->i_green_mask =    ( (1 << p_vout->p_sys->var_info.green.length) - 1 )
529                                     << p_vout->p_sys->var_info.green.offset;
530         p_vout->i_blue_mask =    ( (1 << p_vout->p_sys->var_info.blue.length) - 1 )
531                                     << p_vout->p_sys->var_info.blue.offset;
532     }
533
534     p_vout->p_sys->i_page_size = p_vout->i_width *
535                 p_vout->i_height * p_vout->i_bytes_per_pixel;
536
537     /* Map two framebuffers a the very beginning of the fb */
538     p_vout->p_sys->p_video = mmap( 0, p_vout->p_sys->i_page_size * 2,
539                                    PROT_READ | PROT_WRITE, MAP_SHARED,
540                                    p_vout->p_sys->i_fb_dev, 0 );
541
542     if( (int)p_vout->p_sys->p_video == -1 ) /* according to man, it is -1.
543                                                What about NULL ? */
544     {
545         intf_ErrMsg("vout error: can't map video memory (%s)", strerror(errno) );
546         /* FIXME: restore fb config ?? */
547         if( p_vout->i_screen_depth == 8 )
548         {
549             free( p_vout->p_sys->fb_palette );
550         }
551
552         /* Restore fb config */
553         ioctl( p_vout->p_sys->i_fb_dev, FBIOPUT_VSCREENINFO, &p_vout->p_sys->var_info );
554
555         close( p_vout->p_sys->i_fb_dev );
556         return( 1 );
557     }
558
559     /* Set and initialize buffers */
560     if( p_vout->p_sys->b_pan )
561     {
562         vout_SetBuffers( p_vout, p_vout->p_sys->p_video,
563                                  p_vout->p_sys->p_video
564                                   + p_vout->p_sys->i_page_size );
565     }
566     else
567     {
568         vout_SetBuffers( p_vout, p_vout->p_sys->p_video,
569                                  p_vout->p_sys->p_video );
570     }
571     
572     intf_WarnMsg( 1, "framebuffer type=%d, visual=%d, ypanstep=%d, ywrap=%d, accel=%d",
573                   fix_info.type, fix_info.visual, fix_info.ypanstep, fix_info.ywrapstep, fix_info.accel );
574     return( 0 );
575 }
576
577 /*****************************************************************************
578  * FBCloseDisplay: terminate FB video thread output method
579  *****************************************************************************/
580 static void FBCloseDisplay( vout_thread_t *p_vout )
581 {
582     /* Clear display */
583     memset( p_vout->p_sys->p_video, 0, p_vout->p_sys->i_page_size * 2 );
584
585     /* Restore palette */
586     if( p_vout->i_screen_depth == 8 );
587     {
588         ioctl( p_vout->p_sys->i_fb_dev, FBIOPUTCMAP, &p_vout->p_sys->fb_cmap );
589         free( p_vout->p_sys->fb_palette );
590     }
591
592     /* Restore fb config */
593     ioctl( p_vout->p_sys->i_fb_dev, FBIOPUT_VSCREENINFO, &p_vout->p_sys->var_info );
594
595     /* Close fb */
596     close( p_vout->p_sys->i_fb_dev );
597 }
598
599 /*****************************************************************************
600  * FBSwitchDisplay: VT change signal handler
601  *****************************************************************************
602  * This function activates or deactivates the output of the thread. It is
603  * called by the VT driver, on terminal change.
604  *****************************************************************************/
605 static void FBSwitchDisplay(int i_signal)
606 {
607     if( p_main->p_vout != NULL )
608     {
609         switch( i_signal )
610         {
611         case SIGUSR1:                                /* vt has been released */
612             p_main->p_vout->b_active = 0;
613             ioctl( ((vout_sys_t *)p_main->p_vout->p_sys)->i_tty_dev,
614                    VT_RELDISP, 1 );
615             break;
616         case SIGUSR2:                                /* vt has been acquired */
617             p_main->p_vout->b_active = 1;
618             ioctl( ((vout_sys_t *)p_main->p_vout->p_sys)->i_tty_dev,
619                    VT_RELDISP, VT_ACTIVATE );
620             /* handle blanking */
621             vlc_mutex_lock( &p_main->p_vout->change_lock );
622             p_main->p_vout->i_changes |= VOUT_SIZE_CHANGE;
623             vlc_mutex_unlock( &p_main->p_vout->change_lock );
624             break;
625         }
626     }
627 }
628
629 /*****************************************************************************
630  * FBTextMode and FBGfxMode : switch tty to text/graphic mode
631  *****************************************************************************
632  * These functions toggle the tty mode.
633  *****************************************************************************/
634 static void FBTextMode( int i_tty_dev )
635 {
636     /* return to text mode */
637     if (-1 == ioctl(i_tty_dev, KDSETMODE, KD_TEXT))
638     {
639         intf_ErrMsg( "intf error: failed ioctl KDSETMODE KD_TEXT" );
640     }
641 }
642
643 static void FBGfxMode( int i_tty_dev )
644 {
645     /* switch to graphic mode */
646     if (-1 == ioctl(i_tty_dev, KDSETMODE, KD_GRAPHICS))
647     {
648         intf_ErrMsg( "intf error: failed ioctl KDSETMODE KD_GRAPHICS" );
649     }
650 }
651