Logo Search packages:      
Sourcecode: xawtv version File versions  Download package

scantv.c

/*
 * (c) 2000-2002 Gerd Knorr <kraxel@goldbach.in-berlin.de>
 *
 */
#include "config.h"

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <math.h>
#include <time.h>
#include <fcntl.h>
#include <pthread.h>

/* xawtv */
#include "channel.h"
#include "frequencies.h"
#include "grab-ng.h"
#include "commands.h"

#include "vbi-data.h"

int debug = 0;
int have_dga = 0;

int timeout = 3;
char *tvname;

/*---------------------------------------------------------------------*/

static void
grabber_init(void)
{
    drv = ng_vid_open(ng_dev.video,NULL,NULL,0,&h_drv);
    if (NULL == drv) {
      fprintf(stderr,"no grabber device available\n");
      exit(1);
    }
    f_drv = drv->capabilities(h_drv);
    add_attrs(drv->list_attrs(h_drv));
}

static void
event(struct vbi_event *ev, void *user)
{
    switch (ev->type) {
    case VBI_EVENT_NETWORK:
      if (NULL != tvname)
          free(tvname);
      if (strlen(ev->ev.network.name) > 0)
          tvname = strdup(ev->ev.network.name);
      break;
    }
}

static char*
get_vbi_name(struct vbi_state *vbi)
{
    int start;

    vbi_hasdata(vbi);
    if (NULL != tvname)
      free(tvname);
    tvname = NULL;
    start = time(NULL);
    for (;;) {
      vbi_hasdata(vbi);
        if (time(NULL) > start+timeout)
            break;
        if (tvname)
            break;
    }
    return tvname;
}

static int
menu(char *intro, struct STRTAB *tab, char *opt)
{
    int i,ret;
    char line[80];

    if (NULL != opt) {
      /* cmd line option -- non-interactive mode */
      for (i = 0; tab[i].str != NULL; i++)
          if (0 == strcasecmp(tab[i].str,opt))
            return tab[i].nr;
      fprintf(stderr,"%s: not found\n",opt);
      exit(1);
    }

    fprintf(stderr,"\n%s\n",intro);
    for (i = 0; tab[i].str != NULL; i++)
      fprintf(stderr,"  %2ld: %s\n",tab[i].nr,tab[i].str);

    for (;;) {
      fprintf(stderr,"nr ? ");
      fgets(line,79,stdin);
      ret = atoi(line);
      for (i = 0; tab[i].str != NULL; i++)
          if (ret == tab[i].nr)
            return ret;
      fprintf(stderr,"invalid choice\n");
    }
}

static void
usage(FILE *out, char *prog, char *outfile)
{
    fprintf(out,
          "This tool scan for tv stations and writes "
          "a initial xawtv config file.\n"
          "usage: %s [ options ]\n"
          "options:\n"
          "   -h           print this text\n"
          "   -o outfile   set output file.        [%s]\n"
          "   -n norm      set tv norm.\n"
          "   -f table     set frequency table.\n"
          "   -c device    set video device file.  [%s]\n"
          "   -C device    set vbi device file.    [%s]\n"
          "   -s           skip channel scan\n"
          "   -a           full scan (all frequencies, not just\n"
          "                the ones from the frequency table)\n",
          prog,
          outfile ? outfile : "stdout",
          ng_dev.video, ng_dev.vbi);
}

int
main(int argc, char **argv)
{
    struct vbi_state *vbi;
    struct ng_attribute *attr;
    int c,fi,on,tuned,i,j,scan=1,fullscan=0;
    unsigned int f,f1,f2,fc;
    char *name,dummy[32];
    char *tvnorm  = NULL;
    char *freqtab = NULL;
    char *outfile = NULL;
    FILE *conf = stdout;

    /* parse options */
    ng_init();
    for (;;) {
      if (-1 == (c = getopt(argc, argv, "hsadn:f:o:c:C:")))
          break;
      switch (c) {
      case 'd':
          debug++;
          break;
      case 's':
          scan=0;
          break;
      case 'a':
          fullscan=1;
          break;
      case 'n':
          tvnorm = optarg;
          break;
      case 'f':
          freqtab = optarg;
          break;
      case 'o':
          outfile = optarg;
          break;
      case 'c':
          ng_dev.video = optarg;
          break;
      case 'C':
          ng_dev.vbi = optarg;
          break;
      case 'h':
          usage(stdout,argv[0],outfile);
          exit(0);
      default:
          usage(stderr,argv[0],outfile);
          exit(1);
      }
    }

    if (outfile) {
      if (NULL == (conf = fopen(outfile,"w"))) {
          fprintf(stderr,"open %s: %s\n",argv[1],strerror(errno));
          exit(1);
      }
    }

    /* video */
    if (NULL == drv)
      grabber_init();
    if (NULL == drv) {
      fprintf(stderr,"can't open video device\n");
      exit(1);
    }

    attr_init();
    audio_init();
    freq_init();

    /* ask the user some questions ... */
    attr = ng_attr_byid(attrs,ATTR_ID_NORM);
    i = menu("please select your TV norm",attr->choices,tvnorm);
    j = menu("please select a frequency table",chanlist_names,freqtab);

    fprintf(conf,"[global]\n");
    fprintf(conf,"freqtab = %s\n",chanlist_names[j].str);
    fprintf(conf,"\n");
    fprintf(conf,"[defaults]\n");
    fprintf(conf,"input = Television\n");
    fprintf(conf,"norm = %s\n",ng_attr_getstr(attr,i));
    fprintf(conf,"\n");
    fflush(conf);
    if (!scan)
      exit(0);

    if (!(f_drv & CAN_TUNE)) {
      fprintf(stderr,"device has no tuner, exiting\n");
      exit(0);
    }
    set_defaults();
    do_va_cmd(2,"setinput","television");
    do_va_cmd(2,"setnorm",ng_attr_getstr(attr,i));
    do_va_cmd(2,"setfreqtab",chanlist_names[j].str);

    /* vbi */
    vbi = vbi_open(ng_dev.vbi,debug,0);
    if (NULL == vbi) {
      fprintf(stderr,"open %s: %s\n",ng_dev.vbi,strerror(errno));
      exit(1);
    }
    vbi_event_handler_add(vbi->dec,~0,event,vbi);
    
    if (!fullscan) {
      /* scan channels */
      fprintf(stderr,"\nscanning channel list %s...\n",
            chanlist_names[j].str);
      for (i = 0; i < chancount; i++) {
          fprintf(stderr,"%-4s (%6.2f MHz): ",chanlist[i].name,
                (float)chanlist[i].freq/1000);
          do_va_cmd(2,"setchannel",chanlist[i].name);
          usleep(200000); /* 0.2 sec */
          if (0 == drv->is_tuned(h_drv)) {
            fprintf(stderr,"no station\n");
            continue;
          }
          name = get_vbi_name(vbi);
          fprintf(stderr, "%s\n", name ? name : "???");
          if (NULL == name) {
            sprintf(dummy,"unknown (%s)",chanlist[i].name);
            name = dummy;
          }
          fprintf(conf,"[%s]\nchannel = %s\n\n",name,chanlist[i].name);
          fflush(conf);
      }
    } else {
      /* scan freqnencies */
      fprintf(stderr,"\nscanning freqencies...\n");
      on = 0;
      fc = 0;
      f1 = 0;
      f2 = 0;
      fi = -1;
      for (f = 44*16; f <= 958*16; f += 4) {
          for (i = 0; i < chancount; i++)
            if (chanlist[i].freq * 16 == f * 1000)
                break;
          fprintf(stderr,"?? %6.2f MHz (%-4s): ",f/16.0,
                (i == chancount) ? "-" : chanlist[i].name);
          drv->setfreq(h_drv,f);
          usleep(200000); /* 0.2 sec */
          tuned = drv->is_tuned(h_drv);

          /* state machine */
          if (0 == on && 0 == tuned) {
            fprintf(stderr,"|   no\n");
            continue;
          }
          if (0 == on && 0 != tuned) {
            fprintf(stderr," \\  raise\n");
            f1 = f;
            if (i != chancount) {
                fi = i;
                fc = f;
            }
            on = 1;
            continue;
          }
          if (0 != on && 0 != tuned) {
            fprintf(stderr,"  | yes\n");
            if (i != chancount) {
                fi = i;
                fc = f;
            }
            continue;
          }
          /* if (on != 0 && 0 == tuned)  --  found one, read name from vbi */
          fprintf(stderr," /  fall\n");
          f2 = f;
          if (0 == fc)
            fc = (f1+f2)/2;

          fprintf(stderr,"=> %6.2f MHz (%-4s): ", fc/16.0,
                (-1 != fi) ? chanlist[fi].name : "-");
          drv->setfreq(h_drv,fc);
          
          name = get_vbi_name(vbi);
          fprintf(stderr,"%s\n",name ? name : "???");
          if (NULL == name) {
            if (-1 == fi)
                sprintf(dummy,"unknown (%s)",chanlist[fi].name);
            else
                sprintf(dummy,"unknown (%.2f)",fc/16.0);
            name = dummy;
          }
          if (-1 != fi) {
            if (NULL == name) {
                sprintf(dummy,"unknown (%s)",chanlist[fi].name);
                name = dummy;
            }
            fprintf(conf,"[%s]\nchannel = %s\n\n",name,chanlist[fi].name);
          } else {
            if (NULL == name) {
                sprintf(dummy,"unknown (%.3f)", fc/16.0);
                name = dummy;
            }
            fprintf(conf,"[%s]\nfreq = %.3f\n\n", name, fc/16.0);
          }
          fflush(conf);

          on = 0;
          fc = 0;
          f1 = 0;
          f2 = 0;
          fi = -1;
      }
    }

    /* cleanup */
    audio_off();
    drv->close(h_drv);

    exit(0);
}

Generated by  Doxygen 1.6.0   Back to index