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* */
47 #include "stream_control.h"
48 #include "input_ext-intf.h"
51 #include "video_output.h"
54 #include "interface.h"
58 /*****************************************************************************
59 * intf_sys_t: description and status of FB interface
60 *****************************************************************************/
61 typedef struct intf_sys_s
63 /* System informations */
64 int i_tty_dev; /* tty device handle */
66 /* Original configuration informations */
67 struct sigaction sig_usr1; /* USR1 previous handler */
68 struct sigaction sig_usr2; /* USR2 previous handler */
69 struct vt_mode vt_mode; /* previous VT mode */
71 int i_width; /* width of main window */
72 int i_height; /* height of main window */
74 struct termios old_termios;
75 struct termios new_termios;
79 /*****************************************************************************
81 *****************************************************************************/
82 static void FBSwitchDisplay ( int i_signal );
83 static void FBTextMode ( int i_tty_dev );
84 static void FBGfxMode ( int i_tty_dev );
86 /*****************************************************************************
87 * intf_FBCreate: initialize and create window
88 *****************************************************************************/
89 int intf_FBCreate( intf_thread_t *p_intf )
91 struct sigaction sig_tty; /* sigaction for tty change */
92 struct vt_mode vt_mode; /* vt current mode */
94 /* Allocate instance and initialize some members */
95 p_intf->p_sys = malloc( sizeof( intf_sys_t ) );
96 if( p_intf->p_sys == NULL )
101 /* Set tty and fb devices */
102 p_intf->p_sys->i_tty_dev = 0; /* 0 == /dev/tty0 == current console */
104 FBGfxMode( p_intf->p_sys->i_tty_dev );
106 /* set keyboard settings */
107 if (tcgetattr(0, &p_intf->p_sys->old_termios) == -1)
109 intf_ErrMsg( "intf error: tcgetattr" );
112 if (tcgetattr(0, &p_intf->p_sys->new_termios) == -1)
114 intf_ErrMsg( "intf error: tcgetattr" );
117 p_intf->p_sys->new_termios.c_lflag &= ~ (ICANON | ISIG);
118 p_intf->p_sys->new_termios.c_lflag |= (ECHO | ECHOCTL);
119 p_intf->p_sys->new_termios.c_iflag = 0;
120 p_intf->p_sys->new_termios.c_cc[VMIN] = 1;
121 p_intf->p_sys->new_termios.c_cc[VTIME] = 0;
123 if (tcsetattr(0, TCSAFLUSH, &p_intf->p_sys->new_termios) == -1)
125 intf_ErrMsg( "intf error: tcsetattr" );
128 ioctl(p_intf->p_sys->i_tty_dev, VT_RELDISP, VT_ACKACQ);
130 /* Set-up tty signal handler to be aware of tty changes */
131 memset( &sig_tty, 0, sizeof( sig_tty ) );
132 sig_tty.sa_handler = FBSwitchDisplay;
133 sigemptyset( &sig_tty.sa_mask );
134 if( sigaction( SIGUSR1, &sig_tty, &p_intf->p_sys->sig_usr1 ) ||
135 sigaction( SIGUSR2, &sig_tty, &p_intf->p_sys->sig_usr2 ) )
137 intf_ErrMsg( "intf error: can't set up signal handler (%s)",
139 tcsetattr(0, 0, &p_intf->p_sys->old_termios);
140 FBTextMode( p_intf->p_sys->i_tty_dev );
144 /* Set-up tty according to new signal handler */
145 if( ioctl(p_intf->p_sys->i_tty_dev, VT_GETMODE, &p_intf->p_sys->vt_mode)
148 intf_ErrMsg( "intf error: cant get terminal mode (%s)",
150 sigaction( SIGUSR1, &p_intf->p_sys->sig_usr1, NULL );
151 sigaction( SIGUSR2, &p_intf->p_sys->sig_usr2, NULL );
152 tcsetattr(0, 0, &p_intf->p_sys->old_termios);
153 FBTextMode( p_intf->p_sys->i_tty_dev );
156 memcpy( &vt_mode, &p_intf->p_sys->vt_mode, sizeof( vt_mode ) );
157 vt_mode.mode = VT_PROCESS;
159 vt_mode.relsig = SIGUSR1;
160 vt_mode.acqsig = SIGUSR2;
162 if( ioctl(p_intf->p_sys->i_tty_dev, VT_SETMODE, &vt_mode) == -1 )
164 intf_ErrMsg( "intf error: can't set terminal mode (%s)",
166 sigaction( SIGUSR1, &p_intf->p_sys->sig_usr1, NULL );
167 sigaction( SIGUSR2, &p_intf->p_sys->sig_usr2, NULL );
168 tcsetattr(0, 0, &p_intf->p_sys->old_termios);
169 FBTextMode( p_intf->p_sys->i_tty_dev );
173 /* Spawn video output thread */
174 if( p_main->b_video )
176 p_intf->p_vout = vout_CreateThread( NULL, 0,
177 p_intf->p_sys->i_width,
178 p_intf->p_sys->i_height,
180 if( p_intf->p_vout == NULL ) /* XXX?? error */
182 intf_ErrMsg("intf error: can't create output thread" );
183 ioctl( p_intf->p_sys->i_tty_dev, VT_SETMODE,
184 &p_intf->p_sys->vt_mode );
185 sigaction( SIGUSR1, &p_intf->p_sys->sig_usr1, NULL );
186 sigaction( SIGUSR2, &p_intf->p_sys->sig_usr2, NULL );
187 free( p_intf->p_sys );
188 tcsetattr(0, 0, &p_intf->p_sys->old_termios);
189 FBTextMode( p_intf->p_sys->i_tty_dev );
195 intf_AssignNormalKeys( p_intf );
200 /*****************************************************************************
201 * intf_FBDestroy: destroy interface window
202 *****************************************************************************/
203 void intf_FBDestroy( intf_thread_t *p_intf )
205 /* resets the keyboard state */
206 tcsetattr(0, 0, &p_intf->p_sys->old_termios);
208 /* return to text mode */
209 FBTextMode( p_intf->p_sys->i_tty_dev );
211 /* Close input thread, if any (blocking) */
212 if( p_intf->p_input )
214 input_DestroyThread( p_intf->p_input, NULL );
217 /* Close video output thread, if any (blocking) */
220 vout_DestroyThread( p_intf->p_vout, NULL );
223 /* Destroy structure */
224 free( p_intf->p_sys );
228 /*****************************************************************************
229 * intf_FBManage: event loop
230 *****************************************************************************/
231 void intf_FBManage( intf_thread_t *p_intf )
233 unsigned char buf[16];
235 //while ( read(0, buf, 1) == 1)
236 if ( read(0, buf, 1) == 1)
238 if( intf_ProcessKey(p_intf, (int)buf[0]) )
240 intf_ErrMsg("unhandled key '%c' (%i)", (char) buf[0], buf[0] );
245 /*****************************************************************************
246 * FBSwitchDisplay: VT change signal handler
247 *****************************************************************************
248 * This function activates or deactivates the output of the thread. It is
249 * called by the VT driver, on terminal change.
250 *****************************************************************************/
251 static void FBSwitchDisplay(int i_signal)
253 if( p_main->p_intf->p_vout != NULL )
257 case SIGUSR1: /* vt has been released */
258 p_main->p_intf->p_vout->b_active = 0;
259 ioctl( ((intf_sys_t *)p_main->p_intf->p_sys)->i_tty_dev,
262 case SIGUSR2: /* vt has been acquired */
263 p_main->p_intf->p_vout->b_active = 1;
264 ioctl( ((intf_sys_t *)p_main->p_intf->p_sys)->i_tty_dev,
265 VT_RELDISP, VT_ACTIVATE );
266 /* handle blanking */
267 p_main->p_intf->p_vout->i_changes |= VOUT_SIZE_CHANGE;
273 /*****************************************************************************
274 * FBTextMode and FBGfxMode : switch tty to text/graphic mode
275 *****************************************************************************
276 * These functions toggle the tty mode.
277 *****************************************************************************/
278 static void FBTextMode( int i_tty_dev )
280 /* return to text mode */
281 if (-1 == ioctl(i_tty_dev, KDSETMODE, KD_TEXT))
283 intf_ErrMsg("intf error: ioctl KDSETMODE");
287 static void FBGfxMode( int i_tty_dev )
289 /* switch to graphic mode */
290 if (-1 == ioctl(i_tty_dev, KDSETMODE, KD_GRAPHICS))
292 intf_ErrMsg("intf error: ioctl KDSETMODE");
296 /*****************************************************************************
297 * vout_SysPrint: print simple text on a picture
298 *****************************************************************************
299 * This function will print a simple text on the picture. It is designed to
300 * print debugging or general informations, not to render subtitles.
301 *****************************************************************************/
302 void vout_SysPrint( vout_thread_t *p_vout, int i_x, int i_y, int i_halign,
303 int i_valign, unsigned char *psz_text )