#define _FILE_OFFSET_BITS 64
#define _LARGEFILE_SOURCE 1
#define _LARGEFILE64_SOURCE 1
 
#define DVB_BUF_SIZE    (4096 * 8 * 188)
 
#define BUFLEN (188 * 512)
 
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <signal.h>
#include <argp.h>
#include <sys/time.h>
#include <time.h>
 
#ifdef ENABLE_NLS
# define _(string) gettext(string)
# include "gettext.h"
# include <locale.h>
# include <langinfo.h>
# include <iconv.h>
#else
# define _(string) string
#endif
 
# define N_(string) string
 
#include <linux/dvb/dmx.h>
 
#define CHANNEL_FILE    "channels.conf"
#define PROGRAM_NAME    "dvbv5-zap"
 
 
#ifndef O_LARGEFILE
#  define O_LARGEFILE 0
#endif
 
 
const int NANO_SECONDS_IN_SEC = 1000000000;
 
const char *argp_program_version = PROGRAM_NAME " version " V4L_UTILS_VERSION;
const char *argp_program_bug_address = "Mauro Carvalho Chehab <mchehab@kernel.org>";
 
struct arguments {
        char *confname, *lnb_name, *output, *demux_dev, *dvr_dev, *dvr_fname;
        char *filename, *dvr_pipe;
        unsigned adapter, frontend, demux, get_detected, get_nit;
        int lna, lnb, sat_number;
        unsigned diseqc_wait, silent, verbose, frontend_only, freq_bpf;
        unsigned timeout, dvr, rec_psi, exit_after_tuning;
        unsigned n_apid, n_vpid, extra_pids, all_pids;
        unsigned traffic_monitor, low_traffic, non_human, port;
        char *search, *server;
        const char *cc;
 
        
        unsigned n_status_lines;
};
 
static const struct argp_option options[] = {
        {"adapter",     'a', N_("adapter#"),            0, N_("use given adapter (default 0)"), 0},
        {"audio_pid",   'A', N_("audio_pid#"),          0, N_("audio pid program to use (default 0)"), 0},
        {"channels",    'c', N_("file"),                0, N_("read channels list from 'file'"), 0},
        {"extra-pids",  'E', NULL,                      0, N_("output all channel pids"), 0 },
        {"demux",       'd', N_("demux#"),              0, N_("use given demux (default 0)"), 0},
        {"frontend",    'f', N_("frontend#"),           0, N_("use given frontend (default 0)"), 0},
        {"input-format", 'I',   N_("format"),           0, N_("Input format: ZAP, CHANNEL, DVBV5 (default: DVBV5)"), 0},
        {"lna",         'w', N_("LNA (0, 1, -1)"),      0, N_("enable/disable/auto LNA power"), 0},
        {"lnbf",        'l', N_("LNBf_type"),           0, N_("type of LNBf to use. 'help' lists the available ones"), 0},
        {"search",      'L', N_("string"),              0, N_("search/look for a string inside the traffic"), 0},
        {"monitor",     'm', NULL,                      0, N_("monitors the DVB traffic"), 0},
        {"output",      'o', N_("file"),                0, N_("output filename (use -o - for stdout)"), 0},
        {"pat",         'p', NULL,                      0, N_("add pat and pmt to TS recording (implies -r)"), 0},
        {"all-pids",    'P', NULL,                      0, N_("don't filter any pids. Instead, outputs all of them"), 0 },
        {"record",      'r', NULL,                      0, N_("set up /dev/dvb/adapterX/dvr0 for TS recording"), 0},
        {"silence",     's', NULL,                      0, N_("increases silence (can be used more than once)"), 0},
        {"sat_number",  'S', N_("satellite_number"),    0, N_("satellite number. If not specified, disable DISEqC"), 0},
        {"timeout",     't', N_("seconds"),             0, N_("timeout for zapping and for recording"), 0},
        {"freq_bpf",    'U', N_("frequency"),           0, N_("SCR/Unicable band-pass filter frequency to use, in kHz"), 0},
        {"verbose",     'v', NULL,                      0, N_("verbose debug messages (can be used more than once)"), 0},
        {"video_pid",   'V', N_("video_pid#"),          0, N_("video pid program to use (default 0)"), 0},
        {"wait",        'W', N_("time"),                0, N_("adds additional wait time for DISEqC command completion"), 0},
        {"exit",        'x', NULL,                      0, N_("exit after tuning"), 0},
        {"low_traffic", 'X', N_("packets_per_sec"),     0, N_("sets DVB low traffic threshold. PIDs with less than this amount of packets per second will be ignored. Default: 1 packet per second"), 0},
        {"cc",          'C', N_("country_code"),        0, N_("Set the default country to be used (in ISO 3166-1 two letter code)"), 0},
        {"non-numan",   'N', NULL,                      0, N_("Non-human formatted stats (useful for scripts)"), 0},
        {"server",      'H', N_("SERVER"),              0, N_("dvbv5-daemon host IP address"), 0},
        {"tcp-port",    'T', N_("PORT"),                0, N_("dvbv5-daemon host tcp port"), 0},
        {"dvr-pipe",    'D', N_("PIPE"),                0, N_("Named pipe for DVR output, when using remote access (by default: /tmp/dvr-pipe)"), 0},
        {"help",        '?', 0,                         0, N_("Give this help list"), -1},
        {"usage",       -3,  0,                         0, N_("Give a short usage message")},
        {"version",     -4,  0,                         0, N_("Print program version"), -1},
        { 0, 0, 0, 0, 0, 0 }
};
 
static int timeout_flag = 0;
 
#define ERROR(x...)                                                     \
        do {                                                            \
                fprintf(stderr, _("ERROR: "));                             \
                fprintf(stderr, x);                                     \
                fprintf(stderr, "\n");                                 \
        } while (0)
 
#define PERROR(x...)                                                    \
        do {                                                            \
                fprintf(stderr, _("ERROR: "));                             \
                fprintf(stderr, x);                                     \
                fprintf(stderr, " (%s)\n", strerror(errno));            \
        } while (0)
 
#define monitor_log(msg, args...)                                               \
        do {                                                                    \
                struct timespec __now = { 0 };                                  \
                float __diff;                                                   \
                                                                                \
                clock_gettime(CLOCK_MONOTONIC, &__now);                         \
                __diff = __now.tv_sec * 1.                                      \
                         + __now.tv_nsec *1. / NANO_SECONDS_IN_SEC;             \
                fprintf(stderr, msg, __diff, ##args);                           \
        } while (0)
 
 
static int parse(struct arguments *args,
                 const char *channel,
{
        int i;
        uint32_t sys;
 
        *out_file = NULL;
        *out_entry = NULL;
 
        
        case SYS_DVBT:
        case SYS_DVBS:
        case SYS_DVBC_ANNEX_A:
        case SYS_ATSC:
                break;
        case SYS_DVBC_ANNEX_C:
                sys = SYS_DVBC_ANNEX_A;
                break;
        case SYS_DVBC_ANNEX_B:
                sys = SYS_ATSC;
                break;
        case SYS_ISDBT:
        case SYS_DTMB:
                sys = SYS_DVBT;
                break;
        default:
                sys = SYS_UNDEFINED;
                break;
        }
                                    args->input_format);
                return -2;
 
                        break;
                        break;
        }
        
        if (!entry) {
                                break;
                }
        }
 
        
        if (!entry && (!args->dvr && !args->rec_psi)) {
                if (freq) {
                                if (f == freq)
                                        break;
                        }
 
                }
        }
 
        if (!entry) {
                ERROR("Can't find channel");
                return -3;
        }
 
        
        if (entry->
lnb && !parms->
lnb) {
 
                        ERROR(
"unknown LNB %s\n", entry->
lnb);
                        return -1;
                }
        }
 
 
                int i, type = -1;
                                if (i)
                                        fprintf(stderr, "\n");
                                fprintf(stderr, _("service has pid type %02x: "), type);
                        }
                }
                fprintf(stderr, "\n");
        }
 
        
 
        
        for (i = 0; i < entry->
n_props; i++) {
 
                uint32_t data = entry->
props[i].u.data;
                
                if (entry->
props[i].cmd == DTV_DELIVERY_SYSTEM)
 
                        continue;
                        if (entry->
props[i].cmd == DTV_CODE_RATE_HP) {
 
                                                  data);
                                                  data);
                                                  data);
                        } 
else if (entry->
props[i].cmd == DTV_MODULATION) {
                                                  DTV_ISDBT_LAYERA_MODULATION,
                                                  data);
                                                  DTV_ISDBT_LAYERB_MODULATION,
                                                  data);
                                                  DTV_ISDBT_LAYERC_MODULATION,
                                                  data);
                        }
                }
                    entry->
props[i].cmd == DTV_MODULATION) {
                        if (data != VSB_8 && data != VSB_16)
                                                  DTV_DELIVERY_SYSTEM,
                                                  SYS_DVBC_ANNEX_B);
                }
        }
 
        *out_entry = entry;
        return 0;
}
 
static int setup_frontend(struct arguments *args,
{
        int rc;
        uint32_t freq;
 
        if (args->silent < 2) {
                if (rc < 0) {
                        ERROR("can't get the frequency");
                        return -1;
                }
                fprintf(stderr, _("tuning to %i Hz\n"), freq);
        }
 
        if (rc < 0) {
                ERROR("dvb_fe_set_parms failed");
                return -1;
        }
 
        return 0;
}
 
static void do_timeout(int x)
{
        (void)x;
 
        if (timeout_flag == 0) {
                timeout_flag = 1;
                alarm(2);
                signal(SIGALRM, do_timeout);
        } else {
                
                fprintf(stderr, "Forcing program stop due to timeout or terminate signal\n");
                exit(1);
        }
}
 
{
        int rc;
        fe_status_t status;
        uint32_t snr = 0, _signal = 0, quality = 0;
        uint32_t ber = 0, per = 0, pre_ber = 0, uncorrected_blocks = 0;
 
        if (rc < 0) {
                PERROR("dvb_fe_get_stats failed");
                return -1;
        }
 
 
        fprintf(fd,"status %02x | quality %02x | signal %04x | snr %04x | ber %08x | unc %08x | pre_ber %08x | per %08x | ",
                status, quality, _signal, snr, ber, uncorrected_blocks, pre_ber, per);
 
        if (status & FE_HAS_LOCK)
                fprintf(fd, "FE_HAS_LOCK");
 
        fprintf(fd, "\n");
        fflush(fd);
 
        return 0;
}
 
static int print_frontend_stats(FILE *fd,
                                struct arguments *args,
{
        char buf[512], *p;
        int rc, i, len, show;
        uint32_t status = 0;
 
        if (args->non_human)
                return print_non_human_stats(fd, parms);
 
        
        if (isatty(fileno(fd)) && args->n_status_lines)
                fprintf(fd, "\r\x1b[%dA\x1b[J", args->n_status_lines);
 
        args->n_status_lines = 0;
 
        if (rc) {
                ERROR("dvb_fe_get_stats failed");
                return -1;
        }
 
        p = buf;
        len = sizeof(buf);
 
        for (i = 0; i < MAX_DTV_STATS; i++) {
                show = 1;
 
                                     i, &p, &len, &show);
 
                                     i, &p, &len, &show);
 
                                     i, &p, &len, &show);
 
                                     i,  &p, &len, &show);
 
                                     i,  &p, &len, &show);
 
                                     i,  &p, &len, &show);
 
                                     i,  &p, &len, &show);
 
                if (p != buf) {
                        if (args->n_status_lines)
                                fprintf(fd, "\t%s\n", buf);
                        else
                                fprintf(fd, "%s\n", buf);
 
                        args->n_status_lines++;
 
                        p = buf;
                        len = sizeof(buf);
                }
        }
 
        fflush(fd);
 
        
        if (!isatty(fileno(fd)) || !(status & FE_HAS_LOCK))
                fprintf(fd, "\n");
 
        return 0;
}
 
static int check_frontend(struct arguments *args,
{
        int rc;
        fe_status_t status = 0;
        do {
                if (rc) {
                        ERROR("dvb_fe_get_stats failed");
                        usleep(1000000);
                        continue;
                }
 
                status = 0;
                if (rc) {
                        ERROR("dvb_fe_retrieve_stats failed");
                        usleep(1000000);
                        continue;
                }
                if (!args->silent)
                        print_frontend_stats(stderr, args, parms);
                if (status & FE_HAS_LOCK)
                        break;
                usleep(1000000);
        } while (!timeout_flag);
        if (args->silent < 2)
                print_frontend_stats(stderr, args, parms);
 
        return status & FE_HAS_LOCK;
}
 
static void get_show_stats(FILE *fp, struct arguments *args,
                           int loop)
{
        int rc;
 
        args->n_status_lines = 0;
        do {
                if (!rc)
                        print_frontend_stats(fp, args, parms);
                if (!timeout_flag && loop)
                        usleep(1000000);
        } while (!timeout_flag && loop);
}
 
static struct timespec *elapsed_time(struct timespec *start)
{
        static struct timespec elapsed;
        struct timespec end;
 
        if (!start->tv_sec && !start->tv_nsec)
                return NULL;
 
        if (clock_gettime(CLOCK_MONOTONIC, &end))
                return NULL;
 
        elapsed.tv_sec = end.tv_sec - start->tv_sec;
        elapsed.tv_nsec = end.tv_nsec - start->tv_nsec;
        if (elapsed.tv_nsec < 0) {
                elapsed.tv_sec--;
                elapsed.tv_nsec += NANO_SECONDS_IN_SEC;
        }
        return &elapsed;
}
 
                         int timeout, int silent)
{
        char buf[BUFLEN];
        int r, first = 1;
        long long int rc = 0LL;
        struct timespec start, *elapsed;
 
        
        clock_gettime(CLOCK_MONOTONIC, &start);
 
        while (timeout_flag == 0) {
                if (r < 0) {
                        if (r == -EOVERFLOW) {
                                elapsed = elapsed_time(&start);
                                if (!elapsed)
                                        fprintf(stderr, _("buffer overrun at %lld\n"), rc);
                                else
                                        fprintf(stderr, _("buffer overrun after %lld.%02ld seconds\n"),
                                                (long long)elapsed->tv_sec,
                                                elapsed->tv_nsec / 10000000);
                                continue;
                        }
                        ERROR("Read failed");
                        break;
                }
 
                
                if (first) {
                        if (timeout > 0)
                                alarm(timeout);
 
                        clock_gettime(CLOCK_MONOTONIC, &start);
                        first = 0;
                }
 
                if (write(out_fd, buf, r) < 0) {
                        PERROR(_("Write failed"));
                        break;
                }
 
                rc += r;
        }
        if (silent < 2) {
                if (timeout)
                        fprintf(stderr, _("received %lld bytes (%lld Kbytes/sec)\n"), rc,
                                rc / (1024 * timeout));
                else
                        fprintf(stderr, _("received %lld bytes\n"), rc);
        }
}
 
static error_t parse_opt(int k, char *optarg, struct argp_state *state)
{
        struct arguments *args = state->input;
 
        switch (k) {
        case 'a':
                args->adapter = strtoul(optarg, NULL, 0);
                break;
        case 'f':
                args->frontend = strtoul(optarg, NULL, 0);
                break;
        case 'd':
                args->demux = strtoul(optarg, NULL, 0);
                break;
        case 't':
                args->timeout = strtoul(optarg, NULL, 0);
                break;
        case 'I':
                break;
        case 'o':
                args->filename = strdup(optarg);
                
        case 'r':
                args->dvr = 1;
                break;
        case 'p':
                args->rec_psi = 1;
                break;
        case 'x':
                args->exit_after_tuning = 1;
                break;
        case 'c':
                args->confname = strdup(optarg);
                break;
        case 'w':
                if (!strcasecmp(optarg,"on")) {
                        args->lna = 1;
                } else if (!strcasecmp(optarg,"off")) {
                        args->lna = 0;
                } else if (!strcasecmp(optarg,"auto")) {
                        args->lna = LNA_AUTO;
                } else {
                        int val = strtoul(optarg, NULL, 0);
                        if (!val)
                                args->lna = 0;
                        else if (val > 0)
                                args->lna = 1;
                        else
                                args->lna = LNA_AUTO;
                }
                break;
        case 'l':
                args->lnb_name = strdup(optarg);
                break;
        case 'S':
                args->sat_number = strtoul(optarg, NULL, 0);
                break;
        case 'U':
                args->freq_bpf = strtoul(optarg, NULL, 0);
                break;
        case 'W':
                args->diseqc_wait = strtoul(optarg, NULL, 0);
                break;
        case 's':
                args->silent++;
                break;
        case 'v':
                args->verbose++;
                break;
        case 'A':
                args->n_apid = strtoul(optarg, NULL, 0);
                break;
        case 'V':
                args->n_vpid = strtoul(optarg, NULL, 0);
                break;
        case 'E':
                args->extra_pids = 1;
                break;
        case 'P':
                args->all_pids = 1;
                break;
        case 'm':
                args->traffic_monitor = 1;
                break;
        case 'N':
                args->non_human = 1;
                break;
        case 'X':
                args->low_traffic = atoi(optarg);
                break;
        case 'L':
                args->search = strdup(optarg);
                break;
        case 'C':
                args->cc = strndup(optarg, 2);
                break;
        case 'H':
                args->server = strdup(optarg);
                break;
        case 'T':
                args->port = atoi(optarg);
                break;
        case 'D':
                args->dvr_pipe = strdup(optarg);
                break;
        case '?':
                argp_state_help(state, state->out_stream,
                                ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG
                                | ARGP_HELP_DOC);
                fprintf(state->out_stream, _("\nReport bugs to %s.\n"), argp_program_bug_address);
                exit(0);
        case -4:
                fprintf (state->out_stream, "%s\n", argp_program_version);
                exit(0);
        case -3:
                argp_state_help(state, state->out_stream, ARGP_HELP_USAGE);
                exit(0);
        default:
                return ARGP_ERR_UNKNOWN;
        };
        return 0;
}
 
static char *print_bytes(float val)
{
        static char buf[20];
        char *prefix = "";
 
        if (val >= 500 * 1024 * 1024) {
                prefix = "G";
                val /= 1024 * 1024 * 1024.;
        } else if (val >= 500 * 1024) {
                prefix = "M";
                val /= 1024 * 1024.;
        } else if (val >= 500) {
                prefix = "K";
                val /= 1024.;
        }
        if (*prefix) {
                if (snprintf(buf, sizeof(buf), "%8.3f %s", val, prefix) <= 0)
                        return "      NaN ";
        } else {
                if (snprintf(buf, sizeof(buf), "%9.3f ", val) <= 0)
                        return "      NaN ";
        }
 
        return buf;
}
 
int do_traffic_monitor(
struct arguments *args, 
struct dvb_device *dvb,
 
                       int out_fd, int timeout)
{
        struct timespec startt;
        unsigned long long pidt[0x2001], wait, cont_err = 0;
        unsigned long long err_cnt[0x2000];
        signed char pid_cont[0x2000];
        int i, first = 1;
 
        memset(pidt, 0, sizeof(pidt));
        memset(err_cnt, 0, sizeof(err_cnt));
        memset(pid_cont, 0, sizeof(pid_cont));
 
        args->exit_after_tuning = 1;
        check_frontend(args, parms);
 
        if (!dvr_fd)
                return -1;
 
        fprintf(stderr, _("dvb_dev_set_bufsize: buffer set to %d\n"), DVB_BUF_SIZE);
 
        if (!fd) {
                return -1;
        }
 
        if (args->silent < 2)
                fprintf(stderr, _("  dvb_set_pesfilter to 0x2000\n"));
                                      DMX_OUT_TS_TAP, 0) < 0) {
                return -1;
        }
 
        if (clock_gettime(CLOCK_MONOTONIC, &startt)) {
                fprintf(stderr, _("Can't get timespec\n"));
                return -1;
        }
 
        wait = 1000;
 
        monitor_log(_("%.2fs: Starting capture\n"));
        while (1) {
                struct timespec *elapsed;
                unsigned char buffer[BUFLEN];
                int pid, ok, diff;
                ssize_t r;
 
                if (timeout_flag)
                        break;
 
                        if (r == -EOVERFLOW) {
                                monitor_log(_("%.2fs: buffer overrun\n"));
                                continue;
                        }
                        monitor_log(_("%.2fs: read() returned error %zd\n"), r);
                        break;
                }
 
                
                if (first) {
                        if (timeout > 0)
                                alarm(timeout);
                        first = 0;
                }
                if (out_fd >= 0) {
                        if (write(out_fd, buffer, r) < 0) {
                                PERROR(_("Write failed"));
                                break;
                        }
                }
                if (r != BUFLEN) {
                        monitor_log(_("%.2fs: only read %zd bytes\n"), r);
                        break;
                }
 
                for (i = 0; i < BUFLEN; i += 188) {
                                monitor_log(_("%.2fs: invalid sync byte. Discarding %zd bytes\n"), r);
                                continue;
                        }
 
 
#if 0
                        
                                continue;
#endif
                        ok = 1;
 
                                monitor_log(_("%.2fs: invalid pid: 0x%04x\n"),
                        }
 
                        
 
                                        } else {
                                                monitor_log(_("%.2fs: pid %d has adaption layer, but size is too small!\n"),
                                        }
                                }
 
                                if (wait < 2000)
 
                                        unsigned int next = (pid_cont[
pid] + 1) % 16;
 
                                                monitor_log(_("%.2fs: pid %d, expecting %d received %d\n"),
                                                cont_err++;
                                        }
                                }
                                else
                        }
 
                        if (args->search) {
                                int i, sl = strlen(args->search);
                                ok = 0;
                                        for (i = 0; i < (188 - sl); ++i) {
                                                if (!memcmp((char *)h + i, args->search, sl))
                                                        ok = 1;
                                        }
                                }
                        }
 
                        if (ok) {
                                pidt[0x2000]++;
                        }
                }
 
                elapsed = elapsed_time(&startt);
                if (!elapsed)
                        diff = wait;
                else
                        diff = (unsigned long long)elapsed->tv_sec * 1000
                                + elapsed->tv_nsec * 1000 / NANO_SECONDS_IN_SEC;
 
                if (diff > wait) {
                        unsigned long long other_pidt = 0, other_err_cnt = 0;
 
                        if (isatty(STDOUT_FILENO))
                                printf("\x1b[1H\x1b[2J");
 
                        args->n_status_lines = 0;
                        printf(_(" PID           FREQ         SPEED       TOTAL\n"));
                        int _pid = 0;
                        for (_pid = 0; _pid < 0x2000; _pid++) {
                                if (pidt[_pid]) {
                                        if (args->low_traffic && (pidt[_pid] * 1000. / diff) < args->low_traffic) {
                                                other_pidt += pidt[_pid];
                                                other_err_cnt += err_cnt[_pid];
                                                continue;
                                        }
                                        printf("%5d %9.2f p/s %sbps ",
                                                _pid,
                                                pidt[_pid] * 1000. / diff,
                                                print_bytes(pidt[_pid] * 1000. * 8 * 188/ diff));
                                        if (pidt[_pid] * 188 / 1024)
                                                printf("%8llu KB", (pidt[_pid] * 188 + 512) / 1024);
                                        else
                                                printf(" %8llu B", pidt[_pid] * 188);
                                        if (err_cnt[_pid] > 0)
                                                printf(" %8llu continuity errors",
                                                       err_cnt[_pid]);
 
                                        printf("\n");
                                }
                        }
                        if (other_pidt) {
                                printf(_("OTHER"));
                                printf(" %9.2f p/s %sbps ",
                                        other_pidt * 1000. / diff,
                                        print_bytes(other_pidt * 1000. * 8 * 188/ diff));
                                if (other_pidt * 188 / 1024)
                                        printf("%8llu KB", (other_pidt * 188 + 512) / 1024);
                                else
                                        printf(" %8llu B", other_pidt * 188);
                                if (other_err_cnt > 0)
                                        printf(" %8llu continuity errors",
                                               other_err_cnt);
                                printf("\n");
                        }
 
                        
                        printf("TOT %11.2f p/s %sbps %8llu KB\n",
                                pidt[_pid] * 1000. / diff,
                                print_bytes(pidt[_pid] * 1000. * 8 * 188/ diff),
                                (pidt[_pid] * 188 + 512) / 1024);
                        printf("\n");
                        get_show_stats(stdout, args, parms, 0);
                        wait += 1000;
                        if (cont_err)
                                printf("CONTINUITY errors: %llu\n", cont_err);
                }
        }
        monitor_log(_("%.2fs: Stopping capture\n"));
        return 0;
}
 
static void set_signals(struct arguments *args)
{
        signal(SIGTERM, do_timeout);
        signal(SIGINT, do_timeout);
        if (args->timeout > 0) {
                signal(SIGALRM, do_timeout);
                alarm(args->timeout);
        }
}
 
static char *default_dvr_pipe = "/tmp/dvr-pipe";
 
int main(int argc, char **argv)
{
        struct arguments args = {};
        char *homedir = getenv("HOME");
        char *channel = NULL;
        int lnb = -1, idx = -1;
        int pmtpid = 0;
        int file_fd = -1;
        int err = -1;
        int r, ret;
        const struct argp argp = {
                .options = options,
                .parser = parse_opt,
                .doc = N_("DVB zap utility"),
                .args_doc = N_("<channel name> [or <frequency> if in monitor mode]"),
        };
 
#ifdef ENABLE_NLS
        setlocale (LC_ALL, "");
        bindtextdomain (PACKAGE, LOCALEDIR);
        textdomain (PACKAGE);
#endif
 
        args.sat_number = -1;
        args.lna = LNA_AUTO;
        args.dvr_pipe = default_dvr_pipe;
        args.low_traffic = 1;
 
        if (argp_parse(&argp, argc, argv, ARGP_NO_HELP | ARGP_NO_EXIT, &idx, &args)) {
                argp_help(&argp, stderr, ARGP_HELP_SHORT_USAGE, PROGRAM_NAME);
                return -1;
        }
 
        if (idx < argc)
                channel = argv[idx];
 
        if (!channel) {
                argp_help(&argp, stderr, ARGP_HELP_STD_HELP, PROGRAM_NAME);
                return -1;
        }
 
                ERROR("Please specify a valid format\n");
                argp_help(&argp, stderr, ARGP_HELP_STD_HELP, PROGRAM_NAME);
                return -1;
        }
 
        if (!args.traffic_monitor && args.search) {
                ERROR("search string can be used only on monitor mode\n");
                argp_help(&argp, stderr, ARGP_HELP_STD_HELP, PROGRAM_NAME);
                return -1;
        }
 
        if (args.lnb_name) {
                if (lnb < 0) {
                        printf(_("Please select one of the LNBf's below:\n"));
                        exit(1);
                } else {
                        printf(_("Using LNBf "));
                }
        }
 
        if (!dvb)
                return -1;
 
        if (args.server && args.port) {
                printf(_("Connecting to %s:%d\n"), args.server, args.port);
                if (ret < 0)
                        return -1;
        }
 
 
        if (!dvb_dev) {
                fprintf(stderr, _("Couldn't find demux device node\n"));
                return -1;
        }
 
        if (!dvb_dev) {
                fprintf(stderr, _("Couldn't find dvr device node\n"));
                return -1;
        }
        args.dvr_fname = dvb_dev->
path;
 
        if (args.silent < 2)
                fprintf(stderr, _("using demux '%s'\n"), args.demux_dev);
 
        if (!args.confname) {
                if (!homedir)
                        ERROR("$HOME not set");
                r = asprintf(&args.confname, "%s/.tzap/%i/%s",
                         homedir, args.adapter, CHANNEL_FILE);
                if (access(args.confname, R_OK)) {
                        free(args.confname);
                        r = asprintf(&args.confname, "%s/.tzap/%s",
                                homedir, CHANNEL_FILE);
                }
        }
        fprintf(stderr, _("reading channels from file '%s'\n"), args.confname);
 
        if (!dvb_dev)
                return -1;
 
                goto err;
        if (lnb >= 0)
        if (args.sat_number >= 0)
 
        if (r < 0)
                fprintf(stderr, _("Failed to set the country code:%s\n"), args.cc);
 
                goto err;
 
        if (setup_frontend(&args, parms) < 0)
                goto err;
 
        if (args.exit_after_tuning) {
                set_signals(&args);
                err = 0;
                check_frontend(&args, parms);
                goto err;
        }
 
        if (args.traffic_monitor) {
                if (args.filename) {
                        file_fd = open(args.filename,
                                         O_LARGEFILE |
                                         O_WRONLY | O_CREAT | O_TRUNC,
                                         0644);
                        if (file_fd < 0) {
                                PERROR(_("open of '%s' failed"), args.filename);
                                return -1;
                        }
                }
                set_signals(&args);
                err = do_traffic_monitor(&args, dvb, file_fd, args.timeout);
                goto err;
        }
 
        if (args.rec_psi) {
                if (!sid_fd) {
                        ERROR("opening sid demux failed");
                        return -1;
                }
                if (pmtpid <= 0) {
                        fprintf(stderr, _("couldn't find pmt-pid for sid %04x\n"),
                        goto err;
                }
 
                if (!pat_fd) {
                        ERROR("opening pat demux failed");
                        goto err;
                }
                                args.dvr ? DMX_OUT_TS_TAP : DMX_OUT_DECODER,
                                args.dvr ? 64 * 1024 : 0) < 0)
                        goto err;
 
                if (!pmt_fd) {
                        ERROR("opening pmt demux failed");
                        goto err;
                }
                                args.dvr ? DMX_OUT_TS_TAP : DMX_OUT_DECODER,
                                args.dvr ? 64 * 1024 : 0) < 0)
                        goto err;
 
                
                if (!sdt_fd) {
                        ERROR("opening sdt demux failed");
                        goto err;
                }
                                args.dvr ? DMX_OUT_TS_TAP : DMX_OUT_DECODER,
                                args.dvr ? 64 * 1024 : 0) < 0)
                        goto err;
        }
 
        if (args.all_pids) {
                if (!video_fd) {
                        ERROR("failed opening '%s'", args.demux_dev);
                        goto err;
                }
 
                fprintf(stderr, _("dvb_dev_set_bufsize: buffer set to %d\n"), DVB_BUF_SIZE);
 
                if (args.silent < 2) {
                        fprintf(stderr, _("pass all PIDs to TS\n"));
                        fprintf(stderr, _("  dvb_set_pesfilter %d\n"), 0x2000);
                }
 
                                      DMX_OUT_TS_TAP, 0) < 0) {
                        goto err;
                }
        } else {
                        if (!video_fd) {
                                ERROR("failed opening '%s'", args.demux_dev);
                                goto err;
                        }
 
                        fprintf(stderr, _("dvb_dev_set_bufsize: buffer set to %d\n"), DVB_BUF_SIZE);
 
                                args.n_vpid = 0;
                        }
 
                                if (!args.extra_pids && i != args.n_vpid) {
                                        continue;
                                }
 
                                if (args.silent < 2) {
                                        fprintf(stderr, _("video%2$s pid %1$d\n"),
                                }
 
                                        i == args.n_vpid ? DMX_PES_VIDEO : DMX_PES_OTHER,
                                        args.dvr ? DMX_OUT_TS_TAP : DMX_OUT_DECODER,
                                        args.dvr ? 1024 * 1024 : 0) < 0) {
                                        goto err;
                                }
                        }
                }
 
                                args.n_apid = 0;
                        }
 
                                if (!args.extra_pids && i != args.n_apid) {
                                        continue;
                                }
 
                                if (!audio_fd) {
                                        ERROR("failed opening '%s'", args.demux_dev);
                                        goto err;
                                }
 
                                if (args.silent < 2) {
                                        fprintf(stderr, _("audio%2$s pid %1$d\n"),
                                }
 
                                                i == args.n_apid ? DMX_PES_AUDIO : DMX_PES_OTHER,
                                                args.dvr ? DMX_OUT_TS_TAP : DMX_OUT_DECODER,
                                                args.dvr ? 64 * 1024 : 0) < 0) {
                                        goto err;
                                }
                        }
                }
 
                                if (!other_fd) {
                                        ERROR("failed opening '%s'", args.demux_dev);
                                        goto err;
                                }
 
                                if (args.silent < 2) {
                                        fprintf(stderr, _("other pid %d (%d)\n"),
                                }
 
                                                args.dvr ? DMX_OUT_TS_TAP : DMX_OUT_DECODER,
                                                args.dvr ? 64 * 1024 : 0) < 0) {
                                        goto err;
                                }
                        }
                }
        }
 
                printf(_("PMT record is disabled.\n"
                         "Please notice that some streams can only be decoded with PMT data.\n"
                         "Use '-p' option to also record PMT.\n"));
        }
 
        set_signals(&args);
 
        if (!check_frontend(&args, parms)) {
                err = 1;
                fprintf(stderr, _("frontend doesn't lock\n"));
                goto err;
        }
 
        if (args.dvr) {
                if (args.filename) {
                        file_fd = STDOUT_FILENO;
 
                        if (strcmp(args.filename, "-") != 0) {
                                file_fd = open(args.filename,
                                         O_LARGEFILE |
                                         O_WRONLY | O_CREAT | O_TRUNC,
                                         0644);
                                if (file_fd < 0) {
                                        PERROR(_("open of '%s' failed"),
                                               args.filename);
                                        return -1;
                                }
                        }
                }
 
                if (args.silent < 2)
                        get_show_stats(stderr, &args, parms, 0);
 
                if (file_fd >= 0) {
                        if (!dvr_fd) {
                                ERROR("failed opening '%s'", args.dvr_dev);
                                goto err;
                        }
                        if (!timeout_flag)
                                fprintf(stderr, _("Record to file '%s' started\n"), args.filename);
                        copy_to_file(dvr_fd, file_fd, args.timeout, args.silent);
                } else if (args.server && args.port) {
                        struct stat st;
                        if (stat(args.dvr_pipe, &st) == -1) {
                                if (mknod(args.dvr_pipe,
                                        S_IRUSR | S_IWUSR | S_IFIFO, 0) < 0) {
                                        PERROR("Can't create pipe %s",
                                        args.dvr_pipe);
                                        return -1;
                                }
                        } else {
                                if (!S_ISFIFO(st.st_mode)) {
                                        ERROR("%s exists but is not a pipe",
                                        args.dvr_pipe);
                                        return -1;
                                }
                        }
 
                        fprintf(stderr, _("DVR pipe interface '%s' will be opened\n"), args.dvr_pipe);
 
                        if (!dvr_fd) {
                                ERROR("failed opening '%s'", args.dvr_dev);
                                err = -1;
                                goto err;
                        }
 
                        file_fd = open(args.dvr_pipe,
#ifdef O_LARGEFILE
                                        O_LARGEFILE |
#endif
                                        O_WRONLY,
                                        0644);
                        if (file_fd < 0) {
                                PERROR(_("open of '%s' failed"),
                                        args.filename);
                                err = -1;
                                goto err;
                        }
                        copy_to_file(dvr_fd, file_fd, args.timeout, args.silent);
                } else {
                        if (!timeout_flag)
                                fprintf(stderr, _("DVR interface '%s' can now be opened\n"), args.dvr_fname);
 
                        get_show_stats(stderr, &args, parms, 1);
                }
                if (args.silent < 2)
                        get_show_stats(stderr, &args, parms, 0);
        } else {
                
                while (!timeout_flag) {
                        get_show_stats(stderr, &args, parms, 1);
                        usleep(1000000);
                }
        }
        err = 0;
 
err:
 
        }
 
        
        if (args.confname)
                free(args.confname);
        if (args.filename)
                free(args.filename);
        if (args.lnb_name)
                free(args.lnb_name);
        if (args.search)
                free(args.search);
        if (args.server)
                free(args.server);
        if (args.dvr_pipe != default_dvr_pipe)
                free(args.dvr_pipe);
 
        return err;
}
Provides ancillary code to convert ISO 3166-1 country codes.
Provides interfaces to deal with DVB demux.
Provides interfaces to handle Digital TV devices.
static int dvb_dev_remote_init(struct dvb_device *d, char *server, int port)
struct dvb_dev_list * dvb_dev_seek_by_adapter(struct dvb_device *dvb, unsigned int adapter, unsigned int num, enum dvb_dev_type type)
Find a device that matches the search criteria given by this functions's parameters.
Provides interfaces to deal with DVB channel and program files.
@ FILE_UNKNOWN
File format is unknown.
@ FILE_DVBV5
File is at libdvbv5 format.
Provides interfaces to scan programs inside MPEG-TS digital TV streams.
void dvb_dev_free(struct dvb_device *dvb)
free a struct dvb_device
struct dvb_open_descriptor * dvb_dev_open(struct dvb_device *dvb, const char *sysname, int flags)
Opens a dvb device.
int dvb_dev_dmx_get_pmt_pid(struct dvb_open_descriptor *open_dev, int sid)
read the contents of the MPEG-TS PAT table, seeking for an specific service ID
int dvb_dev_dmx_set_pesfilter(struct dvb_open_descriptor *open_dev, int pid, dmx_pes_type_t type, dmx_output_t output, int buffersize)
Start a filter for a MPEG-TS Packetized Elementary Stream (PES)
int dvb_dev_find(struct dvb_device *dvb, dvb_dev_change_t handler, void *user_priv)
finds all DVB devices on the local machine
int dvb_dev_set_bufsize(struct dvb_open_descriptor *open_dev, int buffersize)
Start a demux or dvr buffer size.
void dvb_dev_set_log(struct dvb_device *dvb, unsigned verbose, dvb_logfunc logfunc)
Sets the DVB verbosity and log function.
ssize_t dvb_dev_read(struct dvb_open_descriptor *open_dev, void *buf, size_t count)
read from a dvb demux or dvr file
struct dvb_device * dvb_dev_alloc(void)
Allocate a struct dvb_device.
void dvb_dev_close(struct dvb_open_descriptor *open_dev)
Closes a dvb device.
dvb_file_formats
Known file formats.
struct dvb_file * dvb_read_file_format(const char *fname, uint32_t delsys, enum dvb_file_formats format)
Read a file on any format natively supported by the library.
int dvb_retrieve_entry_prop(struct dvb_entry *entry, uint32_t cmd, uint32_t *value)
Retrieves the value associated witha key on a DVB file entry.
static void dvb_file_free(struct dvb_file *dvb_file)
Deallocates memory associated with a struct dvb_file.
enum dvb_file_formats dvb_parse_format(const char *name)
Ancillary function that parses the name of a file format.
int dvb_fe_set_default_country(struct dvb_v5_fe_parms *parms, const char *country)
Set default country variant of delivery systems like ISDB-T.
#define DTV_BER
Bit Error Rate.
int dvb_fe_retrieve_stats(struct dvb_v5_fe_parms *parms, unsigned cmd, uint32_t *value)
Retrieve the stats for a DTV layer from cache.
int dvb_fe_store_parm(struct dvb_v5_fe_parms *parms, unsigned cmd, uint32_t value)
Stores the value of a DVBv5/libdvbv5 property.
int dvb_fe_snprintf_stat(struct dvb_v5_fe_parms *parms, uint32_t cmd, char *display_name, int layer, char **buf, int *len, int *show_layer_name)
Ancillary function to sprintf on ENG format.
int dvb_set_compat_delivery_system(struct dvb_v5_fe_parms *parms, uint32_t desired_system)
Sets the delivery system.
#define DTV_STATUS
Lock status of a DTV frontend.
int dvb_fe_retrieve_parm(const struct dvb_v5_fe_parms *parms, unsigned cmd, uint32_t *value)
Retrieves the value of a DVBv5/libdvbv5 property.
#define DTV_QUALITY
A quality indicator that represents if a locked channel provides a good, OK or poor signal.
#define DTV_PER
Packet Error Rate.
int dvb_fe_set_parms(struct dvb_v5_fe_parms *parms)
Prints all the properties at the cache.
#define DTV_PRE_BER
Bit Error Rate before Viterbi.
int dvb_fe_get_stats(struct dvb_v5_fe_parms *parms)
Retrieve the stats from the Kernel.
void dvb_print_all_lnb(void)
Prints all LNBf entries at STDOUT.
int dvb_print_lnb(int index)
prints the contents of a LNBf entry at STDOUT.
const struct dvb_sat_lnb * dvb_sat_get_lnb(int index)
gets a LNBf entry at its internal database
int dvb_sat_search_lnb(const char *name)
search for a LNBf entry
Digital TV device node properties.
Digital TV list of devices.
struct dvb_v5_fe_parms * fe_parms
Represents one entry on a DTV file.
struct dtv_property props[DTV_MAX_COMMAND]
struct dvb_elementary_pid * other_el_pid
unsigned other_el_pid_len
Describes an entire DVB file opened.
struct dvb_entry * first_entry
Opaque struct with a DVB open file descriptor.
Keeps data needed to handle the DVB frontend.
const struct dvb_sat_lnb * lnb
fe_delivery_system_t current_sys