1 /*****************************************************************************
2 * intf_fb.c: Linux framebuffer interface plugin
3 *****************************************************************************
4 * Copyright (C) 2000 VideoLAN
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.
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.
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 *****************************************************************************/
23 /*****************************************************************************
25 *****************************************************************************/
28 #include <errno.h> /* errno */
29 #include <signal.h> /* SIGUSR1, SIGUSR2 */
30 #include <stdlib.h> /* free() */
31 #include <string.h> /* strerror() */
32 #include <unistd.h> /* read() */
33 #include <sys/ioctl.h> /* ioctl() */
34 #include <sys/types.h> /* on BSD, uio.h needs types.h */
35 #include <sys/uio.h> /* for input.h */
37 #include <termios.h> /* struct termios */
38 #include <linux/vt.h> /* VT_* */
39 #include <linux/kd.h> /* KD* */
49 #include "video_output.h"
52 #include "interface.h"
56 /*****************************************************************************
57 * intf_sys_t: description and status of FB interface
58 *****************************************************************************/
59 typedef struct intf_sys_s
61 /* System informations */
62 int i_tty_dev; /* tty device handle */
64 /* Original configuration informations */
65 struct sigaction sig_usr1; /* USR1 previous handler */
66 struct sigaction sig_usr2; /* USR2 previous handler */
67 struct vt_mode vt_mode; /* previous VT mode */
69 int i_width; /* width of main window */
70 int i_height; /* height of main window */
72 struct termios old_termios;
73 struct termios new_termios;
77 /*****************************************************************************
79 *****************************************************************************/
80 static void FBSwitchDisplay ( int i_signal );
81 static void FBTextMode ( int i_tty_dev );
82 static void FBGfxMode ( int i_tty_dev );
84 /*****************************************************************************
85 * intf_FBCreate: initialize and create window
86 *****************************************************************************/
87 int intf_FBCreate( intf_thread_t *p_intf )
89 struct sigaction sig_tty; /* sigaction for tty change */
90 struct vt_mode vt_mode; /* vt current mode */
92 /* Allocate instance and initialize some members */
93 p_intf->p_sys = malloc( sizeof( intf_sys_t ) );
94 if( p_intf->p_sys == NULL )
98 intf_DbgMsg("0x%x\n", p_intf );
100 /* Set tty and fb devices */
101 p_intf->p_sys->i_tty_dev = 0; /* 0 == /dev/tty0 == current console */
103 FBGfxMode( p_intf->p_sys->i_tty_dev );
105 /* set keyboard settings */
106 if (tcgetattr(0, &p_intf->p_sys->old_termios) == -1)
108 intf_ErrMsg( "intf error: tcgetattr" );
111 if (tcgetattr(0, &p_intf->p_sys->new_termios) == -1)
113 intf_ErrMsg( "intf error: tcgetattr" );
116 p_intf->p_sys->new_termios.c_lflag &= ~ (ICANON | ISIG);
117 p_intf->p_sys->new_termios.c_lflag |= (ECHO | ECHOCTL);
118 p_intf->p_sys->new_termios.c_iflag = 0;
119 p_intf->p_sys->new_termios.c_cc[VMIN] = 1;
120 p_intf->p_sys->new_termios.c_cc[VTIME] = 0;
122 if (tcsetattr(0, TCSAFLUSH, &p_intf->p_sys->new_termios) == -1)
124 intf_ErrMsg( "intf error: tcsetattr" );
127 ioctl(p_intf->p_sys->i_tty_dev, VT_RELDISP, VT_ACKACQ);
129 /* Set-up tty signal handler to be aware of tty changes */
130 memset( &sig_tty, 0, sizeof( sig_tty ) );
131 sig_tty.sa_handler = FBSwitchDisplay;
132 sigemptyset( &sig_tty.sa_mask );
133 if( sigaction( SIGUSR1, &sig_tty, &p_intf->p_sys->sig_usr1 ) ||
134 sigaction( SIGUSR2, &sig_tty, &p_intf->p_sys->sig_usr2 ) )
136 intf_ErrMsg( "intf error: can't set up signal handler (%s)\n",
138 tcsetattr(0, 0, &p_intf->p_sys->old_termios);
139 FBTextMode( p_intf->p_sys->i_tty_dev );
143 /* Set-up tty according to new signal handler */
144 if( ioctl(p_intf->p_sys->i_tty_dev, VT_GETMODE, &p_intf->p_sys->vt_mode)
147 intf_ErrMsg( "intf error: cant get terminal mode (%s)\n",
149 sigaction( SIGUSR1, &p_intf->p_sys->sig_usr1, NULL );
150 sigaction( SIGUSR2, &p_intf->p_sys->sig_usr2, NULL );
151 tcsetattr(0, 0, &p_intf->p_sys->old_termios);
152 FBTextMode( p_intf->p_sys->i_tty_dev );
155 memcpy( &vt_mode, &p_intf->p_sys->vt_mode, sizeof( vt_mode ) );
156 vt_mode.mode = VT_PROCESS;
158 vt_mode.relsig = SIGUSR1;
159 vt_mode.acqsig = SIGUSR2;
161 if( ioctl(p_intf->p_sys->i_tty_dev, VT_SETMODE, &vt_mode) == -1 )
163 intf_ErrMsg( "intf error: can't set terminal mode (%s)\n",
165 sigaction( SIGUSR1, &p_intf->p_sys->sig_usr1, NULL );
166 sigaction( SIGUSR2, &p_intf->p_sys->sig_usr2, NULL );
167 tcsetattr(0, 0, &p_intf->p_sys->old_termios);
168 FBTextMode( p_intf->p_sys->i_tty_dev );
172 /* Spawn video output thread */
173 if( p_main->b_video )
175 p_intf->p_vout = vout_CreateThread( NULL, 0,
176 p_intf->p_sys->i_width,
177 p_intf->p_sys->i_height,
179 if( p_intf->p_vout == NULL ) /* XXX?? error */
181 intf_ErrMsg("intf error: can't create output thread\n" );
182 ioctl( p_intf->p_sys->i_tty_dev, VT_SETMODE,
183 &p_intf->p_sys->vt_mode );
184 sigaction( SIGUSR1, &p_intf->p_sys->sig_usr1, NULL );
185 sigaction( SIGUSR2, &p_intf->p_sys->sig_usr2, NULL );
186 free( p_intf->p_sys );
187 tcsetattr(0, 0, &p_intf->p_sys->old_termios);
188 FBTextMode( p_intf->p_sys->i_tty_dev );
196 /*****************************************************************************
197 * intf_FBDestroy: destroy interface window
198 *****************************************************************************/
199 void intf_FBDestroy( intf_thread_t *p_intf )
201 /* resets the keyboard state */
202 tcsetattr(0, 0, &p_intf->p_sys->old_termios);
204 /* return to text mode */
205 FBTextMode( p_intf->p_sys->i_tty_dev );
207 /* Close input thread, if any (blocking) */
208 if( p_intf->p_input )
210 input_DestroyThread( p_intf->p_input, NULL );
213 /* Close video output thread, if any (blocking) */
216 vout_DestroyThread( p_intf->p_vout, NULL );
219 /* Destroy structure */
220 free( p_intf->p_sys );
224 /*****************************************************************************
225 * intf_FBManage: event loop
226 *****************************************************************************/
227 void intf_FBManage( intf_thread_t *p_intf )
229 unsigned char buf[16];
231 //while ( read(0, buf, 1) == 1)
232 if ( read(0, buf, 1) == 1)
234 if( intf_ProcessKey(p_intf, (int)buf[0]) )
236 intf_ErrMsg("unhandled key '%c' (%i)\n", (char) buf[0], buf[0] );
241 /*****************************************************************************
242 * FBSwitchDisplay: VT change signal handler
243 *****************************************************************************
244 * This function activates or deactivates the output of the thread. It is
245 * called by the VT driver, on terminal change.
246 *****************************************************************************/
247 static void FBSwitchDisplay(int i_signal)
249 if( p_main->p_intf->p_vout != NULL )
253 case SIGUSR1: /* vt has been released */
254 p_main->p_intf->p_vout->b_active = 0;
255 ioctl( ((intf_sys_t *)p_main->p_intf->p_sys)->i_tty_dev,
258 case SIGUSR2: /* vt has been acquired */
259 p_main->p_intf->p_vout->b_active = 1;
260 ioctl( ((intf_sys_t *)p_main->p_intf->p_sys)->i_tty_dev,
261 VT_RELDISP, VT_ACTIVATE );
262 /* handle blanking */
263 p_main->p_intf->p_vout->i_changes |= VOUT_SIZE_CHANGE;
269 /*****************************************************************************
270 * FBTextMode and FBGfxMode : switch tty to text/graphic mode
271 *****************************************************************************
272 * These functions toggle the tty mode.
273 *****************************************************************************/
274 static void FBTextMode( int i_tty_dev )
276 /* return to text mode */
277 if (-1 == ioctl(i_tty_dev, KDSETMODE, KD_TEXT))
279 intf_ErrMsg("intf error: ioctl KDSETMODE\n");
283 static void FBGfxMode( int i_tty_dev )
285 /* switch to graphic mode */
286 if (-1 == ioctl(i_tty_dev, KDSETMODE, KD_GRAPHICS))
288 intf_ErrMsg("intf error: ioctl KDSETMODE\n");
292 /*****************************************************************************
293 * vout_SysPrint: print simple text on a picture
294 *****************************************************************************
295 * This function will print a simple text on the picture. It is designed to
296 * print debugging or general informations, not to render subtitles.
297 *****************************************************************************/
298 void vout_SysPrint( vout_thread_t *p_vout, int i_x, int i_y, int i_halign,
299 int i_valign, unsigned char *psz_text )