00001 /* 00002 * libzvbi network identification example. 00003 * 00004 * Copyright (C) 2006 Michael H. Schimek 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00019 */ 00020 00021 /* $Id: network.c,v 1.2 2006/10/27 04:52:08 mschimek Exp $ */ 00022 00023 /* This example shows how to identify a network from data transmitted 00024 in XDS packets, Teletext packet 8/30 format 1 and 2, and VPS packets. 00025 00026 gcc -o network network.c `pkg-config zvbi-0.2 --cflags --libs` */ 00027 00028 #undef NDEBUG 00029 #include <assert.h> 00030 #include <stdio.h> 00031 #include <stdlib.h> 00032 #include <string.h> 00033 #include <locale.h> 00034 #include <errno.h> 00035 00036 #include <libzvbi.h> 00037 00038 static vbi_capture * cap; 00039 static vbi_decoder * dec; 00040 static vbi_bool quit; 00041 00042 static unsigned int services; 00043 00044 static void 00045 handler (vbi_event * ev, 00046 void * user_data) 00047 { 00048 const char *event_name; 00049 const char *network_name; 00050 const char *call_sign; 00051 char *locale_network_name; 00052 00053 user_data = user_data; /* unused */ 00054 00055 /* VBI_EVENT_NETWORK_ID is always sent when the decoder 00056 receives a CNI. VBI_EVENT_NETWORK only if it can 00057 determine a network name. */ 00058 00059 switch (ev->type) { 00060 case VBI_EVENT_NETWORK: 00061 event_name = "VBI_EVENT_NETWORK"; 00062 quit = TRUE; 00063 break; 00064 00065 case VBI_EVENT_NETWORK_ID: 00066 event_name = "VBI_EVENT_NETWORK_ID"; 00067 break; 00068 00069 default: 00070 assert (0); 00071 } 00072 00073 network_name = "unknown"; 00074 if (0 != ev->ev.network.name[0]) 00075 network_name = ev->ev.network.name; 00076 00077 /* The network name is an ISO-8859-1 string (the API is 00078 quite old...) so we convert it to locale encoding, 00079 nowadays usually UTF-8. */ 00080 locale_network_name = vbi_strndup_iconv (vbi_locale_codeset (), 00081 "ISO-8859-1", 00082 network_name, 00083 strlen (network_name), 00084 /* repl_char */ '?'); 00085 00086 /* ASCII. */ 00087 call_sign = "unknown"; 00088 if (0 != ev->ev.network.call[0]) 00089 call_sign = ev->ev.network.call; 00090 00091 printf ("%s: receiving: \"%s\" call sign: \"%s\" " 00092 "CNI VPS: 0x%x 8/30-1: 0x%x 8/30-2: 0x%x\n", 00093 event_name, 00094 (NULL == locale_network_name) ? 00095 "iconv-error" : locale_network_name, 00096 call_sign, 00097 ev->ev.network.cni_vps, 00098 ev->ev.network.cni_8301, 00099 ev->ev.network.cni_8302); 00100 00101 free (locale_network_name); 00102 } 00103 00104 static void 00105 mainloop (void) 00106 { 00107 struct timeval timeout; 00108 vbi_capture_buffer *sliced_buffer; 00109 unsigned int n_frames; 00110 00111 /* Don't wait more than two seconds for the driver 00112 to return data. */ 00113 timeout.tv_sec = 2; 00114 timeout.tv_usec = 0; 00115 00116 /* Should receive a CNI within two seconds, 00117 call sign within ten seconds(?). */ 00118 if (services & VBI_SLICED_CAPTION_525) 00119 n_frames = 11 * 30; 00120 else 00121 n_frames = 3 * 25; 00122 00123 for (; n_frames > 0; --n_frames) { 00124 unsigned int n_lines; 00125 int r; 00126 00127 r = vbi_capture_pull (cap, 00128 /* raw_buffer */ NULL, 00129 &sliced_buffer, 00130 &timeout); 00131 switch (r) { 00132 case -1: 00133 fprintf (stderr, "VBI read error %d (%s)\n", 00134 errno, strerror (errno)); 00135 /* Could be ignored, esp. EIO with some drivers. */ 00136 exit(EXIT_FAILURE); 00137 00138 case 0: 00139 fprintf (stderr, "VBI read timeout\n"); 00140 exit(EXIT_FAILURE); 00141 00142 case 1: /* success */ 00143 break; 00144 00145 default: 00146 assert (0); 00147 } 00148 00149 n_lines = sliced_buffer->size / sizeof (vbi_sliced); 00150 00151 vbi_decode (dec, 00152 (vbi_sliced *) sliced_buffer->data, 00153 n_lines, 00154 sliced_buffer->timestamp); 00155 00156 if (quit) 00157 return; 00158 } 00159 00160 printf ("No network ID received or network unknown.\n"); 00161 } 00162 00163 int 00164 main (void) 00165 { 00166 char *errstr; 00167 vbi_bool success; 00168 00169 setlocale (LC_ALL, ""); 00170 00171 services = (VBI_SLICED_TELETEXT_B | 00172 VBI_SLICED_VPS | 00173 VBI_SLICED_CAPTION_525); 00174 00175 cap = vbi_capture_v4l2_new ("/dev/vbi", 00176 /* buffers */ 5, 00177 &services, 00178 /* strict */ 0, 00179 &errstr, 00180 /* verbose */ FALSE); 00181 if (NULL == cap) { 00182 fprintf (stderr, 00183 "Cannot capture VBI data with V4L2 interface:\n" 00184 "%s\n", 00185 errstr); 00186 00187 free (errstr); 00188 errstr = NULL; 00189 00190 exit (EXIT_FAILURE); 00191 } 00192 00193 dec = vbi_decoder_new (); 00194 assert (NULL != dec); 00195 00196 success = vbi_event_handler_add (dec, 00197 (VBI_EVENT_NETWORK | 00198 VBI_EVENT_NETWORK_ID), 00199 handler, 00200 /* user_data */ NULL); 00201 assert (success); 00202 00203 mainloop (); 00204 00205 vbi_decoder_delete (dec); 00206 dec = NULL; 00207 00208 vbi_capture_delete (cap); 00209 cap = NULL; 00210 00211 exit (EXIT_SUCCESS); 00212 }