Main Page | Modules | Data Structures | Data Fields | Related Pages | Examples

examples/network.c

Network identification example.

/*
 *  libzvbi network identification example.
 *
 *  Copyright (C) 2006 Michael H. Schimek
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

/* $Id: network.c,v 1.2 2006/10/27 04:52:08 mschimek Exp $ */

/* This example shows how to identify a network from data transmitted
   in XDS packets, Teletext packet 8/30 format 1 and 2, and VPS packets.

   gcc -o network network.c `pkg-config zvbi-0.2 --cflags --libs` */

#undef NDEBUG
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
#include <errno.h>

#include <libzvbi.h>

static vbi_capture *            cap;
static vbi_decoder *            dec;
static vbi_bool                 quit;

static unsigned int             services;

static void
handler                         (vbi_event *            ev,
                                 void *                 user_data)
{
        const char *event_name;
        const char *network_name;
        const char *call_sign;
        char *locale_network_name;

        user_data = user_data; /* unused */

        /* VBI_EVENT_NETWORK_ID is always sent when the decoder
           receives a CNI. VBI_EVENT_NETWORK only if it can
           determine a network name. */

        switch (ev->type) {
        case VBI_EVENT_NETWORK:
                event_name = "VBI_EVENT_NETWORK";
                quit = TRUE;
                break;

        case VBI_EVENT_NETWORK_ID:
                event_name = "VBI_EVENT_NETWORK_ID";
                break;

        default:
                assert (0);
        }

        network_name = "unknown";
        if (0 != ev->ev.network.name[0])
                network_name = ev->ev.network.name;

        /* The network name is an ISO-8859-1 string (the API is
           quite old...) so we convert it to locale encoding,
           nowadays usually UTF-8. */
        locale_network_name = vbi_strndup_iconv (vbi_locale_codeset (),
                                                 "ISO-8859-1",
                                                 network_name,
                                                 strlen (network_name),
                                                 /* repl_char */ '?');

        /* ASCII. */
        call_sign = "unknown";
        if (0 != ev->ev.network.call[0])
                call_sign = ev->ev.network.call;

        printf ("%s: receiving: \"%s\" call sign: \"%s\" "
                "CNI VPS: 0x%x 8/30-1: 0x%x 8/30-2: 0x%x\n",
                event_name,
                (NULL == locale_network_name) ?
                "iconv-error" : locale_network_name,
                call_sign,
                ev->ev.network.cni_vps,
                ev->ev.network.cni_8301,
                ev->ev.network.cni_8302);

        free (locale_network_name);
}

static void
mainloop                        (void)
{
        struct timeval timeout;
        vbi_capture_buffer *sliced_buffer;
        unsigned int n_frames;

        /* Don't wait more than two seconds for the driver
           to return data. */
        timeout.tv_sec = 2;
        timeout.tv_usec = 0;

        /* Should receive a CNI within two seconds,
           call sign within ten seconds(?). */
        if (services & VBI_SLICED_CAPTION_525)
                n_frames = 11 * 30;
        else
                n_frames = 3 * 25;

        for (; n_frames > 0; --n_frames) {
                unsigned int n_lines;
                int r;

                r = vbi_capture_pull (cap,
                                      /* raw_buffer */ NULL,
                                      &sliced_buffer,
                                      &timeout);
                switch (r) {
                case -1:
                        fprintf (stderr, "VBI read error %d (%s)\n",
                                 errno, strerror (errno));
                        /* Could be ignored, esp. EIO with some drivers. */
                        exit(EXIT_FAILURE);

                case 0: 
                        fprintf (stderr, "VBI read timeout\n");
                        exit(EXIT_FAILURE);

                case 1: /* success */
                        break;

                default:
                        assert (0);
                }

                n_lines = sliced_buffer->size / sizeof (vbi_sliced);

                vbi_decode (dec,
                            (vbi_sliced *) sliced_buffer->data,
                            n_lines,
                            sliced_buffer->timestamp);

                if (quit)
                        return;
        }

        printf ("No network ID received or network unknown.\n");
}

int
main                            (void)
{
        char *errstr;
        vbi_bool success;

        setlocale (LC_ALL, "");

        services = (VBI_SLICED_TELETEXT_B |
                    VBI_SLICED_VPS |
                    VBI_SLICED_CAPTION_525);

        cap = vbi_capture_v4l2_new ("/dev/vbi",
                                    /* buffers */ 5,
                                    &services,
                                    /* strict */ 0,
                                    &errstr,
                                    /* verbose */ FALSE);
        if (NULL == cap) {
                fprintf (stderr,
                         "Cannot capture VBI data with V4L2 interface:\n"
                         "%s\n",
                         errstr);

                free (errstr);
                errstr = NULL;

                exit (EXIT_FAILURE);
        }

        dec = vbi_decoder_new ();
        assert (NULL != dec);

        success = vbi_event_handler_add (dec,
                                         (VBI_EVENT_NETWORK |
                                          VBI_EVENT_NETWORK_ID),
                                         handler,
                                         /* user_data */ NULL);
        assert (success);

        mainloop ();

        vbi_decoder_delete (dec);
        dec = NULL;

        vbi_capture_delete (cap);
        cap = NULL;

        exit (EXIT_SUCCESS);
}

Generated on Sat Mar 10 00:12:43 2007 for ZVBI Library by  doxygen 1.3.9.1