bbox[n] and spu->scaled_start_row are unsigned, comparison with 0 is pointless.
[mplayer/glamo.git] / stream / tv.c
blob12d23895b9672742a83bd4ed677acee23895a321
1 /*
2 TV Interface for MPlayer
4 (C) Alex Beregszaszi
6 API idea based on libvo2
8 Feb 19, 2002: Significant rewrites by Charles R. Henrich (henrich@msu.edu)
9 to add support for audio, and bktr *BSD support.
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <unistd.h>
16 #include <string.h>
17 #include <ctype.h>
18 #include <sys/time.h>
20 #include "config.h"
23 #include "mp_msg.h"
24 #include "help_mp.h"
26 #include "stream.h"
27 #include "libmpdemux/demuxer.h"
28 #include "libmpdemux/stheader.h"
30 #include "libaf/af_format.h"
31 #include "libmpcodecs/img_format.h"
32 #include "libavutil/avstring.h"
34 #include "tv.h"
36 #include "frequencies.h"
38 tv_channels_t *tv_channel_list;
39 tv_channels_t *tv_channel_current, *tv_channel_last;
40 char *tv_channel_last_real;
42 /* enumerating drivers (like in stream.c) */
43 extern tvi_info_t tvi_info_dummy;
44 #ifdef HAVE_TV_V4L1
45 extern tvi_info_t tvi_info_v4l;
46 #endif
47 #ifdef HAVE_TV_V4L2
48 extern tvi_info_t tvi_info_v4l2;
49 #endif
50 #ifdef HAVE_TV_BSDBT848
51 extern tvi_info_t tvi_info_bsdbt848;
52 #endif
54 static const tvi_info_t* tvi_driver_list[]={
55 &tvi_info_dummy,
56 #ifdef HAVE_TV_V4L1
57 &tvi_info_v4l,
58 #endif
59 #ifdef HAVE_TV_V4L2
60 &tvi_info_v4l2,
61 #endif
62 #ifdef HAVE_TV_BSDBT848
63 &tvi_info_bsdbt848,
64 #endif
65 NULL
69 /* ================== DEMUX_TV ===================== */
71 Return value:
72 0 = EOF(?) or no stream
73 1 = successfully read a packet
75 /* fill demux->video and demux->audio */
77 static int demux_tv_fill_buffer(demuxer_t *demux, demux_stream_t *ds)
79 tvi_handle_t *tvh=(tvi_handle_t*)(demux->priv);
80 demux_packet_t* dp;
81 unsigned int len=0;
83 /* ================== ADD AUDIO PACKET =================== */
85 if (ds==demux->audio && tvh->tv_param->noaudio == 0 &&
86 tvh->functions->control(tvh->priv,
87 TVI_CONTROL_IS_AUDIO, 0) == TVI_CONTROL_TRUE)
89 len = tvh->functions->get_audio_framesize(tvh->priv);
91 dp=new_demux_packet(len);
92 dp->flags|=1; /* Keyframe */
93 dp->pts=tvh->functions->grab_audio_frame(tvh->priv, dp->buffer,len);
94 ds_add_packet(demux->audio,dp);
97 /* ================== ADD VIDEO PACKET =================== */
99 if (ds==demux->video && tvh->functions->control(tvh->priv,
100 TVI_CONTROL_IS_VIDEO, 0) == TVI_CONTROL_TRUE)
102 len = tvh->functions->get_video_framesize(tvh->priv);
103 dp=new_demux_packet(len);
104 dp->flags|=1; /* Keyframe */
105 dp->pts=tvh->functions->grab_video_frame(tvh->priv, dp->buffer, len);
106 ds_add_packet(demux->video,dp);
109 return 1;
112 static int norm_from_string(tvi_handle_t *tvh, char* norm)
114 #ifdef HAVE_TV_V4L2
115 if (strcmp(tvh->tv_param->driver, "v4l2") != 0) {
116 #endif
117 if (!strcasecmp(norm, "pal"))
118 return TV_NORM_PAL;
119 else if (!strcasecmp(norm, "ntsc"))
120 return TV_NORM_NTSC;
121 else if (!strcasecmp(norm, "secam"))
122 return TV_NORM_SECAM;
123 else if (!strcasecmp(norm, "palnc"))
124 return TV_NORM_PALNC;
125 else if (!strcasecmp(norm, "palm"))
126 return TV_NORM_PALM;
127 else if (!strcasecmp(norm, "paln"))
128 return TV_NORM_PALN;
129 else if (!strcasecmp(norm, "ntscjp"))
130 return TV_NORM_NTSCJP;
131 else {
132 mp_msg(MSGT_TV, MSGL_WARN, MSGTR_TV_BogusNormParameter, norm, "PAL");
133 return TV_NORM_PAL;
135 #ifdef HAVE_TV_V4L2
136 } else {
137 tvi_functions_t *funcs = tvh->functions;
138 char str[8];
139 strncpy(str, norm, sizeof(str)-1);
140 str[sizeof(str)-1] = '\0';
141 if (funcs->control(tvh->priv, TVI_CONTROL_SPC_GET_NORMID, str) != TVI_CONTROL_TRUE)
143 mp_msg(MSGT_TV, MSGL_WARN, MSGTR_TV_BogusNormParameter, norm,"default");
144 return 0;
146 return *(int *)str;
148 #endif
151 static int open_tv(tvi_handle_t *tvh)
153 int i;
154 tvi_functions_t *funcs = tvh->functions;
155 int tv_fmt_list[] = {
156 IMGFMT_YV12,
157 IMGFMT_I420,
158 IMGFMT_UYVY,
159 IMGFMT_YUY2,
160 IMGFMT_RGB32,
161 IMGFMT_RGB24,
162 IMGFMT_RGB16,
163 IMGFMT_RGB15
166 if (funcs->control(tvh->priv, TVI_CONTROL_IS_VIDEO, 0) != TVI_CONTROL_TRUE)
168 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_NoVideoInputPresent);
169 return 0;
172 if (tvh->tv_param->outfmt == -1)
173 for (i = 0; i < sizeof (tv_fmt_list) / sizeof (*tv_fmt_list); i++)
175 tvh->tv_param->outfmt = tv_fmt_list[i];
176 if (funcs->control (tvh->priv, TVI_CONTROL_VID_SET_FORMAT,
177 &tvh->tv_param->outfmt) == TVI_CONTROL_TRUE)
178 break;
180 else
182 switch(tvh->tv_param->outfmt)
184 case IMGFMT_YV12:
185 case IMGFMT_I420:
186 case IMGFMT_UYVY:
187 case IMGFMT_YUY2:
188 case IMGFMT_RGB32:
189 case IMGFMT_RGB24:
190 case IMGFMT_BGR32:
191 case IMGFMT_BGR24:
192 case IMGFMT_BGR16:
193 case IMGFMT_BGR15:
194 break;
195 default:
196 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_UnknownImageFormat,tvh->tv_param->outfmt);
198 funcs->control(tvh->priv, TVI_CONTROL_VID_SET_FORMAT, &tvh->tv_param->outfmt);
201 /* set some params got from cmdline */
202 funcs->control(tvh->priv, TVI_CONTROL_SPC_SET_INPUT, &tvh->tv_param->input);
204 #ifdef HAVE_TV_V4L2
205 if (!strcmp(tvh->tv_param->driver, "v4l2") && tvh->tv_param->normid >= 0) {
206 mp_msg(MSGT_TV, MSGL_V, MSGTR_TV_SelectedNormId, tvh->tv_param->normid);
207 if (funcs->control(tvh->priv, TVI_CONTROL_TUN_SET_NORM, &tvh->tv_param->normid) != TVI_CONTROL_TRUE) {
208 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_CannotSetNorm);
210 } else {
211 #endif
212 /* select video norm */
213 tvh->norm = norm_from_string(tvh, tvh->tv_param->norm);
215 mp_msg(MSGT_TV, MSGL_V, MSGTR_TV_SelectedNorm, tvh->tv_param->norm);
216 if (funcs->control(tvh->priv, TVI_CONTROL_TUN_SET_NORM, &tvh->norm) != TVI_CONTROL_TRUE) {
217 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_CannotSetNorm);
219 #ifdef HAVE_TV_V4L2
221 #endif
223 #ifdef HAVE_TV_V4L1
224 if ( tvh->tv_param->mjpeg )
226 /* set width to expected value */
227 if (tvh->tv_param->width == -1)
229 tvh->tv_param->width = 704/tvh->tv_param->decimation;
231 if (tvh->tv_param->height == -1)
233 if ( tvh->norm != TV_NORM_NTSC )
234 tvh->tv_param->height = 576/tvh->tv_param->decimation;
235 else
236 tvh->tv_param->height = 480/tvh->tv_param->decimation;
238 mp_msg(MSGT_TV, MSGL_INFO,
239 MSGTR_TV_MJP_WidthHeight, tvh->tv_param->width, tvh->tv_param->height);
241 #endif
243 /* limits on w&h are norm-dependent -- JM */
244 /* set width */
245 if (tvh->tv_param->width != -1)
247 if (funcs->control(tvh->priv, TVI_CONTROL_VID_CHK_WIDTH, &tvh->tv_param->width) == TVI_CONTROL_TRUE)
248 funcs->control(tvh->priv, TVI_CONTROL_VID_SET_WIDTH, &tvh->tv_param->width);
249 else
251 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_UnableToSetWidth, tvh->tv_param->width);
252 funcs->control(tvh->priv, TVI_CONTROL_VID_GET_WIDTH, &tvh->tv_param->width);
256 /* set height */
257 if (tvh->tv_param->height != -1)
259 if (funcs->control(tvh->priv, TVI_CONTROL_VID_CHK_HEIGHT, &tvh->tv_param->height) == TVI_CONTROL_TRUE)
260 funcs->control(tvh->priv, TVI_CONTROL_VID_SET_HEIGHT, &tvh->tv_param->height);
261 else
263 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_UnableToSetHeight, tvh->tv_param->height);
264 funcs->control(tvh->priv, TVI_CONTROL_VID_GET_HEIGHT, &tvh->tv_param->height);
268 if (funcs->control(tvh->priv, TVI_CONTROL_IS_TUNER, 0) != TVI_CONTROL_TRUE)
270 mp_msg(MSGT_TV, MSGL_WARN, MSGTR_TV_NoTuner);
271 goto done;
274 /* select channel list */
275 for (i = 0; chanlists[i].name != NULL; i++)
277 if (!strcasecmp(chanlists[i].name, tvh->tv_param->chanlist))
279 tvh->chanlist = i;
280 tvh->chanlist_s = chanlists[i].list;
281 break;
285 if (tvh->chanlist == -1)
286 mp_msg(MSGT_TV, MSGL_WARN, MSGTR_TV_UnableFindChanlist,
287 tvh->tv_param->chanlist);
288 else
289 mp_msg(MSGT_TV, MSGL_V, MSGTR_TV_SelectedChanlist,
290 chanlists[tvh->chanlist].name, chanlists[tvh->chanlist].count);
292 if (tvh->tv_param->freq && tvh->tv_param->channel)
294 mp_msg(MSGT_TV, MSGL_WARN, MSGTR_TV_ChannelFreqParamConflict);
295 goto done;
298 /* Handle channel names */
299 if (tvh->tv_param->channels) {
300 char** channels = tvh->tv_param->channels;
301 mp_msg(MSGT_TV, MSGL_INFO, MSGTR_TV_ChannelNamesDetected);
302 tv_channel_list = malloc(sizeof(tv_channels_t));
303 tv_channel_list->index=1;
304 tv_channel_list->next=NULL;
305 tv_channel_list->prev=NULL;
306 tv_channel_current = tv_channel_list;
308 while (*channels) {
309 char* tmp = *(channels++);
310 char* sep = strchr(tmp,'-');
311 int i;
312 struct CHANLIST cl;
314 if (!sep) continue; // Wrong syntax, but mplayer should not crash
316 av_strlcpy(tv_channel_current->name, sep + 1,
317 sizeof(tv_channel_current->name));
318 sep[0] = '\0';
319 strncpy(tv_channel_current->number, tmp, 5);
320 tv_channel_current->number[4]='\0';
322 while ((sep=strchr(tv_channel_current->name, '_')))
323 sep[0] = ' ';
325 // if channel number is a number and larger than 1000 threat it as frequency
326 // tmp still contain pointer to null-terminated string with channel number here
327 if (atoi(tmp)>1000){
328 tv_channel_current->freq=atoi(tmp);
329 }else{
330 tv_channel_current->freq = 0;
331 for (i = 0; i < chanlists[tvh->chanlist].count; i++) {
332 cl = tvh->chanlist_s[i];
333 if (!strcasecmp(cl.name, tv_channel_current->number)) {
334 tv_channel_current->freq=cl.freq;
335 break;
339 if (tv_channel_current->freq == 0)
340 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_NoFreqForChannel,
341 tv_channel_current->number, tv_channel_current->name);
342 else {
343 sep = strchr(tv_channel_current->name, '-');
344 if ( !sep ) sep = strchr(tv_channel_current->name, '+');
346 if ( sep ) {
347 i = atoi (sep+1);
348 if ( sep[0] == '+' ) tv_channel_current->freq += i * 100;
349 if ( sep[0] == '-' ) tv_channel_current->freq -= i * 100;
350 sep[0] = '\0';
354 /*mp_msg(MSGT_TV, MSGL_INFO, "-- Detected channel %s - %s (%5.3f)\n",
355 tv_channel_current->number, tv_channel_current->name,
356 (float)tv_channel_current->freq/1000);*/
358 tv_channel_current->next = malloc(sizeof(tv_channels_t));
359 tv_channel_current->next->index = tv_channel_current->index + 1;
360 tv_channel_current->next->prev = tv_channel_current;
361 tv_channel_current->next->next = NULL;
362 tv_channel_current = tv_channel_current->next;
364 if (tv_channel_current->prev)
365 tv_channel_current->prev->next = NULL;
366 free(tv_channel_current);
367 } else
368 tv_channel_last_real = malloc(5);
370 if (tv_channel_list) {
371 int i;
372 int channel = 0;
373 if (tvh->tv_param->channel)
375 if (isdigit(*tvh->tv_param->channel))
376 /* if tvh->tv_param->channel begins with a digit interpret it as a number */
377 channel = atoi(tvh->tv_param->channel);
378 else
380 /* if tvh->tv_param->channel does not begin with a digit
381 set the first channel that contains tvh->tv_param->channel in its name */
383 tv_channel_current = tv_channel_list;
384 while ( tv_channel_current ) {
385 if ( strstr(tv_channel_current->name, tvh->tv_param->channel) )
386 break;
387 tv_channel_current = tv_channel_current->next;
389 if ( !tv_channel_current ) tv_channel_current = tv_channel_list;
392 else
393 channel = 1;
395 if ( channel ) {
396 tv_channel_current = tv_channel_list;
397 for (i = 1; i < channel; i++)
398 if (tv_channel_current->next)
399 tv_channel_current = tv_channel_current->next;
402 mp_msg(MSGT_TV, MSGL_INFO, MSGTR_TV_SelectedChannel3, tv_channel_current->number,
403 tv_channel_current->name, (float)tv_channel_current->freq/1000);
404 tv_set_freq(tvh, (unsigned long)(((float)tv_channel_current->freq/1000)*16));
405 tv_channel_last = tv_channel_current;
406 } else {
407 /* we need to set frequency */
408 if (tvh->tv_param->freq)
410 unsigned long freq = atof(tvh->tv_param->freq)*16;
412 /* set freq in MHz */
413 funcs->control(tvh->priv, TVI_CONTROL_TUN_SET_FREQ, &freq);
415 funcs->control(tvh->priv, TVI_CONTROL_TUN_GET_FREQ, &freq);
416 mp_msg(MSGT_TV, MSGL_V, MSGTR_TV_SelectedFrequency,
417 freq, (float)freq/16);
420 if (tvh->tv_param->channel) {
421 struct CHANLIST cl;
423 mp_msg(MSGT_TV, MSGL_V, MSGTR_TV_RequestedChannel, tvh->tv_param->channel);
424 for (i = 0; i < chanlists[tvh->chanlist].count; i++)
426 cl = tvh->chanlist_s[i];
427 // printf("count%d: name: %s, freq: %d\n",
428 // i, cl.name, cl.freq);
429 if (!strcasecmp(cl.name, tvh->tv_param->channel))
431 strcpy(tv_channel_last_real, cl.name);
432 tvh->channel = i;
433 mp_msg(MSGT_TV, MSGL_INFO, MSGTR_TV_SelectedChannel2,
434 cl.name, (float)cl.freq/1000);
435 tv_set_freq(tvh, (unsigned long)(((float)cl.freq/1000)*16));
436 break;
442 /* grep frequency in chanlist */
444 unsigned long i2;
445 int freq;
447 tv_get_freq(tvh, &i2);
449 freq = (int) (((float)(i2/16))*1000)+250;
451 for (i = 0; i < chanlists[tvh->chanlist].count; i++)
453 if (tvh->chanlist_s[i].freq == freq)
455 tvh->channel = i+1;
456 break;
461 done:
462 /* also start device! */
463 return 1;
466 static tvi_handle_t *tv_begin(tv_param_t* tv_param)
468 int i;
469 tvi_handle_t* h;
470 if(!strcmp(tv_param->driver,"help")){
471 mp_msg(MSGT_TV,MSGL_INFO,MSGTR_TV_AvailableDrivers);
472 for(i=0;tvi_driver_list[i];i++){
473 mp_msg(MSGT_TV,MSGL_INFO," %s\t%s",tvi_driver_list[i]->short_name,tvi_driver_list[i]->name);
474 if(tvi_driver_list[i]->comment)
475 mp_msg(MSGT_TV,MSGL_INFO," (%s)",tvi_driver_list[i]->comment);
476 mp_msg(MSGT_TV,MSGL_INFO,"\n");
478 return NULL;
481 for(i=0;tvi_driver_list[i];i++){
482 if (!strcmp(tvi_driver_list[i]->short_name, tv_param->driver)){
483 h=tvi_driver_list[i]->tvi_init(tv_param);
484 if(!h) return NULL;
486 h->tv_param=tv_param;
487 mp_msg(MSGT_TV, MSGL_INFO, MSGTR_TV_DriverInfo, tvi_driver_list[i]->short_name,
488 tvi_driver_list[i]->name,
489 tvi_driver_list[i]->author,
490 tvi_driver_list[i]->comment?tvi_driver_list[i]->comment:"");
491 return h;
495 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_NoSuchDriver, tv_param->driver);
496 return(NULL);
499 static int tv_uninit(tvi_handle_t *tvh)
501 int res;
502 if(!tvh) return 1;
503 if (!tvh->priv) return 1;
504 res=tvh->functions->uninit(tvh->priv);
505 if(res) tvh->priv=NULL;
506 return res;
509 static demuxer_t* demux_open_tv(demuxer_t *demuxer)
511 tvi_handle_t *tvh;
512 sh_video_t *sh_video;
513 sh_audio_t *sh_audio = NULL;
514 tvi_functions_t *funcs;
516 demuxer->priv=NULL;
517 if(!(tvh=tv_begin(demuxer->stream->priv))) return NULL;
518 if (!tvh->functions->init(tvh->priv)) return NULL;
520 tvh->functions->control(tvh->priv,TVI_CONTROL_VBI_INIT,&(tvh->tv_param->tdevice));
522 if (!open_tv(tvh)){
523 tv_uninit(tvh);
524 return NULL;
526 funcs = tvh->functions;
527 demuxer->priv=tvh;
529 sh_video = new_sh_video(demuxer, 0);
531 /* get IMAGE FORMAT */
532 funcs->control(tvh->priv, TVI_CONTROL_VID_GET_FORMAT, &sh_video->format);
533 // if (IMGFMT_IS_RGB(sh_video->format) || IMGFMT_IS_BGR(sh_video->format))
534 // sh_video->format = 0x0;
536 /* set FPS and FRAMETIME */
538 if(!sh_video->fps)
540 float tmp;
541 if (funcs->control(tvh->priv, TVI_CONTROL_VID_GET_FPS, &tmp) != TVI_CONTROL_TRUE)
542 sh_video->fps = 25.0f; /* on PAL */
543 else sh_video->fps = tmp;
546 if (tvh->tv_param->fps != -1.0f)
547 sh_video->fps = tvh->tv_param->fps;
549 sh_video->frametime = 1.0f/sh_video->fps;
551 /* If playback only mode, go to immediate mode, fail silently */
552 if(tvh->tv_param->immediate == 1)
554 funcs->control(tvh->priv, TVI_CONTROL_IMMEDIATE, 0);
555 tvh->tv_param->noaudio = 1;
558 /* disable TV audio if -nosound is present */
559 if (!demuxer->audio || demuxer->audio->id == -2) {
560 tvh->tv_param->noaudio = 1;
563 /* set width */
564 funcs->control(tvh->priv, TVI_CONTROL_VID_GET_WIDTH, &sh_video->disp_w);
566 /* set height */
567 funcs->control(tvh->priv, TVI_CONTROL_VID_GET_HEIGHT, &sh_video->disp_h);
569 demuxer->video->sh = sh_video;
570 sh_video->ds = demuxer->video;
571 demuxer->video->id = 0;
572 demuxer->seekable = 0;
574 /* here comes audio init */
575 if (tvh->tv_param->noaudio == 0 && funcs->control(tvh->priv, TVI_CONTROL_IS_AUDIO, 0) == TVI_CONTROL_TRUE)
577 int audio_format;
578 int sh_audio_format;
579 char buf[128];
581 /* yeah, audio is present */
583 funcs->control(tvh->priv, TVI_CONTROL_AUD_SET_SAMPLERATE,
584 &tvh->tv_param->audiorate);
586 if (funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_FORMAT, &audio_format) != TVI_CONTROL_TRUE)
587 goto no_audio;
589 switch(audio_format)
591 case AF_FORMAT_U8:
592 case AF_FORMAT_S8:
593 case AF_FORMAT_U16_LE:
594 case AF_FORMAT_U16_BE:
595 case AF_FORMAT_S16_LE:
596 case AF_FORMAT_S16_BE:
597 case AF_FORMAT_S32_LE:
598 case AF_FORMAT_S32_BE:
599 sh_audio_format = 0x1; /* PCM */
600 break;
601 case AF_FORMAT_IMA_ADPCM:
602 case AF_FORMAT_MU_LAW:
603 case AF_FORMAT_A_LAW:
604 case AF_FORMAT_MPEG2:
605 case AF_FORMAT_AC3:
606 default:
607 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_UnsupportedAudioType,
608 af_fmt2str(audio_format, buf, 128), audio_format);
609 goto no_audio;
612 sh_audio = new_sh_audio(demuxer, 0);
614 funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_SAMPLERATE,
615 &sh_audio->samplerate);
616 funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_SAMPLESIZE,
617 &sh_audio->samplesize);
618 funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_CHANNELS,
619 &sh_audio->channels);
621 sh_audio->format = sh_audio_format;
622 sh_audio->sample_format = audio_format;
624 sh_audio->i_bps = sh_audio->o_bps =
625 sh_audio->samplerate * sh_audio->samplesize *
626 sh_audio->channels;
628 // emulate WF for win32 codecs:
629 sh_audio->wf = malloc(sizeof(WAVEFORMATEX));
630 sh_audio->wf->wFormatTag = sh_audio->format;
631 sh_audio->wf->nChannels = sh_audio->channels;
632 sh_audio->wf->wBitsPerSample = sh_audio->samplesize * 8;
633 sh_audio->wf->nSamplesPerSec = sh_audio->samplerate;
634 sh_audio->wf->nBlockAlign = sh_audio->samplesize * sh_audio->channels;
635 sh_audio->wf->nAvgBytesPerSec = sh_audio->i_bps;
637 mp_msg(MSGT_DECVIDEO, MSGL_V, MSGTR_TV_AudioFormat,
638 sh_audio->wf->nChannels, sh_audio->wf->wBitsPerSample,
639 sh_audio->wf->nSamplesPerSec);
641 demuxer->audio->sh = sh_audio;
642 sh_audio->ds = demuxer->audio;
643 demuxer->audio->id = 0;
645 no_audio:
647 if(!(funcs->start(tvh->priv))){
648 // start failed :(
649 tv_uninit(tvh);
650 return NULL;
653 /* set color eq */
654 tv_set_color_options(tvh, TV_COLOR_BRIGHTNESS, tvh->tv_param->brightness);
655 tv_set_color_options(tvh, TV_COLOR_HUE, tvh->tv_param->hue);
656 tv_set_color_options(tvh, TV_COLOR_SATURATION, tvh->tv_param->saturation);
657 tv_set_color_options(tvh, TV_COLOR_CONTRAST, tvh->tv_param->contrast);
659 return demuxer;
662 static void demux_close_tv(demuxer_t *demuxer)
664 tvi_handle_t *tvh=(tvi_handle_t*)(demuxer->priv);
665 if (!tvh) return;
666 tvh->functions->uninit(tvh->priv);
667 demuxer->priv=NULL;
670 /* utilities for mplayer (not mencoder!!) */
671 int tv_set_color_options(tvi_handle_t *tvh, int opt, int value)
673 tvi_functions_t *funcs = tvh->functions;
675 switch(opt)
677 case TV_COLOR_BRIGHTNESS:
678 return funcs->control(tvh->priv, TVI_CONTROL_VID_SET_BRIGHTNESS, &value);
679 case TV_COLOR_HUE:
680 return funcs->control(tvh->priv, TVI_CONTROL_VID_SET_HUE, &value);
681 case TV_COLOR_SATURATION:
682 return funcs->control(tvh->priv, TVI_CONTROL_VID_SET_SATURATION, &value);
683 case TV_COLOR_CONTRAST:
684 return funcs->control(tvh->priv, TVI_CONTROL_VID_SET_CONTRAST, &value);
685 default:
686 mp_msg(MSGT_TV, MSGL_WARN, MSGTR_TV_UnknownColorOption, opt);
689 return(TVI_CONTROL_UNKNOWN);
692 int tv_get_color_options(tvi_handle_t *tvh, int opt, int* value)
694 tvi_functions_t *funcs = tvh->functions;
696 switch(opt)
698 case TV_COLOR_BRIGHTNESS:
699 return funcs->control(tvh->priv, TVI_CONTROL_VID_GET_BRIGHTNESS, value);
700 case TV_COLOR_HUE:
701 return funcs->control(tvh->priv, TVI_CONTROL_VID_GET_HUE, value);
702 case TV_COLOR_SATURATION:
703 return funcs->control(tvh->priv, TVI_CONTROL_VID_GET_SATURATION, value);
704 case TV_COLOR_CONTRAST:
705 return funcs->control(tvh->priv, TVI_CONTROL_VID_GET_CONTRAST, value);
706 default:
707 mp_msg(MSGT_TV, MSGL_WARN, MSGTR_TV_UnknownColorOption, opt);
710 return(TVI_CONTROL_UNKNOWN);
713 int tv_get_freq(tvi_handle_t *tvh, unsigned long *freq)
715 if (tvh->functions->control(tvh->priv, TVI_CONTROL_IS_TUNER, 0) == TVI_CONTROL_TRUE)
717 tvh->functions->control(tvh->priv, TVI_CONTROL_TUN_GET_FREQ, freq);
718 mp_msg(MSGT_TV, MSGL_V, MSGTR_TV_CurrentFrequency,
719 *freq, (float)*freq/16);
721 return(1);
724 int tv_set_freq(tvi_handle_t *tvh, unsigned long freq)
726 if (tvh->functions->control(tvh->priv, TVI_CONTROL_IS_TUNER, 0) == TVI_CONTROL_TRUE)
728 // unsigned long freq = atof(tvh->tv_param->freq)*16;
730 /* set freq in MHz */
731 tvh->functions->control(tvh->priv, TVI_CONTROL_TUN_SET_FREQ, &freq);
733 tvh->functions->control(tvh->priv, TVI_CONTROL_TUN_GET_FREQ, &freq);
734 mp_msg(MSGT_TV, MSGL_V, MSGTR_TV_CurrentFrequency,
735 freq, (float)freq/16);
737 tvh->functions->control(tvh->priv,TV_VBI_CONTROL_RESET,tvh->tv_param);
738 return(1);
741 /*****************************************************************
742 * \brief tune current frequency by step_interval value
743 * \parameter step_interval increment value in 1/16 MHz
744 * \note frequency is rounded to 1/16 MHz value
745 * \return 1
748 int tv_step_freq(tvi_handle_t* tvh, float step_interval){
749 unsigned long frequency;
751 tv_get_freq(tvh,&frequency);
752 frequency+=step_interval;
753 return tv_set_freq(tvh,frequency);
756 int tv_step_channel_real(tvi_handle_t *tvh, int direction)
758 struct CHANLIST cl;
760 if (direction == TV_CHANNEL_LOWER)
762 if (tvh->channel-1 >= 0)
764 strcpy(tv_channel_last_real, tvh->chanlist_s[tvh->channel].name);
765 cl = tvh->chanlist_s[--tvh->channel];
766 mp_msg(MSGT_TV, MSGL_INFO, MSGTR_TV_SelectedChannel2,
767 cl.name, (float)cl.freq/1000);
768 tv_set_freq(tvh, (unsigned long)(((float)cl.freq/1000)*16));
772 if (direction == TV_CHANNEL_HIGHER)
774 if (tvh->channel+1 < chanlists[tvh->chanlist].count)
776 strcpy(tv_channel_last_real, tvh->chanlist_s[tvh->channel].name);
777 cl = tvh->chanlist_s[++tvh->channel];
778 mp_msg(MSGT_TV, MSGL_INFO, MSGTR_TV_SelectedChannel2,
779 cl.name, (float)cl.freq/1000);
780 tv_set_freq(tvh, (unsigned long)(((float)cl.freq/1000)*16));
783 return(1);
786 int tv_step_channel(tvi_handle_t *tvh, int direction) {
787 if (tv_channel_list) {
788 if (direction == TV_CHANNEL_HIGHER) {
789 tv_channel_last = tv_channel_current;
790 if (tv_channel_current->next)
791 tv_channel_current = tv_channel_current->next;
792 else
793 tv_channel_current = tv_channel_list;
794 tv_set_freq(tvh, (unsigned long)(((float)tv_channel_current->freq/1000)*16));
795 mp_msg(MSGT_TV, MSGL_INFO, MSGTR_TV_SelectedChannel3,
796 tv_channel_current->number, tv_channel_current->name, (float)tv_channel_current->freq/1000);
798 if (direction == TV_CHANNEL_LOWER) {
799 tv_channel_last = tv_channel_current;
800 if (tv_channel_current->prev)
801 tv_channel_current = tv_channel_current->prev;
802 else
803 while (tv_channel_current->next)
804 tv_channel_current = tv_channel_current->next;
805 tv_set_freq(tvh, (unsigned long)(((float)tv_channel_current->freq/1000)*16));
806 mp_msg(MSGT_TV, MSGL_INFO, MSGTR_TV_SelectedChannel3,
807 tv_channel_current->number, tv_channel_current->name, (float)tv_channel_current->freq/1000);
809 } else tv_step_channel_real(tvh, direction);
810 return(1);
813 int tv_set_channel_real(tvi_handle_t *tvh, char *channel) {
814 int i;
815 struct CHANLIST cl;
817 strcpy(tv_channel_last_real, tvh->chanlist_s[tvh->channel].name);
818 for (i = 0; i < chanlists[tvh->chanlist].count; i++)
820 cl = tvh->chanlist_s[i];
821 // printf("count%d: name: %s, freq: %d\n",
822 // i, cl.name, cl.freq);
823 if (!strcasecmp(cl.name, channel))
825 tvh->channel = i;
826 mp_msg(MSGT_TV, MSGL_INFO, MSGTR_TV_SelectedChannel2,
827 cl.name, (float)cl.freq/1000);
828 tv_set_freq(tvh, (unsigned long)(((float)cl.freq/1000)*16));
829 break;
832 return(1);
835 int tv_set_channel(tvi_handle_t *tvh, char *channel) {
836 int i, channel_int;
838 if (tv_channel_list) {
839 tv_channel_last = tv_channel_current;
840 channel_int = atoi(channel);
841 tv_channel_current = tv_channel_list;
842 for (i = 1; i < channel_int; i++)
843 if (tv_channel_current->next)
844 tv_channel_current = tv_channel_current->next;
845 mp_msg(MSGT_TV, MSGL_INFO, MSGTR_TV_SelectedChannel3, tv_channel_current->number,
846 tv_channel_current->name, (float)tv_channel_current->freq/1000);
847 tv_set_freq(tvh, (unsigned long)(((float)tv_channel_current->freq/1000)*16));
848 } else tv_set_channel_real(tvh, channel);
849 return(1);
852 int tv_last_channel(tvi_handle_t *tvh) {
854 if (tv_channel_list) {
855 tv_channels_t *tmp;
857 tmp = tv_channel_last;
858 tv_channel_last = tv_channel_current;
859 tv_channel_current = tmp;
861 mp_msg(MSGT_TV, MSGL_INFO, MSGTR_TV_SelectedChannel3, tv_channel_current->number,
862 tv_channel_current->name, (float)tv_channel_current->freq/1000);
863 tv_set_freq(tvh, (unsigned long)(((float)tv_channel_current->freq/1000)*16));
864 } else {
865 int i;
866 struct CHANLIST cl;
868 for (i = 0; i < chanlists[tvh->chanlist].count; i++)
870 cl = tvh->chanlist_s[i];
871 if (!strcasecmp(cl.name, tv_channel_last_real))
873 strcpy(tv_channel_last_real, tvh->chanlist_s[tvh->channel].name);
874 tvh->channel = i;
875 mp_msg(MSGT_TV, MSGL_INFO, MSGTR_TV_SelectedChannel2,
876 cl.name, (float)cl.freq/1000);
877 tv_set_freq(tvh, (unsigned long)(((float)cl.freq/1000)*16));
878 break;
882 return(1);
885 int tv_step_norm(tvi_handle_t *tvh)
887 tvh->norm++;
888 if (tvh->functions->control(tvh->priv, TVI_CONTROL_TUN_SET_NORM,
889 &tvh->norm) != TVI_CONTROL_TRUE) {
890 tvh->norm = 0;
891 if (tvh->functions->control(tvh->priv, TVI_CONTROL_TUN_SET_NORM,
892 &tvh->norm) != TVI_CONTROL_TRUE) {
893 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_CannotSetNorm);
894 return 0;
897 tvh->functions->control(tvh->priv,TV_VBI_CONTROL_RESET,tvh->tv_param);
898 return(1);
901 int tv_step_chanlist(tvi_handle_t *tvh)
903 return(1);
906 int tv_set_norm(tvi_handle_t *tvh, char* norm)
908 tvh->norm = norm_from_string(tvh, norm);
910 mp_msg(MSGT_TV, MSGL_V, MSGTR_TV_SelectedNorm, tvh->tv_param->norm);
911 if (tvh->functions->control(tvh->priv, TVI_CONTROL_TUN_SET_NORM, &tvh->norm) != TVI_CONTROL_TRUE) {
912 mp_msg(MSGT_TV, MSGL_ERR, MSGTR_TV_CannotSetNorm);
913 return 0;
915 tvh->functions->control(tvh->priv,TV_VBI_CONTROL_RESET,tvh->tv_param);
916 return(1);
919 demuxer_desc_t demuxer_desc_tv = {
920 "Tv card demuxer",
921 "tv",
922 "TV",
923 "Alex Beregszaszi, Charles R. Henrich",
924 "?",
925 DEMUXER_TYPE_TV,
926 0, // no autodetect
927 NULL,
928 demux_tv_fill_buffer,
929 demux_open_tv,
930 demux_close_tv,
931 NULL,
932 NULL