220 lines
5.3 KiB
C
220 lines
5.3 KiB
C
/*
|
|
* libzvbi network identification example
|
|
*
|
|
* Copyright (C) 2006 Michael H. Schimek
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in
|
|
* the documentation and/or other materials provided with the
|
|
* distribution.
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
/* $Id: network.c,v 1.5 2008/02/19 00:51:51 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);
|
|
}
|