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_SysCreate: initialize and create window
86 *****************************************************************************/
87 int intf_SysCreate( 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)
107 intf_ErrMsg( "intf error: tcgetattr" );
108 if (tcgetattr(0, &p_intf->p_sys->new_termios) == -1)
109 intf_ErrMsg( "intf error: tcgetattr" );
111 p_intf->p_sys->new_termios.c_lflag &= ~ (ICANON | ISIG);
112 p_intf->p_sys->new_termios.c_lflag |= (ECHO | ECHOCTL);
113 p_intf->p_sys->new_termios.c_iflag = 0;
114 p_intf->p_sys->new_termios.c_cc[VMIN] = 1;
115 p_intf->p_sys->new_termios.c_cc[VTIME] = 0;
117 if (tcsetattr(0, TCSAFLUSH, &p_intf->p_sys->new_termios) == -1)
118 intf_ErrMsg( "intf error: tcsetattr" );
120 ioctl(p_intf->p_sys->i_tty_dev, VT_RELDISP, VT_ACKACQ);
122 /* Set-up tty signal handler to be aware of tty changes */
123 memset( &sig_tty, 0, sizeof( sig_tty ) );
124 sig_tty.sa_handler = FBSwitchDisplay;
125 sigemptyset( &sig_tty.sa_mask );
126 if( sigaction( SIGUSR1, &sig_tty, &p_intf->p_sys->sig_usr1 ) ||
127 sigaction( SIGUSR2, &sig_tty, &p_intf->p_sys->sig_usr2 ) )
129 intf_ErrMsg("intf error: can't set up signal handler (%s)\n", strerror(errno) );
130 FBTextMode( p_intf->p_sys->i_tty_dev );
134 /* Set-up tty according to new signal handler */
135 if( ioctl(p_intf->p_sys->i_tty_dev, VT_GETMODE, &p_intf->p_sys->vt_mode) == -1 )
137 intf_ErrMsg("intf error: cant get terminal mode (%s)\n", strerror(errno) );
138 sigaction( SIGUSR1, &p_intf->p_sys->sig_usr1, NULL );
139 sigaction( SIGUSR2, &p_intf->p_sys->sig_usr2, NULL );
140 FBTextMode( p_intf->p_sys->i_tty_dev );
143 memcpy( &vt_mode, &p_intf->p_sys->vt_mode, sizeof( vt_mode ) );
144 vt_mode.mode = VT_PROCESS;
146 vt_mode.relsig = SIGUSR1;
147 vt_mode.acqsig = SIGUSR2;
149 if( ioctl(p_intf->p_sys->i_tty_dev, VT_SETMODE, &vt_mode) == -1 )
151 intf_ErrMsg("intf error: can't set terminal mode (%s)\n", strerror(errno) );
152 sigaction( SIGUSR1, &p_intf->p_sys->sig_usr1, NULL );
153 sigaction( SIGUSR2, &p_intf->p_sys->sig_usr2, NULL );
154 FBTextMode( p_intf->p_sys->i_tty_dev );
158 /* Spawn video output thread */
159 if( p_main->b_video )
161 p_intf->p_vout = vout_CreateThread( NULL, 0,
162 p_intf->p_sys->i_width,
163 p_intf->p_sys->i_height, NULL, 0, NULL );
164 if( p_intf->p_vout == NULL ) /* XXX?? error */
166 intf_ErrMsg("intf error: can't create output thread\n" );
167 ioctl(p_intf->p_sys->i_tty_dev, VT_SETMODE, &p_intf->p_sys->vt_mode);
168 sigaction( SIGUSR1, &p_intf->p_sys->sig_usr1, NULL );
169 sigaction( SIGUSR2, &p_intf->p_sys->sig_usr2, NULL );
170 free( p_intf->p_sys );
171 FBTextMode( p_intf->p_sys->i_tty_dev );
179 /*****************************************************************************
180 * intf_SysDestroy: destroy interface window
181 *****************************************************************************/
182 void intf_SysDestroy( intf_thread_t *p_intf )
184 /* resets the keyboard state */
185 tcsetattr(0, 0, &p_intf->p_sys->old_termios);
187 /* return to text mode */
188 FBTextMode( p_intf->p_sys->i_tty_dev );
190 /* Close input thread, if any (blocking) */
191 if( p_intf->p_input )
193 input_DestroyThread( p_intf->p_input, NULL );
196 /* Close video output thread, if any (blocking) */
199 vout_DestroyThread( p_intf->p_vout, NULL );
202 /* Destroy structure */
203 free( p_intf->p_sys );
207 /*****************************************************************************
208 * intf_SysManage: event loop
209 *****************************************************************************/
210 void intf_SysManage( intf_thread_t *p_intf )
212 unsigned char buf[16];
214 //while ( read(0, buf, 1) == 1)
215 if ( read(0, buf, 1) == 1)
217 if( intf_ProcessKey(p_intf, (int)buf[0]) )
219 intf_ErrMsg("unhandled key '%c' (%i)\n", (char) buf[0], buf[0] );
224 /*****************************************************************************
225 * FBSwitchDisplay: VT change signal handler
226 *****************************************************************************
227 * This function activate or desactivate the output of the thread. It is called
228 * by the VT driver, on terminal change.
229 *****************************************************************************/
230 static void FBSwitchDisplay(int i_signal)
232 if( p_main->p_intf->p_vout != NULL )
236 case SIGUSR1: /* vt has been released */
237 p_main->p_intf->p_vout->b_active = 0;
238 ioctl( ((intf_sys_t *)p_main->p_intf->p_sys)->i_tty_dev,
241 case SIGUSR2: /* vt has been acquired */
242 p_main->p_intf->p_vout->b_active = 1;
243 ioctl( ((intf_sys_t *)p_main->p_intf->p_sys)->i_tty_dev,
244 VT_RELDISP, VT_ACTIVATE );
245 /* handle blanking */
246 p_main->p_intf->p_vout->i_changes |= VOUT_SIZE_CHANGE;
252 /*****************************************************************************
253 * FBTextMode and FBGfxMode : switch tty to text/graphic mode
254 *****************************************************************************
255 * These functions toggle the tty mode.
256 *****************************************************************************/
257 static void FBTextMode( int i_tty_dev )
259 /* return to text mode */
260 if (-1 == ioctl(i_tty_dev, KDSETMODE, KD_TEXT))
262 intf_ErrMsg("intf error: ioctl KDSETMODE\n");
266 static void FBGfxMode( int i_tty_dev )
268 /* switch to graphic mode */
269 if (-1 == ioctl(i_tty_dev, KDSETMODE, KD_GRAPHICS))
271 intf_ErrMsg("intf error: ioctl KDSETMODE\n");
275 /*****************************************************************************
276 * vout_SysPrint: print simple text on a picture
277 *****************************************************************************
278 * This function will print a simple text on the picture. It is designed to
279 * print debugging or general informations, not to render subtitles.
280 *****************************************************************************/
281 void vout_SysPrint( vout_thread_t *p_vout, int i_x, int i_y, int i_halign,
282 int i_valign, unsigned char *psz_text )