00001 /* 00002 * libzvbi network identification example 00003 * 00004 * Copyright (C) 2006 Michael H. Schimek 00005 * 00006 * Redistribution and use in source and binary forms, with or without 00007 * modification, are permitted provided that the following conditions 00008 * are met: 00009 * 1. Redistributions of source code must retain the above copyright 00010 * notice, this list of conditions and the following disclaimer. 00011 * 2. Redistributions in binary form must reproduce the above copyright 00012 * notice, this list of conditions and the following disclaimer in 00013 * the documentation and/or other materials provided with the 00014 * distribution. 00015 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00016 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00017 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00018 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 00019 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00020 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00021 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00022 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00023 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00024 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00025 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00026 */ 00027 00028 /* $Id: network.c,v 1.5 2008/02/19 00:51:51 mschimek Exp $ */ 00029 00030 /* This example shows how to identify a network from data transmitted 00031 in XDS packets, Teletext packet 8/30 format 1 and 2, and VPS packets. 00032 00033 gcc -o network network.c `pkg-config zvbi-0.2 --cflags --libs` */ 00034 00035 #undef NDEBUG 00036 #include <assert.h> 00037 #include <stdio.h> 00038 #include <stdlib.h> 00039 #include <string.h> 00040 #include <locale.h> 00041 #include <errno.h> 00042 00043 #include <libzvbi.h> 00044 00045 static vbi_capture * cap; 00046 static vbi_decoder * dec; 00047 static vbi_bool quit; 00048 00049 static unsigned int services; 00050 00051 static void 00052 handler (vbi_event * ev, 00053 void * user_data) 00054 { 00055 const char *event_name; 00056 const char *network_name; 00057 const char *call_sign; 00058 char *locale_network_name; 00059 00060 user_data = user_data; /* unused */ 00061 00062 /* VBI_EVENT_NETWORK_ID is always sent when the decoder 00063 receives a CNI. VBI_EVENT_NETWORK only if it can 00064 determine a network name. */ 00065 00066 switch (ev->type) { 00067 case VBI_EVENT_NETWORK: 00068 event_name = "VBI_EVENT_NETWORK"; 00069 quit = TRUE; 00070 break; 00071 00072 case VBI_EVENT_NETWORK_ID: 00073 event_name = "VBI_EVENT_NETWORK_ID"; 00074 break; 00075 00076 default: 00077 assert (0); 00078 } 00079 00080 network_name = "unknown"; 00081 if (0 != ev->ev.network.name[0]) 00082 network_name = ev->ev.network.name; 00083 00084 /* The network name is an ISO-8859-1 string (the API is 00085 quite old...) so we convert it to locale encoding, 00086 nowadays usually UTF-8. */ 00087 locale_network_name = vbi_strndup_iconv (vbi_locale_codeset (), 00088 "ISO-8859-1", 00089 network_name, 00090 strlen (network_name), 00091 /* repl_char */ '?'); 00092 00093 /* ASCII. */ 00094 call_sign = "unknown"; 00095 if (0 != ev->ev.network.call[0]) 00096 call_sign = ev->ev.network.call; 00097 00098 printf ("%s: receiving: \"%s\" call sign: \"%s\" " 00099 "CNI VPS: 0x%x 8/30-1: 0x%x 8/30-2: 0x%x\n", 00100 event_name, 00101 (NULL == locale_network_name) ? 00102 "iconv-error" : locale_network_name, 00103 call_sign, 00104 ev->ev.network.cni_vps, 00105 ev->ev.network.cni_8301, 00106 ev->ev.network.cni_8302); 00107 00108 free (locale_network_name); 00109 } 00110 00111 static void 00112 mainloop (void) 00113 { 00114 struct timeval timeout; 00115 vbi_capture_buffer *sliced_buffer; 00116 unsigned int n_frames; 00117 00118 /* Don't wait more than two seconds for the driver 00119 to return data. */ 00120 timeout.tv_sec = 2; 00121 timeout.tv_usec = 0; 00122 00123 /* Should receive a CNI within two seconds, 00124 call sign within ten seconds(?). */ 00125 if (services & VBI_SLICED_CAPTION_525) 00126 n_frames = 11 * 30; 00127 else 00128 n_frames = 3 * 25; 00129 00130 for (; n_frames > 0; --n_frames) { 00131 unsigned int n_lines; 00132 int r; 00133 00134 r = vbi_capture_pull (cap, 00135 /* raw_buffer */ NULL, 00136 &sliced_buffer, 00137 &timeout); 00138 switch (r) { 00139 case -1: 00140 fprintf (stderr, "VBI read error %d (%s)\n", 00141 errno, strerror (errno)); 00142 /* Could be ignored, esp. EIO with some drivers. */ 00143 exit(EXIT_FAILURE); 00144 00145 case 0: 00146 fprintf (stderr, "VBI read timeout\n"); 00147 exit(EXIT_FAILURE); 00148 00149 case 1: /* success */ 00150 break; 00151 00152 default: 00153 assert (0); 00154 } 00155 00156 n_lines = sliced_buffer->size / sizeof (vbi_sliced); 00157 00158 vbi_decode (dec, 00159 (vbi_sliced *) sliced_buffer->data, 00160 n_lines, 00161 sliced_buffer->timestamp); 00162 00163 if (quit) 00164 return; 00165 } 00166 00167 printf ("No network ID received or network unknown.\n"); 00168 } 00169 00170 int 00171 main (void) 00172 { 00173 char *errstr; 00174 vbi_bool success; 00175 00176 setlocale (LC_ALL, ""); 00177 00178 services = (VBI_SLICED_TELETEXT_B | 00179 VBI_SLICED_VPS | 00180 VBI_SLICED_CAPTION_525); 00181 00182 cap = vbi_capture_v4l2_new ("/dev/vbi", 00183 /* buffers */ 5, 00184 &services, 00185 /* strict */ 0, 00186 &errstr, 00187 /* verbose */ FALSE); 00188 if (NULL == cap) { 00189 fprintf (stderr, 00190 "Cannot capture VBI data with V4L2 interface:\n" 00191 "%s\n", 00192 errstr); 00193 00194 free (errstr); 00195 errstr = NULL; 00196 00197 exit (EXIT_FAILURE); 00198 } 00199 00200 dec = vbi_decoder_new (); 00201 assert (NULL != dec); 00202 00203 success = vbi_event_handler_add (dec, 00204 (VBI_EVENT_NETWORK | 00205 VBI_EVENT_NETWORK_ID), 00206 handler, 00207 /* user_data */ NULL); 00208 assert (success); 00209 00210 mainloop (); 00211 00212 vbi_decoder_delete (dec); 00213 dec = NULL; 00214 00215 vbi_capture_delete (cap); 00216 cap = NULL; 00217 00218 exit (EXIT_SUCCESS); 00219 }