7373793f5f59817535ce0781d856fcd3e38d39ae
[vlc.git] / modules / access / pvr / pvr.c
1 /*****************************************************************************
2  * pvr.c
3  *****************************************************************************
4  * Copyright (C) 2001, 2002 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Eric Petit <titer@videolan.org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <vlc/vlc.h>
28 #include <vlc/input.h>
29
30 #include <stdlib.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <fcntl.h>
34 #include <unistd.h>
35 #include <errno.h>
36 #include <linux/types.h>
37 #include <sys/ioctl.h>
38 #include "videodev2.h"
39
40 /*****************************************************************************
41  * Module descriptor
42  *****************************************************************************/
43 static int  Open ( vlc_object_t * );
44 static void Close( vlc_object_t * );
45
46 #define CACHING_TEXT N_("Caching value in ms")
47 #define CACHING_LONGTEXT N_( \
48     "Default caching value for PVR streams. This " \
49     "value should be set in milliseconds." )
50
51 #define DEVICE_TEXT N_( "Device" )
52 #define DEVICE_LONGTEXT N_( "PVR video device" )
53
54 #define RADIO_DEVICE_TEXT N_( "Radio device" )
55 #define RADIO_DEVICE_LONGTEXT N_( "PVR radio device" )
56
57 #define NORM_TEXT N_( "Norm" )
58 #define NORM_LONGTEXT N_( "Norm of the stream " \
59     "(Automatic, SECAM, PAL, or NTSC)." )
60
61 #define WIDTH_TEXT N_( "Width" )
62 #define WIDTH_LONGTEXT N_( "Width of the stream to capture " \
63     "(-1 for autodetection)." )
64
65 #define HEIGHT_TEXT N_( "Height" )
66 #define HEIGHT_LONGTEXT N_( "Height of the stream to capture " \
67     "(-1 for autodetection)." )
68
69 #define FREQUENCY_TEXT N_( "Frequency" )
70 #define FREQUENCY_LONGTEXT N_( "Frequency to capture (in kHz), if applicable." )
71
72 #define FRAMERATE_TEXT N_( "Framerate" )
73 #define FRAMERATE_LONGTEXT N_( "Framerate to capture, if applicable " \
74     "(-1 for autodetect)." )
75
76 #define KEYINT_TEXT N_( "Key interval" )
77 #define KEYINT_LONGTEXT N_( "Interval between keyframes (-1 for autodetect)." )
78
79 #define BFRAMES_TEXT N_( "B Frames" )
80 #define BFRAMES_LONGTEXT N_("If this option is set, B-Frames will be used. " \
81     "Use this option to set the number of B-Frames.")
82
83 #define BITRATE_TEXT N_( "Bitrate" )
84 #define BITRATE_LONGTEXT N_( "Bitrate to use (-1 for default)." )
85
86 #define BITRATE_PEAK_TEXT N_( "Bitrate peak" )
87 #define BITRATE_PEAK_LONGTEXT N_( "Peak bitrate in VBR mode." )
88
89 #define BITRATE_MODE_TEXT N_( "Bitrate mode)" )
90 #define BITRATE_MODE_LONGTEXT N_( "Bitrate mode to use (VBR or CBR)." )
91
92 #define BITMASK_TEXT N_( "Audio bitmask" )
93 #define BITMASK_LONGTEXT N_("Bitmask that will "\
94     "get used by the audio part of the card." )
95
96 #define VOLUME_TEXT N_( "Volume" )
97 #define VOLUME_LONGTEXT N_("Audio volume (0-65535)." )
98
99 #define CHAN_TEXT N_( "Channel" )
100 #define CHAN_LONGTEXT N_( "Channel of the card to use (Usually, 0 = tuner, " \
101     "1 = composite, 2 = svideo)" )
102
103 static int i_norm_list[] =
104     { V4L2_STD_UNKNOWN, V4L2_STD_SECAM, V4L2_STD_PAL, V4L2_STD_NTSC };
105 static char *psz_norm_list_text[] =
106     { N_("Automatic"), N_("SECAM"), N_("PAL"),  N_("NTSC") };
107
108 static int i_bitrates[] = { 0, 1 };
109 static char *psz_bitrates_list_text[] = { N_("vbr"), N_("cbr") };
110
111 static int pi_radio_range[2] = { 65000, 108000 };
112
113 vlc_module_begin();
114     set_shortname( _("PVR") );
115     set_description( _("IVTV MPEG Encoding cards input") );
116     set_category( CAT_INPUT );
117     set_subcategory( SUBCAT_INPUT_ACCESS );
118     set_capability( "access2", 0 );
119     add_shortcut( "pvr" );
120
121     add_integer( "pvr-caching", DEFAULT_PTS_DELAY / 1000, NULL, CACHING_TEXT, CACHING_LONGTEXT, VLC_TRUE );
122     add_string( "pvr-device", "/dev/video0", NULL, DEVICE_TEXT,
123                  DEVICE_LONGTEXT, VLC_FALSE );
124     add_string( "pvr-radio-device", "/dev/radio0", NULL, RADIO_DEVICE_TEXT,
125                  RADIO_DEVICE_LONGTEXT, VLC_FALSE );
126     add_integer( "pvr-norm", V4L2_STD_UNKNOWN , NULL, NORM_TEXT,
127                  NORM_LONGTEXT, VLC_FALSE );
128        change_integer_list( i_norm_list, psz_norm_list_text, 0 );
129     add_integer( "pvr-width", -1, NULL, WIDTH_TEXT, WIDTH_LONGTEXT, VLC_TRUE );
130     add_integer( "pvr-height", -1, NULL, HEIGHT_TEXT, HEIGHT_LONGTEXT,
131                  VLC_TRUE );
132     add_integer( "pvr-frequency", -1, NULL, FREQUENCY_TEXT, FREQUENCY_LONGTEXT,
133                  VLC_FALSE );
134     add_integer( "pvr-framerate", -1, NULL, FRAMERATE_TEXT, FRAMERATE_LONGTEXT,
135                  VLC_TRUE );
136     add_integer( "pvr-keyint", -1, NULL, KEYINT_TEXT, KEYINT_LONGTEXT,
137                  VLC_TRUE );
138     add_integer( "pvr-bframes", -1, NULL, FRAMERATE_TEXT, FRAMERATE_LONGTEXT,
139                  VLC_TRUE );
140     add_integer( "pvr-bitrate", -1, NULL, BITRATE_TEXT, BITRATE_LONGTEXT,
141                  VLC_FALSE );
142     add_integer( "pvr-bitrate-peak", -1, NULL, BITRATE_PEAK_TEXT,
143                  BITRATE_PEAK_LONGTEXT, VLC_TRUE );
144     add_integer( "pvr-bitrate-mode", -1, NULL, BITRATE_MODE_TEXT,
145                  BITRATE_MODE_LONGTEXT, VLC_TRUE );
146         change_integer_list( i_bitrates, psz_bitrates_list_text, 0 );
147     add_integer( "pvr-audio-bitmask", -1, NULL, BITMASK_TEXT,
148                  BITMASK_LONGTEXT, VLC_TRUE );
149     add_integer( "pvr-audio-volume", -1, NULL, VOLUME_TEXT,
150                  VOLUME_LONGTEXT, VLC_TRUE );
151     add_integer( "pvr-channel", -1, NULL, CHAN_TEXT, CHAN_LONGTEXT, VLC_TRUE );
152
153     set_callbacks( Open, Close );
154 vlc_module_end();
155
156 /*****************************************************************************
157  * Prototypes
158  *****************************************************************************/
159 static int Read   ( access_t *, uint8_t *, int );
160 static int Control( access_t *, int, va_list );
161
162 /* ivtv specific ioctls */
163 #define IVTV_IOC_G_CODEC    0xFFEE7703
164 #define IVTV_IOC_S_CODEC    0xFFEE7704
165
166 /* for use with IVTV_IOC_G_CODEC and IVTV_IOC_S_CODEC */
167
168 struct ivtv_ioctl_codec {
169         uint32_t aspect;
170         uint32_t audio_bitmask;
171         uint32_t bframes;
172         uint32_t bitrate_mode;
173         uint32_t bitrate;
174         uint32_t bitrate_peak;
175         uint32_t dnr_mode;
176         uint32_t dnr_spatial;
177         uint32_t dnr_temporal;
178         uint32_t dnr_type;
179         uint32_t framerate;
180         uint32_t framespergop;
181         uint32_t gop_closure;
182         uint32_t pulldown;
183         uint32_t stream_type;
184 };
185
186 struct access_sys_t
187 {
188     /* file descriptor */
189     int i_fd;
190     int i_radio_fd;
191
192     /* options */
193     int i_standard;
194     int i_width;
195     int i_height;
196     int i_frequency;
197     int i_framerate;
198     int i_keyint;
199     int i_bframes;
200     int i_bitrate;
201     int i_bitrate_peak;
202     int i_bitrate_mode;
203     int i_audio_bitmask;
204     int i_input;
205     int i_volume;
206 };
207
208 /*****************************************************************************
209  * Open: open the device
210  *****************************************************************************/
211 static int Open( vlc_object_t * p_this )
212 {
213     access_t *p_access = (access_t*) p_this;
214     access_sys_t * p_sys;
215     char * psz_tofree, * psz_parser, * psz_device, * psz_radio_device;
216     vlc_value_t val;
217
218     //psz_device = calloc( strlen( "/dev/videox" ) + 1, 1 );
219
220     p_access->pf_read = Read;
221     p_access->pf_block = NULL;
222     p_access->pf_seek = NULL;
223     p_access->pf_control = Control;
224     p_access->info.i_update = 0;
225     p_access->info.i_size = 0;
226     p_access->info.i_pos = 0;
227     p_access->info.b_eof = VLC_FALSE;
228     p_access->info.i_title = 0;
229     p_access->info.i_seekpoint = 0;
230
231     /* create private access data */
232     p_sys = calloc( sizeof( access_sys_t ), 1 );
233     p_access->p_sys = p_sys;
234
235     /* defaults values */
236     var_Create( p_access, "pvr-caching", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
237
238     var_Create( p_access, "pvr-device", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
239     var_Get( p_access, "pvr-device" , &val);
240     psz_device = val.psz_string;
241
242     var_Create( p_access, "pvr-radio-device", VLC_VAR_STRING |
243                                               VLC_VAR_DOINHERIT );
244     var_Get( p_access, "pvr-radio-device" , &val);
245     psz_radio_device = val.psz_string;
246
247     var_Create( p_access, "pvr-norm", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
248     var_Get( p_access, "pvr-norm" , &val);
249     p_sys->i_standard = val.i_int;
250
251     var_Create( p_access, "pvr-width", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
252     var_Get( p_access, "pvr-width" , &val);
253     p_sys->i_width = val.i_int;
254
255     var_Create( p_access, "pvr-height", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
256     var_Get( p_access, "pvr-height" , &val);
257     p_sys->i_height = val.i_int;
258
259     var_Create( p_access, "pvr-frequency", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
260     var_Get( p_access, "pvr-frequency" , &val);
261     p_sys->i_frequency = val.i_int;
262
263     var_Create( p_access, "pvr-framerate", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
264     var_Get( p_access, "pvr-framerate" , &val);
265     p_sys->i_framerate = val.i_int;
266
267     var_Create( p_access, "pvr-keyint", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
268     var_Get( p_access, "pvr-keyint" , &val);
269     p_sys->i_keyint = val.i_int;
270
271     var_Create( p_access, "pvr-bframes", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
272     var_Get( p_access, "pvr-bframes" , &val);
273     p_sys->i_bframes = val.b_bool;
274
275     var_Create( p_access, "pvr-bitrate", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
276     var_Get( p_access, "pvr-bitrate" , &val);
277     p_sys->i_bitrate = val.i_int;
278
279     var_Create( p_access, "pvr-bitrate-peak", VLC_VAR_INTEGER |
280                                               VLC_VAR_DOINHERIT );
281     var_Get( p_access, "pvr-bitrate-peak" , &val);
282     p_sys->i_bitrate_peak = val.i_int;
283
284     var_Create( p_access, "pvr-bitrate-mode", VLC_VAR_INTEGER |
285                                               VLC_VAR_DOINHERIT );
286     var_Get( p_access, "pvr-bitrate-mode" , &val);
287     p_sys->i_bitrate_mode = val.i_int;
288
289     var_Create( p_access, "pvr-audio-bitmask", VLC_VAR_INTEGER |
290                                               VLC_VAR_DOINHERIT );
291     var_Get( p_access, "pvr-audio-bitmask" , &val);
292     p_sys->i_audio_bitmask = val.i_int;
293
294     var_Create( p_access, "pvr-audio-volume", VLC_VAR_INTEGER |
295                                               VLC_VAR_DOINHERIT );
296     var_Get( p_access, "pvr-audio-volume" , &val);
297     p_sys->i_volume = val.i_int;
298
299     var_Create( p_access, "pvr-channel", VLC_VAR_INTEGER |
300                                               VLC_VAR_DOINHERIT );
301     var_Get( p_access, "pvr-channel" , &val);
302     p_sys->i_input = val.i_int;
303
304     /* parse command line options */
305     psz_tofree = strdup( p_access->psz_path );
306     psz_parser = psz_tofree;
307
308     if( *psz_parser )
309     {
310         for( ;; )
311         {
312             if ( !strncmp( psz_parser, "norm=", strlen( "norm=" ) ) )
313             {
314                 char *psz_parser_init;
315                 psz_parser += strlen( "norm=" );
316                 psz_parser_init = psz_parser;
317                 while ( *psz_parser != ':' && *psz_parser != ','
318                                                     && *psz_parser != '\0' )
319                 {
320                     psz_parser++;
321                 }
322
323                 if ( !strncmp( psz_parser_init, "secam" ,
324                                psz_parser - psz_parser_init ) )
325                 {
326                     p_sys->i_standard = V4L2_STD_SECAM;
327                 }
328                 else if ( !strncmp( psz_parser_init, "pal" ,
329                                     psz_parser - psz_parser_init ) )
330                 {
331                     p_sys->i_standard = V4L2_STD_PAL;
332                 }
333                 else if ( !strncmp( psz_parser_init, "ntsc" ,
334                                     psz_parser - psz_parser_init ) )
335                 {
336                     p_sys->i_standard = V4L2_STD_NTSC;
337                 }
338                 else
339                 {
340                     p_sys->i_standard = strtol( psz_parser_init ,
341                                                 &psz_parser, 0 );
342                 }
343             }
344             else if( !strncmp( psz_parser, "channel=",
345                                strlen( "channel=" ) ) )
346             {
347                 p_sys->i_input =
348                     strtol( psz_parser + strlen( "channel=" ),
349                             &psz_parser, 0 );
350             }
351             else if( !strncmp( psz_parser, "device=", strlen( "device=" ) ) )
352             {
353                 psz_device = calloc( strlen( "/dev/videox" ) + 1, 1 );
354                 sprintf( psz_device, "/dev/video%ld",
355                             strtol( psz_parser + strlen( "device=" ),
356                             &psz_parser, 0 ) );
357             }
358             else if( !strncmp( psz_parser, "frequency=",
359                                strlen( "frequency=" ) ) )
360             {
361                 p_sys->i_frequency =
362                     strtol( psz_parser + strlen( "frequency=" ),
363                             &psz_parser, 0 );
364             }
365             else if( !strncmp( psz_parser, "framerate=",
366                                strlen( "framerate=" ) ) )
367             {
368                 p_sys->i_framerate =
369                     strtol( psz_parser + strlen( "framerate=" ),
370                             &psz_parser, 0 );
371             }
372             else if( !strncmp( psz_parser, "keyint=",
373                                strlen( "keyint=" ) ) )
374             {
375                 p_sys->i_keyint =
376                     strtol( psz_parser + strlen( "keyint=" ),
377                             &psz_parser, 0 );
378             }
379             else if( !strncmp( psz_parser, "bframes=",
380                                strlen( "bframes=" ) ) )
381             {
382                 p_sys->i_bframes =
383                     strtol( psz_parser + strlen( "bframes=" ),
384                             &psz_parser, 0 );
385             }
386
387             else if( !strncmp( psz_parser, "width=",
388                                strlen( "width=" ) ) )
389             {
390                 p_sys->i_width =
391                     strtol( psz_parser + strlen( "width=" ),
392                             &psz_parser, 0 );
393             }
394             else if( !strncmp( psz_parser, "height=",
395                                strlen( "height=" ) ) )
396             {
397                 p_sys->i_height =
398                     strtol( psz_parser + strlen( "height=" ),
399                             &psz_parser, 0 );
400             }
401             else if( !strncmp( psz_parser, "audio=",
402                                strlen( "audio=" ) ) )
403             {
404                 p_sys->i_audio_bitmask =
405                     strtol( psz_parser + strlen( "audio=" ),
406                             &psz_parser, 0 );
407             }
408             else if( !strncmp( psz_parser, "bitrate=",
409                                strlen( "bitrate=" ) ) )
410             {
411                 p_sys->i_bitrate =
412                     strtol( psz_parser + strlen( "bitrate=" ),
413                             &psz_parser, 0 );
414             }
415             else if( !strncmp( psz_parser, "maxbitrate=",
416                                strlen( "maxbitrate=" ) ) )
417             {
418                 p_sys->i_bitrate_peak =
419                     strtol( psz_parser + strlen( "maxbitrate=" ),
420                             &psz_parser, 0 );
421             }
422             else if( !strncmp( psz_parser, "bitratemode=",
423                                strlen( "bitratemode=" ) ) )
424             {
425                 char *psz_parser_init;
426                 psz_parser += strlen( "bitratemode=" );
427                 psz_parser_init = psz_parser;
428                 while ( *psz_parser != ':' && *psz_parser != ','
429                          && *psz_parser != '\0' )
430                 {
431                     psz_parser++;
432                 }
433
434                 if ( !strncmp( psz_parser_init, "vbr" ,
435                                psz_parser - psz_parser_init ) )
436                 {
437                      p_sys->i_bitrate_mode = 0;
438                 }
439                 else if ( !strncmp( psz_parser_init, "cbr" ,
440                                     psz_parser - psz_parser_init ) )
441                 {
442                     p_sys->i_bitrate_mode = 1;
443                 }
444             }
445             else if( !strncmp( psz_parser, "size=",
446                                strlen( "size=" ) ) )
447             {
448                 p_sys->i_width =
449                     strtol( psz_parser + strlen( "size=" ),
450                             &psz_parser, 0 );
451                 p_sys->i_height =
452                     strtol( psz_parser + 1 ,
453                             &psz_parser, 0 );
454             }
455             else
456             {
457                 char *psz_parser_init;
458                 psz_parser_init = psz_parser;
459                 while ( *psz_parser != ':' && *psz_parser != ',' && *psz_parser != '\0' )
460                 {
461                     psz_parser++;
462                 }
463                 psz_device = calloc( psz_parser - psz_parser_init + 1, 1 );
464                 strncpy( psz_device, psz_parser_init,
465                          psz_parser - psz_parser_init );
466             }
467             if( *psz_parser )
468                 psz_parser++;
469             else
470                 break;
471         }
472     }
473
474     //give a default value to psz_device if none has been specified
475
476     if ( psz_device == NULL )
477     {
478         psz_device = calloc( strlen( "/dev/videox" ) + 1, 1 );
479         strcpy( psz_device, "/dev/video0" );
480     }
481
482     free( psz_tofree );
483
484     /* open the device */
485     if( ( p_sys->i_fd = open( psz_device, O_RDWR ) ) < 0 )
486     {
487         msg_Err( p_access, "cannot open device (%s)", strerror( errno ) );
488         free( p_sys );
489         return VLC_EGENERIC;
490     }
491     else
492     {
493         msg_Dbg( p_access, "using video device: %s",psz_device);
494     }
495
496     free( psz_device );
497
498     /* set the input */
499     if ( p_sys->i_input != -1 )
500     {
501         if ( ioctl( p_sys->i_fd, VIDIOC_S_INPUT, &p_sys->i_input ) < 0 )
502         {
503             msg_Warn( p_access, "VIDIOC_S_INPUT failed" );
504         }
505         else
506         {
507             msg_Dbg( p_access, "input set to :%d", p_sys->i_input);
508         }
509     }
510
511     /* set the video standard */
512     if ( p_sys->i_standard != V4L2_STD_UNKNOWN )
513     {
514         if ( ioctl( p_sys->i_fd, VIDIOC_S_STD, &p_sys->i_standard ) < 0 )
515         {
516             msg_Warn( p_access, "VIDIOC_S_STD failed" );
517         }
518         else
519         {
520             msg_Dbg( p_access, "video standard set to :%x", p_sys->i_standard);
521         }
522     }
523
524     /* set the picture size */
525     if ( p_sys->i_width != -1 || p_sys->i_height != -1 )
526     {
527         struct v4l2_format vfmt;
528
529         vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
530         if ( ioctl( p_sys->i_fd, VIDIOC_G_FMT, &vfmt ) < 0 )
531         {
532             msg_Warn( p_access, "VIDIOC_G_FMT failed" );
533         }
534         else
535         {
536             if ( p_sys->i_width != -1 )
537             {
538                 vfmt.fmt.pix.width = p_sys->i_width;
539             }
540
541             if ( p_sys->i_height != -1 )
542             {
543                 vfmt.fmt.pix.height = p_sys->i_height;
544             }
545
546             if ( ioctl( p_sys->i_fd, VIDIOC_S_FMT, &vfmt ) < 0 )
547             {
548                 msg_Warn( p_access, "VIDIOC_S_FMT failed" );
549             }
550             else
551             {
552                 msg_Dbg( p_access, "picture size set to :%dx%d",
553                          vfmt.fmt.pix.width, vfmt.fmt.pix.height );
554             }
555         }
556     }
557
558     /* set the frequency */
559     if ( p_sys->i_frequency != -1 )
560     {
561         int i_fd;
562         struct v4l2_frequency vf;
563         vf.tuner = 0; /* TODO: let the user choose the tuner */
564
565         if ( p_sys->i_frequency >= pi_radio_range[0]
566               && p_sys->i_frequency <= pi_radio_range[1] )
567         {
568             if( ( p_sys->i_radio_fd = open( psz_radio_device, O_RDWR ) ) < 0 )
569             {
570                 msg_Err( p_access, "cannot open radio device (%s)",
571                          strerror( errno ) );
572                 close( p_sys->i_fd );
573                 free( p_sys );
574                 return VLC_EGENERIC;
575             }
576             else
577             {
578                 msg_Dbg( p_access, "using radio device: %s", psz_radio_device );
579             }
580             i_fd = p_sys->i_radio_fd;
581         }
582         else
583         {
584             i_fd = p_sys->i_fd;
585             p_sys->i_radio_fd = -1;
586         }
587
588         if ( ioctl( i_fd, VIDIOC_G_FREQUENCY, &vf ) < 0 )
589         {
590             msg_Warn( p_access, "VIDIOC_G_FREQUENCY failed (%s)",
591                       strerror( errno ) );
592         }
593         else
594         {
595             vf.frequency = (p_sys->i_frequency * 16 + 500) / 1000;
596             if( ioctl( i_fd, VIDIOC_S_FREQUENCY, &vf ) < 0 )
597             {
598                 msg_Warn( p_access, "VIDIOC_S_FREQUENCY failed (%s)",
599                           strerror( errno ) );
600             }
601             else
602             {
603                 msg_Dbg( p_access, "tuner frequency set to :%d",
604                          p_sys->i_frequency );
605             }
606         }
607     }
608
609     /* control parameters */
610     if ( p_sys->i_volume != -1 )
611     {
612         struct v4l2_control ctrl;
613
614         ctrl.id = V4L2_CID_AUDIO_VOLUME;
615         ctrl.value = p_sys->i_volume;
616
617         if ( ioctl( p_sys->i_fd, VIDIOC_S_CTRL, &ctrl ) < 0 )
618         {
619             msg_Warn( p_access, "VIDIOC_S_CTRL failed" );
620         }
621     }
622
623     /* codec parameters */
624     if ( p_sys->i_framerate != -1
625             || p_sys->i_bitrate_mode != -1
626             || p_sys->i_bitrate_peak != -1
627             || p_sys->i_keyint != -1
628             || p_sys->i_bframes != -1
629             || p_sys->i_bitrate != -1
630             || p_sys->i_audio_bitmask != -1 )
631     {
632         struct ivtv_ioctl_codec codec;
633
634         if ( ioctl( p_sys->i_fd, IVTV_IOC_G_CODEC, &codec ) < 0 )
635         {
636             msg_Warn( p_access, "IVTV_IOC_G_CODEC failed" );
637         }
638         else
639         {
640             if ( p_sys->i_framerate != -1 )
641             {
642                 switch ( p_sys->i_framerate )
643                 {
644                     case 30:
645                         codec.framerate = 0;
646                         break;
647
648                     case 25:
649                         codec.framerate = 1;
650                         break;
651
652                     default:
653                         msg_Warn( p_access, "invalid framerate, reverting to 25" );
654                         codec.framerate = 1;
655                         break;
656                 }
657             }
658
659             if ( p_sys->i_bitrate != -1 )
660             {
661                 codec.bitrate = p_sys->i_bitrate;
662             }
663
664             if ( p_sys->i_bitrate_peak != -1 )
665             {
666                 codec.bitrate_peak = p_sys->i_bitrate_peak;
667             }
668
669             if ( p_sys->i_bitrate_mode != -1 )
670             {
671                 codec.bitrate_mode = p_sys->i_bitrate_mode;
672             }
673
674             if ( p_sys->i_audio_bitmask != -1 )
675             {
676                 codec.audio_bitmask = p_sys->i_audio_bitmask;
677             }
678             if ( p_sys->i_keyint != -1 )
679             {
680                 codec.framespergop = p_sys->i_keyint;
681             }
682
683             if ( p_sys->i_bframes != -1 )
684             {
685                 codec.bframes = p_sys->i_bframes;
686             }
687             if( ioctl( p_sys->i_fd, IVTV_IOC_S_CODEC, &codec ) < 0 )
688             {
689                 msg_Warn( p_access, "IVTV_IOC_S_CODEC failed" );
690             }
691             else
692             {
693                 msg_Dbg( p_access, "Setting codec parameters to:  framerate: %d, bitrate: %d/%d/%d",
694                codec.framerate, codec.bitrate, codec.bitrate_peak, codec.bitrate_mode );
695             }
696         }
697     }
698
699     /* do a quick read */
700 #if 0
701     if ( p_sys->i_fd )
702     {
703         if ( read( p_sys->i_fd, psz_tmp, 1 ) )
704         {
705             msg_Dbg(p_input, "Could read byte from device");
706         }
707         else
708         {
709             msg_Warn(p_input, "Could not read byte from device");
710         }
711     }
712 #endif
713
714     return VLC_SUCCESS;
715 }
716
717 /*****************************************************************************
718  * Close: close the device
719  *****************************************************************************/
720 static void Close( vlc_object_t * p_this )
721 {
722     access_t *p_access = (access_t*) p_this;
723     access_sys_t * p_sys = p_access->p_sys;
724
725     close( p_sys->i_fd );
726     if ( p_sys->i_radio_fd != -1 )
727         close( p_sys->i_radio_fd );
728     free( p_sys );
729 }
730
731 /*****************************************************************************
732  * Read
733  *****************************************************************************/
734 static int Read( access_t * p_access, uint8_t * p_buffer, int i_len )
735 {
736     access_sys_t * p_sys = p_access->p_sys;
737
738     int i_ret;
739
740     struct timeval timeout;
741     fd_set fds;
742
743     FD_ZERO( &fds );
744     FD_SET( p_sys->i_fd, &fds );
745     timeout.tv_sec = 0;
746     timeout.tv_usec = 500000;
747
748     if( p_access->info.b_eof )
749         return 0;
750
751     while( !( i_ret = select( p_sys->i_fd + 1, &fds, NULL, NULL, &timeout) ) )
752     {
753         FD_ZERO( &fds );
754         FD_SET( p_sys->i_fd, &fds );
755         timeout.tv_sec = 0;
756         timeout.tv_usec = 500000;
757
758         if( p_access->b_die )
759             return 0;
760     }
761
762     if( i_ret < 0 )
763     {
764         msg_Err( p_access, "select error (%s)", strerror( errno ) );
765         return -1;
766     }
767
768     i_ret = read( p_sys->i_fd, p_buffer, i_len );
769     if( i_ret == 0 )
770     {
771         p_access->info.b_eof = VLC_TRUE;
772     }
773     else if( i_ret > 0 )
774     {
775         p_access->info.i_pos += i_ret;
776     }
777
778     return i_ret;
779 }
780
781 /*****************************************************************************
782  * Control
783  *****************************************************************************/
784 static int Control( access_t *p_access, int i_query, va_list args )
785 {
786     vlc_bool_t   *pb_bool;
787     int          *pi_int;
788     int64_t      *pi_64;
789
790     switch( i_query )
791     {
792         /* */
793         case ACCESS_CAN_SEEK:
794         case ACCESS_CAN_FASTSEEK:
795             pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );
796             *pb_bool = VLC_FALSE;
797             break;
798         case ACCESS_CAN_PAUSE:
799             pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );
800             *pb_bool = VLC_FALSE;
801             break;
802         case ACCESS_CAN_CONTROL_PACE:
803             pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );
804             *pb_bool = VLC_FALSE;
805             break;
806
807         /* */
808         case ACCESS_GET_MTU:
809             pi_int = (int*)va_arg( args, int * );
810             *pi_int = 0;
811             break;
812
813         case ACCESS_GET_PTS_DELAY:
814             pi_64 = (int64_t*)va_arg( args, int64_t * );
815             *pi_64 = (int64_t)var_GetInteger( p_access, "pvr-caching" ) * 1000;
816             break;
817
818         /* */
819         case ACCESS_SET_PAUSE_STATE:
820             /* Nothing to do */
821             break;
822
823         case ACCESS_GET_TITLE_INFO:
824         case ACCESS_SET_TITLE:
825         case ACCESS_SET_SEEKPOINT:
826         case ACCESS_SET_PRIVATE_ID_STATE:
827             return VLC_EGENERIC;
828
829         default:
830             msg_Warn( p_access, "unimplemented query in control" );
831             return VLC_EGENERIC;
832
833     }
834     return VLC_SUCCESS;
835 }