Sophie

Sophie

distrib > Mageia > 6 > x86_64 > media > core-release > by-pkgid > 2a781e5f78e233aedaa1e51ed196dcc3 > files > 28

lib64zvbi-devel-0.2.35-5.mga6.x86_64.rpm

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.11"/>
<title>ZVBI Library: examples/pdc2.c</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectalign" style="padding-left: 0.5em;">
   <div id="projectname">ZVBI Library
   &#160;<span id="projectnumber">0.2.35</span>
   </div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.11 -->
  <div id="navrow1" class="tabs">
    <ul class="tablist">
      <li><a href="index.html"><span>Main&#160;Page</span></a></li>
      <li><a href="pages.html"><span>Related&#160;Pages</span></a></li>
      <li><a href="modules.html"><span>Modules</span></a></li>
      <li><a href="annotated.html"><span>Data&#160;Structures</span></a></li>
      <li><a href="examples.html"><span>Examples</span></a></li>
    </ul>
  </div>
</div><!-- top -->
<div class="header">
  <div class="headertitle">
<div class="title">examples/pdc2.c</div>  </div>
</div><!--header-->
<div class="contents">
<div class="fragment"><div class="line"><span class="comment">/*</span></div><div class="line"><span class="comment"> *  libzvbi VPS/PDC example 2</span></div><div class="line"><span class="comment"> *</span></div><div class="line"><span class="comment"> *  Copyright (C) 2009 Michael H. Schimek</span></div><div class="line"><span class="comment"> *</span></div><div class="line"><span class="comment"> *  Redistribution and use in source and binary forms, with or without</span></div><div class="line"><span class="comment"> *  modification, are permitted provided that the following conditions</span></div><div class="line"><span class="comment"> *  are met:</span></div><div class="line"><span class="comment"> *  1. Redistributions of source code must retain the above copyright</span></div><div class="line"><span class="comment"> *     notice, this list of conditions and the following disclaimer.</span></div><div class="line"><span class="comment"> *  2. Redistributions in binary form must reproduce the above copyright</span></div><div class="line"><span class="comment"> *     notice, this list of conditions and the following disclaimer in</span></div><div class="line"><span class="comment"> *     the documentation and/or other materials provided with the</span></div><div class="line"><span class="comment"> *     distribution.</span></div><div class="line"><span class="comment"> *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS</span></div><div class="line"><span class="comment"> *  &quot;AS IS&quot; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT</span></div><div class="line"><span class="comment"> *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR</span></div><div class="line"><span class="comment"> *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT</span></div><div class="line"><span class="comment"> *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,</span></div><div class="line"><span class="comment"> *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT</span></div><div class="line"><span class="comment"> *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,</span></div><div class="line"><span class="comment"> *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY</span></div><div class="line"><span class="comment"> *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT</span></div><div class="line"><span class="comment"> *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE</span></div><div class="line"><span class="comment"> *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</span></div><div class="line"><span class="comment"> */</span></div><div class="line"></div><div class="line"><span class="comment">/* $Id: pdc2.c,v 1.1 2009/03/23 01:30:39 mschimek Exp $ */</span></div><div class="line"></div><div class="line"><span class="comment">/* This example shows how to receive and decode VPS/PDC Program IDs.</span></div><div class="line"><span class="comment">   For simplicity channel change functions have been omitted and not</span></div><div class="line"><span class="comment">   all PDC features are supported. (A more complete example will be</span></div><div class="line"><span class="comment">   added later.)</span></div><div class="line"><span class="comment"></span></div><div class="line"><span class="comment">   To compile this program type:</span></div><div class="line"><span class="comment">   gcc -o pdc2 pdc2.c `pkg-config zvbi-0.2 --cflags --libs`</span></div><div class="line"><span class="comment"></span></div><div class="line"><span class="comment">   This program expects the starting date and time, ending time</span></div><div class="line"><span class="comment">   and VPS/PDC time of a TV program to record as arguments:</span></div><div class="line"><span class="comment">   ./pdc2  YYYY-MM-DD HH:MM  HH:MM  HH:MM</span></div><div class="line"><span class="comment"></span></div><div class="line"><span class="comment">   It opens a V4L2 device at /dev/vbi and scans the currently tuned in</span></div><div class="line"><span class="comment">   channel for a matching VPS/PDC label, logging the progress on</span></div><div class="line"><span class="comment">   standard output, without actually recording anything.</span></div><div class="line"><span class="comment"></span></div><div class="line"><span class="comment">   The -t option enables a test mode where the program reads VPS/PDC</span></div><div class="line"><span class="comment">   signal changes from standard input instead of opening a VBI</span></div><div class="line"><span class="comment">   device. See parse_test_file_line() for a description of the file</span></div><div class="line"><span class="comment">   format.</span></div><div class="line"><span class="comment">*/</span></div><div class="line"></div><div class="line"><span class="preprocessor">#define _GNU_SOURCE 1</span></div><div class="line"><span class="preprocessor">#undef NDEBUG</span></div><div class="line"></div><div class="line"><span class="preprocessor">#include &lt;stdio.h&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;stdlib.h&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;stdarg.h&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;string.h&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;float.h&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;math.h&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;time.h&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;locale.h&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;ctype.h&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;unistd.h&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;getopt.h&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;limits.h&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;errno.h&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;assert.h&gt;</span></div><div class="line"></div><div class="line"><span class="preprocessor">#include &lt;libzvbi.h&gt;</span></div><div class="line"></div><div class="line"><span class="preprocessor">#ifndef N_ELEMENTS</span></div><div class="line"><span class="preprocessor">#  define N_ELEMENTS(array) (sizeof (array) / sizeof (*(array)))</span></div><div class="line"><span class="preprocessor">#endif</span></div><div class="line"><span class="preprocessor">#ifndef MIN</span></div><div class="line"><span class="preprocessor">#  define MIN(x, y) ((x) &lt; (y) ? (x) : (y))</span></div><div class="line"><span class="preprocessor">#endif</span></div><div class="line"></div><div class="line"><span class="keyword">static</span> <a name="_a0"></a><a class="code" href="structvbi__capture.html">vbi_capture</a> *            cap;</div><div class="line"><span class="keyword">static</span> <a name="_a1"></a><a class="code" href="structvbi__decoder.html">vbi_decoder</a> *            dec;</div><div class="line"><span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">char</span> *             dev_name;</div><div class="line"><span class="keyword">static</span> vbi_bool                 quit;</div><div class="line"><span class="keyword">static</span> <span class="keywordtype">int</span>                      exit_code;</div><div class="line"></div><div class="line"><span class="comment">/* The current time of the intended audience of the tuned in network</span></div><div class="line"><span class="comment">   according to the network (see VBI_EVENT_LOCAL_TIME). It may differ</span></div><div class="line"><span class="comment">   from system time if the system is not in sync with UTC or if we</span></div><div class="line"><span class="comment">   receive the TV signal with a delay. */</span></div><div class="line"><span class="keyword">static</span> time_t                   audience_time;</div><div class="line"></div><div class="line"><span class="comment">/* The system time in seconds when the most recent PDC signal was</span></div><div class="line"><span class="comment">   received. */</span></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">double</span>                   timestamp;</div><div class="line"></div><div class="line"><span class="comment">/* PDC Label Channel state. */</span></div><div class="line"><span class="keyword">struct </span>lc_state {</div><div class="line">        <span class="comment">/* The PIL most recently received on this LC, zero if none. */</span></div><div class="line">        <a class="code" href="group__ProgramID.html#ga870eeecedc6aed609b9f53d4dbe0f6c7">vbi_pil</a>                         pil;</div><div class="line"></div><div class="line">        <span class="comment">/* The system time in seconds when the PIL was most recently</span></div><div class="line"><span class="comment">           received. */</span></div><div class="line">        <span class="keywordtype">double</span>                          last_at;</div><div class="line">};</div><div class="line"></div><div class="line"><span class="comment">/* The most recently received PILs. */</span></div><div class="line"><span class="keyword">static</span> <span class="keyword">struct </span>lc_state          lc_state[VBI_MAX_PID_CHANNELS];</div><div class="line"></div><div class="line"><span class="comment">/* Video recorder states. */</span></div><div class="line"><span class="keyword">enum</span> vcr_state {</div><div class="line">        <span class="comment">/* All capturing stopped. */</span></div><div class="line">        VCR_STATE_STBY,</div><div class="line"></div><div class="line">        <span class="comment">/* Searching for a PDC signal. */</span></div><div class="line">        VCR_STATE_SCAN,</div><div class="line"></div><div class="line">        <span class="comment">/* Preparing to record. */</span></div><div class="line">        VCR_STATE_PTR,</div><div class="line"></div><div class="line">        <span class="comment">/* Recording a program. */</span></div><div class="line">        VCR_STATE_REC</div><div class="line">};</div><div class="line"></div><div class="line"><span class="comment">/* The current video recorder state. */</span></div><div class="line"><span class="keyword">static</span> <span class="keyword">enum</span> vcr_state           vcr_state;</div><div class="line"></div><div class="line"><span class="comment">/* The system time in seconds at the last change of vcr_state. */</span></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">double</span>                   vcr_state_since;</div><div class="line"></div><div class="line"><span class="comment">/* In timer control mode we start and stop recording at the scheduled</span></div><div class="line"><span class="comment">   times. Timer control mode is enabled when the network does not</span></div><div class="line"><span class="comment">   transmit program IDs or when we lost all PDC signals. */</span></div><div class="line"><span class="keyword">static</span> vbi_bool                 timer_control_mode;</div><div class="line"></div><div class="line"><span class="comment">/* In VCR_STATE_REC this variable stops recording with a 30 second</span></div><div class="line"><span class="comment">   delay as required by EN 300 231. This is a system time in</span></div><div class="line"><span class="comment">   seconds, or DBL_MAX if no stop is planned. */</span></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">double</span>                   delayed_stop_at;</div><div class="line"></div><div class="line"><span class="comment">/* In VCR_REC_STATE if delayed_stop_at &lt; DBL_MAX, delayed_stop_pid</span></div><div class="line"><span class="comment">   contains a copy of the program ID which caused the delayed stop.</span></div><div class="line"><span class="comment"></span></div><div class="line"><span class="comment">   If delayed_stop_pid.luf == 1 the program will continue on the</span></div><div class="line"><span class="comment">   channel with delayed_stop_pid.cni, accompanied by</span></div><div class="line"><span class="comment">   delayed_stop_pid.pil (which may also provide a new start date and</span></div><div class="line"><span class="comment">   time for the schedule).</span></div><div class="line"><span class="comment"></span></div><div class="line"><span class="comment">   Otherwise delayed_stop_pid.pil can be a valid PIL, a RI/T or INT</span></div><div class="line"><span class="comment">   service code, or zero if a loss of the PDC signal or service caused</span></div><div class="line"><span class="comment">   the delayed stop. */</span></div><div class="line"><span class="keyword">static</span> <a name="_a2"></a><a class="code" href="structvbi__program__id.html">vbi_program_id</a>           delayed_stop_pid;</div><div class="line"></div><div class="line"><span class="comment">/* A program to be recorded. */</span></div><div class="line"><span class="keyword">struct </span>program {</div><div class="line">        <span class="keyword">struct </span>program *        next;</div><div class="line"></div><div class="line">        <span class="comment">/* A number in lieu of a title. */</span></div><div class="line">        <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span>            index;</div><div class="line"></div><div class="line">        <span class="comment">/* The most recently announced start and end time of the</span></div><div class="line"><span class="comment">           program (&quot;AT-1&quot; in EN 300 231 in parlance), in case we do</span></div><div class="line"><span class="comment">           not receive a PDC signal. When the duration of the program</span></div><div class="line"><span class="comment">           is unknown start_time == end_time. end_time is</span></div><div class="line"><span class="comment">           exclusive. */</span></div><div class="line">        time_t                  start_time;</div><div class="line">        time_t                  end_time;</div><div class="line"></div><div class="line">        <span class="comment">/* The expected Program Identification Label. Usually this is</span></div><div class="line"><span class="comment">           the originally announced start date and time of the program</span></div><div class="line"><span class="comment">           (&quot;AT-2&quot; in EN 300 231), relative to the time zone of the</span></div><div class="line"><span class="comment">           intended audience. */</span></div><div class="line">        <a class="code" href="group__ProgramID.html#ga870eeecedc6aed609b9f53d4dbe0f6c7">vbi_pil</a>                 pil;</div><div class="line"></div><div class="line">        <span class="comment">/* The validity window of pil, that is the time when the</span></div><div class="line"><span class="comment">           network can be expected to transmit the PIL. Usually from</span></div><div class="line"><span class="comment">           00:00 on the same day to 04:00 on the next</span></div><div class="line"><span class="comment">           day. pil_valid_end is exclusive. */</span></div><div class="line">        time_t                  pil_valid_start;</div><div class="line">        time_t                  pil_valid_end;</div><div class="line"></div><div class="line">        <span class="comment">/* Recording is in progress or was interrupted. */</span></div><div class="line">        vbi_bool                continues;</div><div class="line">};</div><div class="line"></div><div class="line"><span class="comment">/* The recording schedule, a singly-linked list of program</span></div><div class="line"><span class="comment">   structures. */</span></div><div class="line"><span class="keyword">static</span> <span class="keyword">struct </span>program *         schedule;</div><div class="line"></div><div class="line"><span class="comment">/* In VCR_STATE_PTR and VCR_STATE_REC the program we (are about to)</span></div><div class="line"><span class="comment">   record, a pointer into the schedule list. Otherwise NULL. */</span></div><div class="line"><span class="keyword">static</span> <span class="keyword">struct </span>program *         curr_program;</div><div class="line"></div><div class="line"><span class="comment">/* If curr_program != NULL this variable contains a copy of the</span></div><div class="line"><span class="comment">   program ID which put us into PTR or REC state. If recording was</span></div><div class="line"><span class="comment">   started by the timer curr_pid.pil is zero. */</span></div><div class="line"><span class="keyword">static</span> <a class="code" href="structvbi__program__id.html">vbi_program_id</a>           curr_pid;</div><div class="line"></div><div class="line"><span class="keyword">static</span> vbi_bool                 test_mode;</div><div class="line"></div><div class="line"><span class="comment">/* In test mode this is the expected VCR state after the most recent</span></div><div class="line"><span class="comment">   PDC signal change. */</span></div><div class="line"><span class="keyword">static</span> <span class="keyword">enum</span> vcr_state           test_exp_vcr_state;</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">double</span></div><div class="line">signal_timeout [<a name="a3"></a><a class="code" href="group__ProgramID.html#gga289ec10e87cef7655799144bc898f262a4d686ec8bbbcbac78fb4526374cecb01">VBI_MAX_PID_CHANNELS</a>] = {</div><div class="line">        [<a name="a4"></a><a class="code" href="group__ProgramID.html#gga289ec10e87cef7655799144bc898f262a51a53db4366781f100d5d02836d6452e">VBI_PID_CHANNEL_LCI_0</a>] = 2,</div><div class="line">        [<a name="a5"></a><a class="code" href="group__ProgramID.html#gga289ec10e87cef7655799144bc898f262afdd62439879c03c78fce236bf7dcc081">VBI_PID_CHANNEL_LCI_1</a>] = 2,</div><div class="line">        [<a name="a6"></a><a class="code" href="group__ProgramID.html#gga289ec10e87cef7655799144bc898f262ac9a4d6e6932f0f4fd2a19f71f07f4447">VBI_PID_CHANNEL_LCI_2</a>] = 2,</div><div class="line">        [<a name="a7"></a><a class="code" href="group__ProgramID.html#gga289ec10e87cef7655799144bc898f262a969d34250cbd4e60539740cc4f3398f1">VBI_PID_CHANNEL_LCI_3</a>] = 2,</div><div class="line"></div><div class="line">        <span class="comment">/* VPS signals have no error protection. When the payload</span></div><div class="line"><span class="comment">           changes, libzvbi will wait for one repetition to confirm</span></div><div class="line"><span class="comment">           correct reception. */</span></div><div class="line">        [<a name="a8"></a><a class="code" href="group__ProgramID.html#gga289ec10e87cef7655799144bc898f262a232efb61f9f576d83a778ad18b90e296">VBI_PID_CHANNEL_VPS</a>] = 3 / 25.0,</div><div class="line"></div><div class="line">        <span class="comment">/* Other channels not implemented yet. */</span></div><div class="line">};</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">double</span></div><div class="line">signal_period [<a class="code" href="group__ProgramID.html#gga289ec10e87cef7655799144bc898f262a4d686ec8bbbcbac78fb4526374cecb01">VBI_MAX_PID_CHANNELS</a>] = {</div><div class="line">        <span class="comment">/* EN 300 231 Section 8.3: &quot;In the case of the packet 8/30</span></div><div class="line"><span class="comment">           version (Method B) the repetition rate of labels in any</span></div><div class="line"><span class="comment">           label data channel is once per second.&quot; Section E.2: &quot;Where</span></div><div class="line"><span class="comment">           more than one label channel is in use the signalling rate</span></div><div class="line"><span class="comment">           is normally one line per label channel per second.&quot; */</span></div><div class="line">        [<a class="code" href="group__ProgramID.html#gga289ec10e87cef7655799144bc898f262a51a53db4366781f100d5d02836d6452e">VBI_PID_CHANNEL_LCI_0</a>] = 1,</div><div class="line">        [<a class="code" href="group__ProgramID.html#gga289ec10e87cef7655799144bc898f262afdd62439879c03c78fce236bf7dcc081">VBI_PID_CHANNEL_LCI_1</a>] = 1,</div><div class="line">        [<a class="code" href="group__ProgramID.html#gga289ec10e87cef7655799144bc898f262ac9a4d6e6932f0f4fd2a19f71f07f4447">VBI_PID_CHANNEL_LCI_2</a>] = 1,</div><div class="line">        [<a class="code" href="group__ProgramID.html#gga289ec10e87cef7655799144bc898f262a969d34250cbd4e60539740cc4f3398f1">VBI_PID_CHANNEL_LCI_3</a>] = 1,</div><div class="line"></div><div class="line">        [<a class="code" href="group__ProgramID.html#gga289ec10e87cef7655799144bc898f262a232efb61f9f576d83a778ad18b90e296">VBI_PID_CHANNEL_VPS</a>] = 1 / 25.0,</div><div class="line"></div><div class="line">        <span class="comment">/* Other channels not implemented yet. */</span></div><div class="line">};</div><div class="line"></div><div class="line"><span class="comment">/* For debugging. */</span></div><div class="line"><span class="preprocessor">#define D printf (&quot;%s:%u\n&quot;, __FILE__, __LINE__)</span></div><div class="line"></div><div class="line"><span class="comment">/* For debugging. */</span></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span></div><div class="line">print_time                      (time_t                 time)</div><div class="line">{</div><div class="line">        <span class="keywordtype">char</span> buffer[80];</div><div class="line">        <span class="keyword">struct </span>tm tm;</div><div class="line"></div><div class="line">        memset (&amp;tm, 0, <span class="keyword">sizeof</span> (tm));</div><div class="line">        localtime_r (&amp;time, &amp;tm);</div><div class="line">        strftime (buffer, <span class="keyword">sizeof</span> (buffer),</div><div class="line">                  <span class="stringliteral">&quot;%Y-%m-%d %H:%M:%S %Z = &quot;</span>, &amp;tm);</div><div class="line">        fputs (buffer, stdout);</div><div class="line"></div><div class="line">        memset (&amp;tm, 0, <span class="keyword">sizeof</span> (tm));</div><div class="line">        gmtime_r (&amp;time, &amp;tm);</div><div class="line">        strftime (buffer, <span class="keyword">sizeof</span> (buffer),</div><div class="line">                  <span class="stringliteral">&quot;%Y-%m-%d %H:%M:%S UTC&quot;</span>, &amp;tm);</div><div class="line">        puts (buffer);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="comment">/* Attention! This function returns a static string. */</span></div><div class="line"><span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">char</span> *</div><div class="line">pil_str                         (<a class="code" href="group__ProgramID.html#ga870eeecedc6aed609b9f53d4dbe0f6c7">vbi_pil</a>                pil)</div><div class="line">{</div><div class="line">        <span class="keyword">static</span> <span class="keywordtype">char</span> buffer[32];</div><div class="line"></div><div class="line">        <span class="keywordflow">switch</span> (pil) {</div><div class="line">        <span class="keywordflow">case</span> <a name="a9"></a><a class="code" href="group__ProgramID.html#gga05589fbab0657f08285ebdfe93f5ec9eae7cbef095ebb79470785785bebdb2f8d">VBI_PIL_TIMER_CONTROL</a>:     <span class="keywordflow">return</span> <span class="stringliteral">&quot;TC&quot;</span>;</div><div class="line">        <span class="keywordflow">case</span> <a name="a10"></a><a class="code" href="group__ProgramID.html#gga05589fbab0657f08285ebdfe93f5ec9eaad30c6505f26ef2b6e26626afdff02dd">VBI_PIL_INHIBIT_TERMINATE</a>: <span class="keywordflow">return</span> <span class="stringliteral">&quot;RI/T&quot;</span>;</div><div class="line">        <span class="keywordflow">case</span> <a name="a11"></a><a class="code" href="group__ProgramID.html#gga05589fbab0657f08285ebdfe93f5ec9ea835908e1f719f7761589ac1f3b968cb4">VBI_PIL_INTERRUPTION</a>:      <span class="keywordflow">return</span> <span class="stringliteral">&quot;INT&quot;</span>;</div><div class="line">        <span class="keywordflow">case</span> <a name="a12"></a><a class="code" href="group__ProgramID.html#gga05589fbab0657f08285ebdfe93f5ec9ea4084b4cb78ad4667f7645101adebb3e1">VBI_PIL_CONTINUE</a>:          <span class="keywordflow">return</span> <span class="stringliteral">&quot;CONT&quot;</span>;</div><div class="line"></div><div class="line">        <span class="keywordflow">case</span> <a name="a13"></a><a class="code" href="group__ProgramID.html#gga05589fbab0657f08285ebdfe93f5ec9eac9b7c435e58a2f76a87f1acb221630f9">VBI_PIL_NSPV</a>:</div><div class="line">                <span class="comment">/* NSVP service code if source is VPS/PDC,</span></div><div class="line"><span class="comment">                   END code if source is XDS. */</span></div><div class="line">                <span class="keywordflow">return</span> <span class="stringliteral">&quot;NSPV/END&quot;</span>;</div><div class="line"></div><div class="line">        <span class="keywordflow">default</span>:</div><div class="line">                snprintf (buffer, <span class="keyword">sizeof</span> (buffer),</div><div class="line">                          <span class="stringliteral">&quot;%02u%02uT%02u%02u&quot;</span>,</div><div class="line">                          <a name="a14"></a><a class="code" href="group__ProgramID.html#gaae3974c3e680d42322edaad37b35ebcc">VBI_PIL_MONTH</a> (pil),</div><div class="line">                          <a name="a15"></a><a class="code" href="group__ProgramID.html#ga138a4f95542c36527f6df6ee08094f2f">VBI_PIL_DAY</a> (pil),</div><div class="line">                          <a name="a16"></a><a class="code" href="group__ProgramID.html#ga78d71b2b88dd3729e5364f6061000ebf">VBI_PIL_HOUR</a> (pil),</div><div class="line">                          <a name="a17"></a><a class="code" href="group__ProgramID.html#gaacada356d88add876dc7484892231e73">VBI_PIL_MINUTE</a> (pil));</div><div class="line"></div><div class="line">                <span class="keywordflow">return</span> buffer;</div><div class="line">        }</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span></div><div class="line">msg                             (<span class="keyword">const</span> <span class="keywordtype">char</span> *           templ,</div><div class="line">                                 ...)</div><div class="line">{</div><div class="line">        va_list ap;</div><div class="line"></div><div class="line">        va_start (ap, templ);</div><div class="line"></div><div class="line">        <span class="keywordflow">if</span> (test_mode) {</div><div class="line">                <span class="keywordtype">char</span> buffer[80];</div><div class="line">                <span class="keyword">struct </span>tm tm;</div><div class="line"></div><div class="line">                memset (&amp;tm, 0, <span class="keyword">sizeof</span> (tm));</div><div class="line">                localtime_r (&amp;audience_time, &amp;tm);</div><div class="line">                strftime (buffer, <span class="keyword">sizeof</span> (buffer), <span class="stringliteral">&quot;%Y%m%dT%H%M%S &quot;</span>, &amp;tm);</div><div class="line">                fputs (buffer, stdout);</div><div class="line">        }</div><div class="line"></div><div class="line">        vprintf (templ, ap);</div><div class="line"></div><div class="line">        va_end (ap);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span></div><div class="line">remove_program_from_schedule    (<span class="keyword">struct</span> program *       p)</div><div class="line">{</div><div class="line">        <span class="keyword">struct </span>program **pp;</div><div class="line"></div><div class="line">        <span class="keywordflow">if</span> (p == curr_program) {</div><div class="line">                assert (quit</div><div class="line">                        || VCR_STATE_STBY == vcr_state</div><div class="line">                        || VCR_STATE_SCAN == vcr_state);</div><div class="line"></div><div class="line">                curr_program = NULL;</div><div class="line">        }</div><div class="line"></div><div class="line">        <span class="keywordflow">for</span> (pp = &amp;schedule; NULL != *pp; pp = &amp;(*pp)-&gt;next) {</div><div class="line">                <span class="keywordflow">if</span> (*pp == p) {</div><div class="line">                        *pp = p-&gt;next;</div><div class="line">                        free (p);</div><div class="line">                        <span class="keywordflow">break</span>;</div><div class="line">                }</div><div class="line">        }</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span></div><div class="line">remove_stale_programs_from_schedule (<span class="keywordtype">void</span>)</div><div class="line">{</div><div class="line">        <span class="keyword">struct </span>program *p;</div><div class="line">        <span class="keyword">struct </span>program *p_next;</div><div class="line"></div><div class="line">        <span class="keywordflow">for</span> (p = schedule; NULL != p; p = p_next) {</div><div class="line">                p_next = p-&gt;next;</div><div class="line"></div><div class="line">                <span class="keywordflow">if</span> (audience_time &gt;= p-&gt;end_time</div><div class="line">                    &amp;&amp; audience_time &gt;= p-&gt;pil_valid_end) {</div><div class="line">                        msg (<span class="stringliteral">&quot;PIL %s no longer valid, &quot;</span></div><div class="line">                             <span class="stringliteral">&quot;removing program %u from schedule.\n&quot;</span>,</div><div class="line">                             pil_str (p-&gt;pil), p-&gt;index);</div><div class="line">                        remove_program_from_schedule (p);</div><div class="line">                }</div><div class="line">        }</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keyword">struct </span>program *</div><div class="line">find_program_by_pil             (<a class="code" href="group__ProgramID.html#ga870eeecedc6aed609b9f53d4dbe0f6c7">vbi_pil</a>                pil)</div><div class="line">{</div><div class="line">        <span class="keyword">struct </span>program *p;</div><div class="line"></div><div class="line">        <span class="keywordflow">for</span> (p = schedule; NULL != p; p = p-&gt;next) {</div><div class="line">                <span class="keywordflow">if</span> (pil == p-&gt;pil)</div><div class="line">                        <span class="keywordflow">return</span> p;</div><div class="line">        }</div><div class="line"></div><div class="line">        <span class="keywordflow">return</span> NULL;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">char</span> *</div><div class="line">vcr_state_name                  (<span class="keyword">enum</span> vcr_state         state)</div><div class="line">{</div><div class="line">        <span class="keywordflow">switch</span> (state) {</div><div class="line"><span class="preprocessor">#define CASE(x) case VCR_STATE_ ## x: return #x;</span></div><div class="line">        CASE (STBY)</div><div class="line">        CASE (SCAN)</div><div class="line">        CASE (PTR)</div><div class="line">        CASE (REC)</div><div class="line"><span class="preprocessor">#undef CASE</span></div><div class="line">        }</div><div class="line"></div><div class="line">        assert (0);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span></div><div class="line">change_vcr_state                (<span class="keyword">enum</span> vcr_state         new_state)</div><div class="line">{</div><div class="line">        <span class="keywordflow">if</span> (new_state == vcr_state)</div><div class="line">                <span class="keywordflow">return</span>;</div><div class="line"></div><div class="line">        msg (<span class="stringliteral">&quot;VCR state %s -&gt; %s.\n&quot;</span>,</div><div class="line">             vcr_state_name (vcr_state),</div><div class="line">             vcr_state_name (new_state));</div><div class="line"></div><div class="line">        vcr_state = new_state;</div><div class="line">        vcr_state_since = timestamp;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> vbi_bool</div><div class="line">teletext_8302_available         (<span class="keywordtype">void</span>)</div><div class="line">{</div><div class="line">        <span class="keywordflow">return</span> (0 != (lc_state[<a class="code" href="group__ProgramID.html#gga289ec10e87cef7655799144bc898f262a51a53db4366781f100d5d02836d6452e">VBI_PID_CHANNEL_LCI_0</a>].pil |</div><div class="line">                      lc_state[<a class="code" href="group__ProgramID.html#gga289ec10e87cef7655799144bc898f262afdd62439879c03c78fce236bf7dcc081">VBI_PID_CHANNEL_LCI_1</a>].pil |</div><div class="line">                      lc_state[<a class="code" href="group__ProgramID.html#gga289ec10e87cef7655799144bc898f262ac9a4d6e6932f0f4fd2a19f71f07f4447">VBI_PID_CHANNEL_LCI_2</a>].pil |</div><div class="line">                      lc_state[<a class="code" href="group__ProgramID.html#gga289ec10e87cef7655799144bc898f262a969d34250cbd4e60539740cc4f3398f1">VBI_PID_CHANNEL_LCI_3</a>].pil));</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span></div><div class="line">disable_timer_control           (<span class="keywordtype">void</span>)</div><div class="line">{</div><div class="line">        <span class="keywordflow">if</span> (!timer_control_mode)</div><div class="line">                <span class="keywordflow">return</span>;</div><div class="line">        msg (<span class="stringliteral">&quot;Leaving timer control mode.\n&quot;</span>);</div><div class="line">        timer_control_mode = FALSE;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span></div><div class="line">enable_timer_control            (<span class="keywordtype">void</span>)</div><div class="line">{</div><div class="line">        <span class="keywordflow">if</span> (timer_control_mode)</div><div class="line">                <span class="keywordflow">return</span>;</div><div class="line">        msg (<span class="stringliteral">&quot;Entering timer control mode.\n&quot;</span>);</div><div class="line">        timer_control_mode = TRUE;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span></div><div class="line">stop_recording_now              (<span class="keywordtype">void</span>)</div><div class="line">{</div><div class="line">        assert (VCR_STATE_REC == vcr_state);</div><div class="line"></div><div class="line">        msg (<span class="stringliteral">&quot;Program %u ended according to %s%s.\n&quot;</span>,</div><div class="line">             curr_program-&gt;index,</div><div class="line">             timer_control_mode ? <span class="stringliteral">&quot;schedule&quot;</span> : <span class="stringliteral">&quot;VPS/PDC signal&quot;</span>,</div><div class="line">             (delayed_stop_at &lt; DBL_MAX) ? <span class="stringliteral">&quot; with delay&quot;</span> : <span class="stringliteral">&quot;&quot;</span>);</div><div class="line"></div><div class="line">        change_vcr_state (VCR_STATE_SCAN);</div><div class="line"></div><div class="line">        delayed_stop_at = DBL_MAX;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span></div><div class="line">stop_recording_in_30s           (<span class="keyword">const</span> <a class="code" href="structvbi__program__id.html">vbi_program_id</a> * pid)</div><div class="line">{</div><div class="line">        assert (VCR_STATE_REC == vcr_state);</div><div class="line"></div><div class="line">        <span class="comment">/* What triggered the stop. */</span></div><div class="line">        <span class="keywordflow">if</span> (NULL == pid) {</div><div class="line">                <span class="comment">/* Signal lost. */</span></div><div class="line">                memset (&amp;delayed_stop_pid, 0,</div><div class="line">                        <span class="keyword">sizeof</span> (delayed_stop_pid));</div><div class="line">        } <span class="keywordflow">else</span> {</div><div class="line">                delayed_stop_pid = *pid;</div><div class="line">        }</div><div class="line"></div><div class="line">        <span class="comment">/* If we stop because the PIL is no longer transmitted we may</span></div><div class="line"><span class="comment">           need one second to realize (e.g. receiving LCI 0 at time t,</span></div><div class="line"><span class="comment">           LCI 1 at t + 0.2, then LCI 0 at t + 1, and again LCI 0 at</span></div><div class="line"><span class="comment">           t + 2 seconds) so we start counting 30 seconds not from</span></div><div class="line"><span class="comment">           the current time (t + 2) but the first time the label was</span></div><div class="line"><span class="comment">           missing (t + 1). */</span></div><div class="line">        <span class="keywordflow">if</span> (NULL == pid &amp;&amp; 0 != curr_pid.<a name="a18"></a><a class="code" href="structvbi__program__id.html#a30c0862c008de112f4222e1208038d58">pil</a>) {</div><div class="line">                delayed_stop_at = lc_state[curr_pid.<a name="a19"></a><a class="code" href="structvbi__program__id.html#a90794327986da193ddb76d518331589d">channel</a>].last_at + 31;</div><div class="line">        } <span class="keywordflow">else</span> {</div><div class="line">                delayed_stop_at = timestamp + 30;</div><div class="line">        }</div><div class="line"></div><div class="line">        msg (<span class="stringliteral">&quot;Will stop recording in %d seconds.\n&quot;</span>,</div><div class="line">             (<span class="keywordtype">int</span>)(delayed_stop_at - timestamp));</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span></div><div class="line">start_recording_by_pil          (<span class="keyword">struct</span> program *       p,</div><div class="line">                                 <span class="keyword">const</span> <a class="code" href="structvbi__program__id.html">vbi_program_id</a> * pid)</div><div class="line">{</div><div class="line">        assert (!timer_control_mode);</div><div class="line">        assert (VCR_STATE_SCAN == vcr_state</div><div class="line">                || VCR_STATE_PTR == vcr_state);</div><div class="line"></div><div class="line">        msg (<span class="stringliteral">&quot;Recording program %u using VPS/PDC signal.\n&quot;</span>,</div><div class="line">             p-&gt;index);</div><div class="line"></div><div class="line">        <span class="comment">/* EN 300 231 Section 9.4.1: &quot;[When] labels are not received</span></div><div class="line"><span class="comment">           correctly during a recording, the recording will be</span></div><div class="line"><span class="comment">           continued for the computed duration following the actual</span></div><div class="line"><span class="comment">           start time&quot; */</span></div><div class="line">        <span class="keywordflow">if</span> (!p-&gt;continues) {</div><div class="line">                p-&gt;end_time += audience_time - p-&gt;start_time;</div><div class="line">                p-&gt;start_time = audience_time;</div><div class="line">                p-&gt;continues = TRUE;</div><div class="line">        }</div><div class="line"></div><div class="line">        change_vcr_state (VCR_STATE_REC);</div><div class="line"></div><div class="line">        curr_program = p;</div><div class="line">        curr_pid = *pid;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span></div><div class="line">prepare_to_record_by_pil        (<span class="keyword">struct</span> program *       p,</div><div class="line">                                 <span class="keyword">const</span> <a class="code" href="structvbi__program__id.html">vbi_program_id</a> * pid)</div><div class="line">{</div><div class="line">        assert (!timer_control_mode);</div><div class="line">        assert (VCR_STATE_SCAN == vcr_state);</div><div class="line"></div><div class="line">        change_vcr_state (VCR_STATE_PTR);</div><div class="line"></div><div class="line">        curr_program = p;</div><div class="line">        curr_pid = *pid;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span></div><div class="line">start_recording_by_timer        (<span class="keyword">struct</span> program *       p)</div><div class="line">{</div><div class="line">        assert (timer_control_mode);</div><div class="line">        assert (VCR_STATE_SCAN == vcr_state);</div><div class="line"></div><div class="line">        msg (<span class="stringliteral">&quot;Recording program %u using timer.\n&quot;</span>,</div><div class="line">             p-&gt;index);</div><div class="line"></div><div class="line">        change_vcr_state (VCR_STATE_REC);</div><div class="line"></div><div class="line">        curr_program = p;</div><div class="line">        memset (&amp;curr_pid, 0, <span class="keyword">sizeof</span> (curr_pid));</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span></div><div class="line">remove_program_if_ended         (<span class="keyword">struct</span> program *       p,</div><div class="line">                                 <span class="keyword">const</span> <a class="code" href="structvbi__program__id.html">vbi_program_id</a> * pid)</div><div class="line">{</div><div class="line">        <span class="keywordflow">if</span> (timer_control_mode) {</div><div class="line">                <span class="comment">/* We don&#39;t know if the program really ends now, so we</span></div><div class="line"><span class="comment">                   keep it scheduled until curr_program-&gt;pil_valid_end</span></div><div class="line"><span class="comment">                   in case we receive its PIL after all. */</span></div><div class="line">                <span class="keywordflow">return</span>;</div><div class="line">        } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (NULL != pid &amp;&amp; <a class="code" href="group__ProgramID.html#gga05589fbab0657f08285ebdfe93f5ec9ea835908e1f719f7761589ac1f3b968cb4">VBI_PIL_INTERRUPTION</a> == pid-&gt;<a class="code" href="structvbi__program__id.html#a30c0862c008de112f4222e1208038d58">pil</a>) {</div><div class="line">                <span class="comment">/* The program pauses, will not be removed. */</span></div><div class="line">                <span class="keywordflow">return</span>;</div><div class="line">        } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (NULL != pid &amp;&amp; pid-&gt;<a name="a20"></a><a class="code" href="structvbi__program__id.html#abdd578b10dfa50e422cf90f200899d84">luf</a>) {</div><div class="line">                <span class="comment">/* The program has been rescheduled to another date,</span></div><div class="line"><span class="comment">                   we don&#39;t care in this example. */</span></div><div class="line">        }</div><div class="line"></div><div class="line">        <span class="comment">/* Objective accomplished. */</span></div><div class="line">        remove_program_from_schedule (p);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span></div><div class="line">signal_or_service_lost          (<span class="keywordtype">void</span>)</div><div class="line">{</div><div class="line">        <span class="keyword">struct </span>program *p;</div><div class="line"></div><div class="line">        <span class="keywordflow">if</span> (timer_control_mode)</div><div class="line">                <span class="keywordflow">return</span>;</div><div class="line"></div><div class="line">        enable_timer_control ();</div><div class="line"></div><div class="line">        <span class="keywordflow">switch</span> (vcr_state) {</div><div class="line">        <span class="keywordflow">case</span> VCR_STATE_STBY:</div><div class="line">                assert (0);</div><div class="line"></div><div class="line">        <span class="keywordflow">case</span> VCR_STATE_SCAN:</div><div class="line">                <span class="keywordflow">break</span>;</div><div class="line"></div><div class="line">        <span class="keywordflow">case</span> VCR_STATE_PTR:</div><div class="line">                p = curr_program;</div><div class="line"></div><div class="line">                <span class="comment">/* According to EN 300 231 Section E.1 and Section E.3</span></div><div class="line"><span class="comment">                   Example 12 the program should begin within one</span></div><div class="line"><span class="comment">                   minute when PRF=1, so we start recording now. We</span></div><div class="line"><span class="comment">                   will stop by PIL if we pick up a VPS or Teletext</span></div><div class="line"><span class="comment">                   signal again before curr_program-&gt;end_time, but we</span></div><div class="line"><span class="comment">                   will not return to VCR_STATE_PTR if PRF is still</span></div><div class="line"><span class="comment">                   1. */</span></div><div class="line">                msg (<span class="stringliteral">&quot;Recording program %u using lost &quot;</span></div><div class="line">                     <span class="stringliteral">&quot;PDC signal with PRF=1.\n&quot;</span>,</div><div class="line">                     p-&gt;index);</div><div class="line"></div><div class="line">                <span class="comment">/* Record for the scheduled duration... */</span></div><div class="line">                p-&gt;end_time = p-&gt;end_time - p-&gt;start_time + audience_time;</div><div class="line">                <span class="comment">/* ...plus one minute since PRF was set. */</span></div><div class="line">                p-&gt;end_time += 60 - MIN (vcr_state_since - timestamp,</div><div class="line">                                         60.0);</div><div class="line">                p-&gt;start_time = audience_time;</div><div class="line"></div><div class="line">                change_vcr_state (VCR_STATE_REC);</div><div class="line"></div><div class="line">                <span class="comment">/* Now recording by timer. */</span></div><div class="line">                memset (&amp;curr_pid, 0, <span class="keyword">sizeof</span> (curr_pid));</div><div class="line"></div><div class="line">                <span class="keywordflow">break</span>;</div><div class="line"></div><div class="line">        <span class="keywordflow">case</span> VCR_STATE_REC:</div><div class="line">                <span class="keywordflow">if</span> (delayed_stop_at &lt; DBL_MAX) {</div><div class="line">                        msg (<span class="stringliteral">&quot;PDC signal lost; already stopping in &quot;</span></div><div class="line">                             <span class="stringliteral">&quot;%d seconds.\n&quot;</span>,</div><div class="line">                             (<span class="keywordtype">int</span>)(delayed_stop_at - timestamp));</div><div class="line">                } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (curr_program-&gt;start_time</div><div class="line">                           == curr_program-&gt;end_time) {</div><div class="line">                        <span class="comment">/* Since we don&#39;t know the program duration,</span></div><div class="line"><span class="comment">                           we cannot record under timer control. We</span></div><div class="line"><span class="comment">                           stop recording in 30 seconds as shown in EN</span></div><div class="line"><span class="comment">                           300 231 Annex E.3, Example 11, 16:20:10,</span></div><div class="line"><span class="comment">                           but with an extra twist: If we receive</span></div><div class="line"><span class="comment">                           curr_program-&gt;pil again within those 30</span></div><div class="line"><span class="comment">                           seconds the stop will be canceled. */</span></div><div class="line">                        stop_recording_in_30s (<span class="comment">/* pid */</span> NULL);</div><div class="line">                } <span class="keywordflow">else</span> {</div><div class="line">                        <span class="comment">/* Keep recording by timer. */</span></div><div class="line">                        memset (&amp;curr_pid, 0, <span class="keyword">sizeof</span> (curr_pid));</div><div class="line">                }</div><div class="line"></div><div class="line">                <span class="keywordflow">break</span>;</div><div class="line">        }</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span></div><div class="line">pil_no_longer_transmitted       (<span class="keyword">const</span> <a class="code" href="structvbi__program__id.html">vbi_program_id</a> * pid)</div><div class="line">{</div><div class="line">        vbi_bool mi;</div><div class="line"></div><div class="line">        <span class="keywordflow">switch</span> (vcr_state) {</div><div class="line">        <span class="keywordflow">case</span> VCR_STATE_STBY:</div><div class="line">        <span class="keywordflow">case</span> VCR_STATE_SCAN:</div><div class="line">                assert (0);</div><div class="line"></div><div class="line">        <span class="keywordflow">case</span> VCR_STATE_PTR:</div><div class="line">                assert (!timer_control_mode);</div><div class="line"></div><div class="line">                msg (<span class="stringliteral">&quot;PIL %s is no longer present on LC %u.\n&quot;</span>,</div><div class="line">                     pil_str (curr_program-&gt;pil),</div><div class="line">                     curr_pid.<a class="code" href="structvbi__program__id.html#a90794327986da193ddb76d518331589d">channel</a>);</div><div class="line"></div><div class="line">                change_vcr_state (VCR_STATE_SCAN);</div><div class="line"></div><div class="line">                <span class="keywordflow">return</span>;</div><div class="line"></div><div class="line">        <span class="keywordflow">case</span> VCR_STATE_REC:</div><div class="line">                assert (!timer_control_mode);</div><div class="line"></div><div class="line">                msg (<span class="stringliteral">&quot;PIL %s is no longer present on LC %u.\n&quot;</span>,</div><div class="line">                     pil_str (curr_program-&gt;pil),</div><div class="line">                     curr_pid.<a class="code" href="structvbi__program__id.html#a90794327986da193ddb76d518331589d">channel</a>);</div><div class="line"></div><div class="line">                <span class="keywordflow">if</span> (delayed_stop_at &lt; DBL_MAX) {</div><div class="line">                        msg (<span class="stringliteral">&quot;Already stopping in %d seconds.\n&quot;</span>,</div><div class="line">                             (<span class="keywordtype">int</span>)(delayed_stop_at - timestamp));</div><div class="line">                        <span class="keywordflow">return</span>;</div><div class="line">                }</div><div class="line"></div><div class="line">                <span class="keywordflow">break</span>;</div><div class="line">        }</div><div class="line"></div><div class="line">        <span class="keywordflow">if</span> (NULL != pid</div><div class="line">            <span class="comment">/* EN 300 231 Annex E.3 Example 8. */</span></div><div class="line">            &amp;&amp; !pid-&gt;<a class="code" href="structvbi__program__id.html#abdd578b10dfa50e422cf90f200899d84">luf</a></div><div class="line">            <span class="comment">/* EN 300 231 Section 6.2 p) and Annex E.3 Example 7 and</span></div><div class="line"><span class="comment">               9. */</span></div><div class="line">            &amp;&amp; (<a class="code" href="group__ProgramID.html#gga05589fbab0657f08285ebdfe93f5ec9ea835908e1f719f7761589ac1f3b968cb4">VBI_PIL_INTERRUPTION</a> == pid-&gt;<a class="code" href="structvbi__program__id.html#a30c0862c008de112f4222e1208038d58">pil</a></div><div class="line">                || <a class="code" href="group__ProgramID.html#gga05589fbab0657f08285ebdfe93f5ec9eaad30c6505f26ef2b6e26626afdff02dd">VBI_PIL_INHIBIT_TERMINATE</a> == pid-&gt;<a class="code" href="structvbi__program__id.html#a30c0862c008de112f4222e1208038d58">pil</a>)) {</div><div class="line">                mi = pid-&gt;<a name="a21"></a><a class="code" href="structvbi__program__id.html#a9cccb9d3856e8b459d09e67cd12908d4">mi</a>;</div><div class="line">        } <span class="keywordflow">else</span> {</div><div class="line">                <span class="comment">/* EN 300 231 is unclear about the expected response</span></div><div class="line"><span class="comment">                   if a PIL with MI = 1 replaces a PIL with MI = 0 or</span></div><div class="line"><span class="comment">                   vice versa. Section 6.2 p) suggests that only the</span></div><div class="line"><span class="comment">                   MI flag of the old label determines when the</span></div><div class="line"><span class="comment">                   program stops and Annex E.3 Example 1 to 7 are</span></div><div class="line"><span class="comment">                   consistent with this interpretation, Example 10 is</span></div><div class="line"><span class="comment">                   not. */</span></div><div class="line">                <span class="keywordflow">if</span> (0 == curr_pid.<a class="code" href="structvbi__program__id.html#a30c0862c008de112f4222e1208038d58">pil</a>) {</div><div class="line">                        <span class="comment">/* Recording was started by timer. */</span></div><div class="line">                        mi = TRUE;</div><div class="line">                } <span class="keywordflow">else</span> {</div><div class="line">                        mi = curr_pid.<a class="code" href="structvbi__program__id.html#a9cccb9d3856e8b459d09e67cd12908d4">mi</a>;</div><div class="line">                }</div><div class="line">        }</div><div class="line"></div><div class="line">        <span class="keywordflow">if</span> (mi) {</div><div class="line">                stop_recording_now ();</div><div class="line">                remove_program_if_ended (curr_program, pid);</div><div class="line">        } <span class="keywordflow">else</span> {</div><div class="line">                stop_recording_in_30s (pid);</div><div class="line">        }</div><div class="line">}</div><div class="line"></div><div class="line"><span class="comment">/* Interruption or Recording Inhibit/Terminate service code. */</span></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span></div><div class="line">received_int_rit                (<span class="keyword">const</span> <a class="code" href="structvbi__program__id.html">vbi_program_id</a> * pid)</div><div class="line">{</div><div class="line">        <span class="keywordflow">switch</span> (vcr_state) {</div><div class="line">        <span class="keywordflow">case</span> VCR_STATE_STBY:</div><div class="line">                assert (0);</div><div class="line"></div><div class="line">        <span class="keywordflow">case</span> VCR_STATE_SCAN:</div><div class="line">                disable_timer_control ();</div><div class="line">                <span class="keywordflow">return</span>;</div><div class="line"></div><div class="line">        <span class="keywordflow">case</span> VCR_STATE_PTR:</div><div class="line">                assert (!timer_control_mode);</div><div class="line"></div><div class="line">                <span class="keywordflow">if</span> (pid-&gt;<a class="code" href="structvbi__program__id.html#a90794327986da193ddb76d518331589d">channel</a> != curr_pid.<a class="code" href="structvbi__program__id.html#a90794327986da193ddb76d518331589d">channel</a>) {</div><div class="line">                        msg (<span class="stringliteral">&quot;Ignore %s/%02X with different LCI.\n&quot;</span>,</div><div class="line">                             pil_str (pid-&gt;<a class="code" href="structvbi__program__id.html#a30c0862c008de112f4222e1208038d58">pil</a>), pid-&gt;<a name="a22"></a><a class="code" href="structvbi__program__id.html#a069f84e950d47f19a589cbe4a3603068">pty</a>);</div><div class="line">                        <span class="keywordflow">return</span>;</div><div class="line">                }</div><div class="line"></div><div class="line">                <span class="keywordflow">break</span>;</div><div class="line"></div><div class="line">        <span class="keywordflow">case</span> VCR_STATE_REC:</div><div class="line">                <span class="keywordflow">if</span> (timer_control_mode) {</div><div class="line">                        <span class="comment">/* Impossible to know if this service code</span></div><div class="line"><span class="comment">                           refers to curr_program, so we keep</span></div><div class="line"><span class="comment">                           recording for now. */</span></div><div class="line">                        <span class="keywordflow">return</span>;</div><div class="line">                } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (pid-&gt;<a class="code" href="structvbi__program__id.html#a90794327986da193ddb76d518331589d">channel</a> != curr_pid.<a class="code" href="structvbi__program__id.html#a90794327986da193ddb76d518331589d">channel</a>) {</div><div class="line">                        msg (<span class="stringliteral">&quot;Ignore %s/%02X with different LCI.\n&quot;</span>,</div><div class="line">                             pil_str (pid-&gt;<a class="code" href="structvbi__program__id.html#a30c0862c008de112f4222e1208038d58">pil</a>), pid-&gt;<a class="code" href="structvbi__program__id.html#a069f84e950d47f19a589cbe4a3603068">pty</a>);</div><div class="line">                        <span class="keywordflow">return</span>;</div><div class="line">                }</div><div class="line"></div><div class="line">                <span class="keywordflow">break</span>;</div><div class="line">        }</div><div class="line"></div><div class="line">        pil_no_longer_transmitted (pid);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span></div><div class="line">received_pil                    (<span class="keyword">const</span> <a class="code" href="structvbi__program__id.html">vbi_program_id</a> * pid)</div><div class="line">{</div><div class="line">        <span class="keyword">struct </span>program *p;</div><div class="line"></div><div class="line">        <span class="keywordflow">switch</span> (vcr_state) {</div><div class="line">        <span class="keywordflow">case</span> VCR_STATE_STBY:</div><div class="line">                assert (0);</div><div class="line"></div><div class="line">        <span class="keywordflow">case</span> VCR_STATE_SCAN:</div><div class="line">                disable_timer_control ();</div><div class="line">                <span class="keywordflow">if</span> (pid-&gt;<a class="code" href="structvbi__program__id.html#abdd578b10dfa50e422cf90f200899d84">luf</a>)</div><div class="line">                        <span class="keywordflow">return</span>;</div><div class="line">                p = find_program_by_pil (pid-&gt;<a class="code" href="structvbi__program__id.html#a30c0862c008de112f4222e1208038d58">pil</a>);</div><div class="line">                <span class="keywordflow">break</span>;</div><div class="line"></div><div class="line">        <span class="keywordflow">case</span> VCR_STATE_PTR:</div><div class="line">                assert (!timer_control_mode);</div><div class="line"></div><div class="line">                <span class="keywordflow">if</span> (pid-&gt;<a class="code" href="structvbi__program__id.html#a90794327986da193ddb76d518331589d">channel</a> != curr_pid.<a class="code" href="structvbi__program__id.html#a90794327986da193ddb76d518331589d">channel</a>) {</div><div class="line">                        msg (<span class="stringliteral">&quot;Ignore %s/%02X with different LCI.\n&quot;</span>,</div><div class="line">                             pil_str (pid-&gt;<a class="code" href="structvbi__program__id.html#a30c0862c008de112f4222e1208038d58">pil</a>), pid-&gt;<a class="code" href="structvbi__program__id.html#a069f84e950d47f19a589cbe4a3603068">pty</a>);</div><div class="line">                        <span class="keywordflow">return</span>;</div><div class="line">                } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (pid-&gt;<a class="code" href="structvbi__program__id.html#abdd578b10dfa50e422cf90f200899d84">luf</a>) {</div><div class="line">                        pil_no_longer_transmitted (pid);</div><div class="line"></div><div class="line">                        <span class="comment">/* This example does not support VCR</span></div><div class="line"><span class="comment">                           reprogramming. */</span></div><div class="line">                        <span class="keywordflow">return</span>;</div><div class="line">                } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (pid-&gt;<a class="code" href="structvbi__program__id.html#a30c0862c008de112f4222e1208038d58">pil</a> != curr_pid.<a class="code" href="structvbi__program__id.html#a30c0862c008de112f4222e1208038d58">pil</a>) {</div><div class="line">                        pil_no_longer_transmitted (pid);</div><div class="line">                        p = find_program_by_pil (pid-&gt;<a class="code" href="structvbi__program__id.html#a30c0862c008de112f4222e1208038d58">pil</a>);</div><div class="line">                        <span class="keywordflow">break</span>;</div><div class="line">                } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (pid-&gt;<a name="a23"></a><a class="code" href="structvbi__program__id.html#a35a130af99faf5714b96da7f3d08c48e">prf</a>) {</div><div class="line">                        <span class="keywordflow">if</span> (timestamp &gt;= vcr_state_since + 60) {</div><div class="line">                                <span class="comment">/* EN 300 231 Section E.1,</span></div><div class="line"><span class="comment">                                   Section E.3 Example 12. */</span></div><div class="line">                                msg (<span class="stringliteral">&quot;Overriding stuck PRF flag.\n&quot;</span>);</div><div class="line">                        } <span class="keywordflow">else</span> {</div><div class="line">                                msg (<span class="stringliteral">&quot;Already prepared to record.\n&quot;</span>);</div><div class="line">                                <span class="keywordflow">return</span>;</div><div class="line">                        }</div><div class="line">                }</div><div class="line"></div><div class="line">                <span class="comment">/* PRF 1 -&gt; 0, program starts now. */</span></div><div class="line"></div><div class="line">                start_recording_by_pil (curr_program, pid);</div><div class="line"></div><div class="line">                <span class="keywordflow">return</span>;</div><div class="line"></div><div class="line">        <span class="keywordflow">case</span> VCR_STATE_REC:</div><div class="line">                <span class="keywordflow">if</span> (timer_control_mode) {</div><div class="line">                        <span class="keywordflow">if</span> (pid-&gt;<a class="code" href="structvbi__program__id.html#abdd578b10dfa50e422cf90f200899d84">luf</a>) {</div><div class="line">                                <span class="comment">/* Impossible to know if this service</span></div><div class="line"><span class="comment">                                   code refers to curr_program, so we</span></div><div class="line"><span class="comment">                                   keep recording for now. */</span></div><div class="line">                                <span class="keywordflow">return</span>;</div><div class="line">                        }</div><div class="line"></div><div class="line">                        p = find_program_by_pil (pid-&gt;<a class="code" href="structvbi__program__id.html#a30c0862c008de112f4222e1208038d58">pil</a>);</div><div class="line">                        <span class="keywordflow">if</span> (p == curr_program) {</div><div class="line">                                disable_timer_control ();</div><div class="line"></div><div class="line">                                msg (<span class="stringliteral">&quot;Continue recording using &quot;</span></div><div class="line">                                     <span class="stringliteral">&quot;VPS/PDC signal.\n&quot;</span>);</div><div class="line"></div><div class="line">                                curr_pid = *pid;</div><div class="line"></div><div class="line">                                <span class="comment">/* Cancel a delayed stop because the</span></div><div class="line"><span class="comment">                                   program is evidently still</span></div><div class="line"><span class="comment">                                   running. */</span></div><div class="line">                                delayed_stop_at = DBL_MAX;</div><div class="line"></div><div class="line">                                <span class="keywordflow">return</span>;</div><div class="line">                        } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (NULL == p) {</div><div class="line">                                <span class="comment">/* This program is not scheduled for</span></div><div class="line"><span class="comment">                                   recording but the network may</span></div><div class="line"><span class="comment">                                   transmit other PILs in parallel, so</span></div><div class="line"><span class="comment">                                   we allow some time to pick them up</span></div><div class="line"><span class="comment">                                   before we stop. */</span></div><div class="line">                                stop_recording_in_30s (<span class="comment">/* pil */</span> NULL);</div><div class="line">                                <span class="keywordflow">return</span>;</div><div class="line">                        } <span class="keywordflow">else</span> {</div><div class="line">                                disable_timer_control ();</div><div class="line"></div><div class="line">                                <span class="comment">/* Perhaps in practice one should just</span></div><div class="line"><span class="comment">                                   open a new file and not restart</span></div><div class="line"><span class="comment">                                   capturing. */</span></div><div class="line">                                stop_recording_now ();</div><div class="line">                        }</div><div class="line">                } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (pid-&gt;<a class="code" href="structvbi__program__id.html#a90794327986da193ddb76d518331589d">channel</a> != curr_pid.<a class="code" href="structvbi__program__id.html#a90794327986da193ddb76d518331589d">channel</a>) {</div><div class="line">                        msg (<span class="stringliteral">&quot;Ignore %s/%02X with different LCI.\n&quot;</span>,</div><div class="line">                             pil_str (pid-&gt;<a class="code" href="structvbi__program__id.html#a30c0862c008de112f4222e1208038d58">pil</a>), pid-&gt;<a class="code" href="structvbi__program__id.html#a069f84e950d47f19a589cbe4a3603068">pty</a>);</div><div class="line">                        <span class="keywordflow">return</span>;</div><div class="line">                } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (pid-&gt;<a class="code" href="structvbi__program__id.html#abdd578b10dfa50e422cf90f200899d84">luf</a>) {</div><div class="line">                        pil_no_longer_transmitted (pid);</div><div class="line"></div><div class="line">                        <span class="comment">/* This example does not support VCR</span></div><div class="line"><span class="comment">                           reprogramming. */</span></div><div class="line">                        <span class="keywordflow">return</span>;</div><div class="line">                } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (pid-&gt;<a class="code" href="structvbi__program__id.html#a30c0862c008de112f4222e1208038d58">pil</a> == curr_pid.<a class="code" href="structvbi__program__id.html#a30c0862c008de112f4222e1208038d58">pil</a>) {</div><div class="line">                        <span class="keywordflow">if</span> (delayed_stop_at &lt; DBL_MAX) {</div><div class="line">                                <span class="comment">/* We lost all PDC signals and</span></div><div class="line"><span class="comment">                                   timer_control() arranged for a</span></div><div class="line"><span class="comment">                                   delayed stop. Or we received an INT</span></div><div class="line"><span class="comment">                                   or RI/T code or a different PIL</span></div><div class="line"><span class="comment">                                   than curr_program-&gt;pil with</span></div><div class="line"><span class="comment">                                   MI=0. But now we receive</span></div><div class="line"><span class="comment">                                   curr_program-&gt;pil again. */</span></div><div class="line">                                delayed_stop_at = DBL_MAX;</div><div class="line">                                msg (<span class="stringliteral">&quot;Delayed stop canceled.\n&quot;</span>);</div><div class="line">                                <span class="keywordflow">return</span>;</div><div class="line">                        } <span class="keywordflow">else</span> {</div><div class="line">                                <span class="comment">/* We lost all PDC signals and</span></div><div class="line"><span class="comment">                                   timer_control() started recording</span></div><div class="line"><span class="comment">                                   out of SCAN or PTR state, but now</span></div><div class="line"><span class="comment">                                   we receive curr_program-&gt;pil</span></div><div class="line"><span class="comment">                                   (again). Or this is just a</span></div><div class="line"><span class="comment">                                   retransmission of the PIL which</span></div><div class="line"><span class="comment">                                   started recording. Either way, we</span></div><div class="line"><span class="comment">                                   do not return to VCR_STATE_PTR if</span></div><div class="line"><span class="comment">                                   PRF is (still or again) 1. */</span></div><div class="line">                                msg (<span class="stringliteral">&quot;Already recording.\n&quot;</span>);</div><div class="line">                                <span class="keywordflow">return</span>;</div><div class="line">                        }</div><div class="line">                } <span class="keywordflow">else</span> {</div><div class="line">                        pil_no_longer_transmitted (pid);</div><div class="line">                        <span class="keywordflow">if</span> (VCR_STATE_SCAN != vcr_state) {</div><div class="line">                                <span class="comment">/* Stopping later. */</span></div><div class="line">                                <span class="keywordflow">return</span>;</div><div class="line">                        }</div><div class="line"></div><div class="line">                        p = find_program_by_pil (pid-&gt;<a class="code" href="structvbi__program__id.html#a30c0862c008de112f4222e1208038d58">pil</a>);</div><div class="line">                }</div><div class="line"></div><div class="line">                <span class="keywordflow">break</span>;</div><div class="line">        }</div><div class="line"></div><div class="line">        assert (VCR_STATE_SCAN == vcr_state);</div><div class="line"></div><div class="line">        <span class="keywordflow">if</span> (NULL == p)</div><div class="line">                <span class="keywordflow">return</span>;</div><div class="line"></div><div class="line">        <span class="keywordflow">if</span> (pid-&gt;<a class="code" href="structvbi__program__id.html#a35a130af99faf5714b96da7f3d08c48e">prf</a>) {</div><div class="line">                prepare_to_record_by_pil (p, pid);</div><div class="line">        } <span class="keywordflow">else</span> {</div><div class="line">                start_recording_by_pil (p, pid);</div><div class="line">        }</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span></div><div class="line"><a name="_a24"></a><a class="code" href="structevent__handler.html">event_handler</a>                   (<a name="_a25"></a><a class="code" href="structvbi__event.html">vbi_event</a> *            ev,</div><div class="line">                                 <span class="keywordtype">void</span> *                 user_data)</div><div class="line">{</div><div class="line">        <span class="keyword">const</span> <a class="code" href="structvbi__program__id.html">vbi_program_id</a> *pid;</div><div class="line">        <a class="code" href="group__ProgramID.html#ga289ec10e87cef7655799144bc898f262">vbi_pid_channel</a> lci;</div><div class="line"></div><div class="line">        user_data = user_data; <span class="comment">/* unused, no warning please */</span></div><div class="line"></div><div class="line">        assert (VCR_STATE_STBY != vcr_state);</div><div class="line"></div><div class="line">        pid = ev-&gt;<a name="a26"></a>ev.<a name="a27"></a>prog_id;</div><div class="line">        lci = pid-&gt;<a class="code" href="structvbi__program__id.html#a90794327986da193ddb76d518331589d">channel</a>;</div><div class="line"></div><div class="line">        <span class="keywordflow">switch</span> (lci) {</div><div class="line">        <span class="keywordflow">case</span> <a class="code" href="group__ProgramID.html#gga289ec10e87cef7655799144bc898f262a51a53db4366781f100d5d02836d6452e">VBI_PID_CHANNEL_LCI_0</a>:</div><div class="line">        <span class="keywordflow">case</span> <a class="code" href="group__ProgramID.html#gga289ec10e87cef7655799144bc898f262afdd62439879c03c78fce236bf7dcc081">VBI_PID_CHANNEL_LCI_1</a>:</div><div class="line">        <span class="keywordflow">case</span> <a class="code" href="group__ProgramID.html#gga289ec10e87cef7655799144bc898f262ac9a4d6e6932f0f4fd2a19f71f07f4447">VBI_PID_CHANNEL_LCI_2</a>:</div><div class="line">        <span class="keywordflow">case</span> <a class="code" href="group__ProgramID.html#gga289ec10e87cef7655799144bc898f262a969d34250cbd4e60539740cc4f3398f1">VBI_PID_CHANNEL_LCI_3</a>:</div><div class="line">                <span class="keywordflow">break</span>;</div><div class="line"></div><div class="line">        <span class="keywordflow">case</span> <a class="code" href="group__ProgramID.html#gga289ec10e87cef7655799144bc898f262a232efb61f9f576d83a778ad18b90e296">VBI_PID_CHANNEL_VPS</a>:</div><div class="line">                <span class="comment">/* EN 300 231 Section 9.4.1: &quot;When both line 16 (VPS)</span></div><div class="line"><span class="comment">                   and Teletext-delivered labels are available</span></div><div class="line"><span class="comment">                   simultaneously, decoders should default to the</span></div><div class="line"><span class="comment">                   Teletext-delivered service;&quot; */</span></div><div class="line">                <span class="keywordflow">if</span> (teletext_8302_available ())</div><div class="line">                        <span class="keywordflow">goto</span> finish;</div><div class="line">                <span class="keywordflow">break</span>;</div><div class="line"></div><div class="line">        <span class="keywordflow">default</span>:</div><div class="line">                <span class="comment">/* Support for other sources not implemented yet. */</span></div><div class="line">                <span class="keywordflow">return</span>;</div><div class="line">        }</div><div class="line"></div><div class="line">        msg (<span class="stringliteral">&quot;Received PIL %s/%02X on LC %u.\n&quot;</span>,</div><div class="line">             pil_str (pid-&gt;<a class="code" href="structvbi__program__id.html#a30c0862c008de112f4222e1208038d58">pil</a>), pid-&gt;<a class="code" href="structvbi__program__id.html#a069f84e950d47f19a589cbe4a3603068">pty</a>, lci);</div><div class="line"></div><div class="line">        <span class="keywordflow">switch</span> (pid-&gt;<a class="code" href="structvbi__program__id.html#a30c0862c008de112f4222e1208038d58">pil</a>) {</div><div class="line">        <span class="keywordflow">case</span> <a class="code" href="group__ProgramID.html#gga05589fbab0657f08285ebdfe93f5ec9eae7cbef095ebb79470785785bebdb2f8d">VBI_PIL_TIMER_CONTROL</a>:</div><div class="line">        <span class="keywordflow">case</span> <a class="code" href="group__ProgramID.html#gga05589fbab0657f08285ebdfe93f5ec9ea4084b4cb78ad4667f7645101adebb3e1">VBI_PIL_CONTINUE</a>:</div><div class="line">                signal_or_service_lost ();</div><div class="line">                <span class="keywordflow">break</span>;</div><div class="line"></div><div class="line">        <span class="keywordflow">case</span> <a class="code" href="group__ProgramID.html#gga05589fbab0657f08285ebdfe93f5ec9ea835908e1f719f7761589ac1f3b968cb4">VBI_PIL_INTERRUPTION</a>:</div><div class="line">        <span class="keywordflow">case</span> <a class="code" href="group__ProgramID.html#gga05589fbab0657f08285ebdfe93f5ec9eaad30c6505f26ef2b6e26626afdff02dd">VBI_PIL_INHIBIT_TERMINATE</a>:</div><div class="line">                received_int_rit (pid);</div><div class="line">                <span class="keywordflow">break</span>;</div><div class="line"></div><div class="line">        <span class="keywordflow">default</span>:</div><div class="line">                received_pil (pid);</div><div class="line">                <span class="keywordflow">break</span>;</div><div class="line">        }</div><div class="line"></div><div class="line"> finish:</div><div class="line">        lc_state[lci].pil = pid-&gt;<a class="code" href="structvbi__program__id.html#a30c0862c008de112f4222e1208038d58">pil</a>;</div><div class="line">        lc_state[lci].last_at = timestamp;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> vbi_bool</div><div class="line">in_pil_validity_window          (<span class="keywordtype">void</span>)</div><div class="line">{</div><div class="line">        <span class="keyword">struct </span>program *p;</div><div class="line"></div><div class="line">        <span class="keywordflow">for</span> (p = schedule; NULL != p; p = p-&gt;next) {</div><div class="line">                <span class="comment">/* The announced start and end time should fall within</span></div><div class="line"><span class="comment">                   the PIL validity window, but just in case. */</span></div><div class="line">                <span class="keywordflow">if</span> ((audience_time &gt;= p-&gt;start_time</div><div class="line">                     &amp;&amp; audience_time &lt; p-&gt;end_time)</div><div class="line">                    || (audience_time &gt;= p-&gt;pil_valid_start</div><div class="line">                        &amp;&amp; audience_time &lt; p-&gt;pil_valid_end))</div><div class="line">                        <span class="keywordflow">return</span> TRUE;</div><div class="line">        }</div><div class="line"></div><div class="line">        <span class="keywordflow">return</span> FALSE;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span></div><div class="line">timer_control                   (<span class="keywordtype">void</span>)</div><div class="line">{</div><div class="line">        <span class="keyword">struct </span>program *p;</div><div class="line"></div><div class="line">        assert (timer_control_mode);</div><div class="line"></div><div class="line">        <span class="keywordflow">switch</span> (vcr_state) {</div><div class="line">        <span class="keywordflow">case</span> VCR_STATE_STBY:</div><div class="line">        <span class="keywordflow">case</span> VCR_STATE_PTR:</div><div class="line">                assert (0);</div><div class="line"></div><div class="line">        <span class="keywordflow">case</span> VCR_STATE_SCAN:</div><div class="line">                <span class="keywordflow">break</span>;</div><div class="line"></div><div class="line">        <span class="keywordflow">case</span> VCR_STATE_REC:</div><div class="line">                <span class="keywordflow">if</span> (delayed_stop_at &lt; DBL_MAX) {</div><div class="line">                        <span class="comment">/* Will stop later. */</span></div><div class="line">                        <span class="keywordflow">return</span>;</div><div class="line">                } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (audience_time &gt;= curr_program-&gt;end_time) {</div><div class="line">                        stop_recording_now ();</div><div class="line"></div><div class="line">                        <span class="comment">/* We remove the program from the schedule as</span></div><div class="line"><span class="comment">                           shown in EN 300 231 Annex E.3, Example 11,</span></div><div class="line"><span class="comment">                           01:58:00. However as the example itself</span></div><div class="line"><span class="comment">                           demonstrates this is not in the best</span></div><div class="line"><span class="comment">                           interest of the user. A better idea may be</span></div><div class="line"><span class="comment">                           to keep the program scheduled until</span></div><div class="line"><span class="comment">                           curr_program-&gt;pil_valid_end, in case the</span></div><div class="line"><span class="comment">                           program is late or overrunning and we</span></div><div class="line"><span class="comment">                           receive its PIL after all. */</span></div><div class="line">                        remove_program_from_schedule (curr_program);</div><div class="line">                } <span class="keywordflow">else</span> {</div><div class="line">                        <span class="comment">/* Still running. */</span></div><div class="line">                        <span class="keywordflow">return</span>;</div><div class="line">                }</div><div class="line"></div><div class="line">                assert (VCR_STATE_SCAN == vcr_state);</div><div class="line"></div><div class="line">                <span class="keywordflow">break</span>;</div><div class="line">        }</div><div class="line"></div><div class="line">        <span class="keywordflow">for</span> (p = schedule; NULL != p; p = p-&gt;next) {</div><div class="line">                <span class="comment">/* Note if no program length has been specified</span></div><div class="line"><span class="comment">                   (start_time == end_time) this function will not</span></div><div class="line"><span class="comment">                   record the program. */</span></div><div class="line">                <span class="comment">/* We must also compare against p-&gt;end_time because we</span></div><div class="line"><span class="comment">                   will not always remove the program from the</span></div><div class="line"><span class="comment">                   schedule at that time. See</span></div><div class="line"><span class="comment">                   remove_program_if_ended(). */</span></div><div class="line">                <span class="keywordflow">if</span> (audience_time &gt;= p-&gt;start_time</div><div class="line">                    &amp;&amp; audience_time &lt; p-&gt;end_time) {</div><div class="line">                        start_recording_by_timer (p);</div><div class="line">                        <span class="keywordflow">return</span>;</div><div class="line">                }</div><div class="line">        }</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span></div><div class="line">pdc_signal_check                (<span class="keywordtype">void</span>)</div><div class="line">{</div><div class="line">        <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> ttx_chs =</div><div class="line">                ((1 &lt;&lt; <a class="code" href="group__ProgramID.html#gga289ec10e87cef7655799144bc898f262a51a53db4366781f100d5d02836d6452e">VBI_PID_CHANNEL_LCI_0</a>) |</div><div class="line">                 (1 &lt;&lt; <a class="code" href="group__ProgramID.html#gga289ec10e87cef7655799144bc898f262a51a53db4366781f100d5d02836d6452e">VBI_PID_CHANNEL_LCI_0</a>) |</div><div class="line">                 (1 &lt;&lt; <a class="code" href="group__ProgramID.html#gga289ec10e87cef7655799144bc898f262a51a53db4366781f100d5d02836d6452e">VBI_PID_CHANNEL_LCI_0</a>) |</div><div class="line">                 (1 &lt;&lt; <a class="code" href="group__ProgramID.html#gga289ec10e87cef7655799144bc898f262a51a53db4366781f100d5d02836d6452e">VBI_PID_CHANNEL_LCI_0</a>));</div><div class="line">        <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> vps_ch =</div><div class="line">                (1 &lt;&lt; <a class="code" href="group__ProgramID.html#gga289ec10e87cef7655799144bc898f262a232efb61f9f576d83a778ad18b90e296">VBI_PID_CHANNEL_VPS</a>);</div><div class="line">        <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> active_chs;</div><div class="line">        <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> lost_chs;</div><div class="line">        <a class="code" href="group__ProgramID.html#ga289ec10e87cef7655799144bc898f262">vbi_pid_channel</a> i;</div><div class="line"></div><div class="line">        <span class="keywordflow">if</span> (timer_control_mode)</div><div class="line">                <span class="keywordflow">return</span>;</div><div class="line"></div><div class="line">        <span class="comment">/* Determine if we lost signals. */</span></div><div class="line"></div><div class="line">        active_chs = 0;</div><div class="line">        lost_chs = 0;</div><div class="line"></div><div class="line">        <span class="keywordflow">for</span> (i = 0; i &lt; <a class="code" href="group__ProgramID.html#gga289ec10e87cef7655799144bc898f262a4d686ec8bbbcbac78fb4526374cecb01">VBI_MAX_PID_CHANNELS</a>; ++i) {</div><div class="line">                <span class="keywordtype">double</span> timeout_at;</div><div class="line"></div><div class="line">                <span class="keywordflow">if</span> (0 == lc_state[i].pil)</div><div class="line">                        <span class="keywordflow">continue</span>;</div><div class="line"></div><div class="line">                timeout_at = lc_state[i].last_at + signal_timeout[i];</div><div class="line">                <span class="keywordflow">if</span> (timestamp &gt;= timeout_at) {</div><div class="line">                        lost_chs |= 1 &lt;&lt; i;</div><div class="line">                } <span class="keywordflow">else</span> {</div><div class="line">                        active_chs |= 1 &lt;&lt; i;</div><div class="line">                }</div><div class="line">        }</div><div class="line"></div><div class="line">        <span class="comment">/* For now only Teletext and VPS delivery is supported, so we</span></div><div class="line"><span class="comment">           don&#39;t check other channels. */</span></div><div class="line"></div><div class="line">        <span class="keywordflow">if</span> (0 == active_chs) {</div><div class="line">                <span class="keywordflow">if</span> (0 != lost_chs) {</div><div class="line">                        msg (<span class="stringliteral">&quot;All Teletext and VPS signals lost, &quot;</span></div><div class="line">                             <span class="stringliteral">&quot;will fall back to timer control.\n&quot;</span>);</div><div class="line"></div><div class="line">                        signal_or_service_lost ();</div><div class="line">                }</div><div class="line">        } <span class="keywordflow">else</span> {</div><div class="line">                <span class="keywordflow">if</span> (vps_ch == active_chs</div><div class="line">                    &amp;&amp; 0 != (lost_chs &amp; ttx_chs)) {</div><div class="line">                        msg (<span class="stringliteral">&quot;Teletext signal lost, &quot;</span></div><div class="line">                             <span class="stringliteral">&quot;will fall back to VPS.\n&quot;</span>);</div><div class="line"></div><div class="line">                        <span class="keywordflow">if</span> (curr_pid.<a class="code" href="structvbi__program__id.html#a30c0862c008de112f4222e1208038d58">pil</a></div><div class="line">                            == lc_state[<a class="code" href="group__ProgramID.html#gga289ec10e87cef7655799144bc898f262a232efb61f9f576d83a778ad18b90e296">VBI_PID_CHANNEL_VPS</a>].pil) {</div><div class="line">                                curr_pid.<a class="code" href="structvbi__program__id.html#a90794327986da193ddb76d518331589d">channel</a> = <a class="code" href="group__ProgramID.html#gga289ec10e87cef7655799144bc898f262a232efb61f9f576d83a778ad18b90e296">VBI_PID_CHANNEL_VPS</a>;</div><div class="line">                        }</div><div class="line">                }</div><div class="line"></div><div class="line">                <span class="keywordflow">if</span> ((VCR_STATE_PTR == vcr_state</div><div class="line">                     || VCR_STATE_REC == vcr_state)</div><div class="line">                    &amp;&amp; 0 != curr_pid.<a class="code" href="structvbi__program__id.html#a30c0862c008de112f4222e1208038d58">pil</a></div><div class="line">                    &amp;&amp; 0 != (lost_chs &amp; (1 &lt;&lt; curr_pid.<a class="code" href="structvbi__program__id.html#a90794327986da193ddb76d518331589d">channel</a>))) {</div><div class="line">                        <span class="comment">/* Note if multiple label channels are in use</span></div><div class="line"><span class="comment">                           (Teletext only) a PIL may just &quot;disappear&quot;</span></div><div class="line"><span class="comment">                           without a RI/T service code or other PIL</span></div><div class="line"><span class="comment">                           subsequently transmitted on the same</span></div><div class="line"><span class="comment">                           channel. */</span></div><div class="line">                        pil_no_longer_transmitted (<span class="comment">/* pid */</span> NULL);</div><div class="line">                }</div><div class="line">        }</div><div class="line"></div><div class="line">        <span class="keywordflow">if</span> (0 != lost_chs) {</div><div class="line">                <span class="keywordflow">for</span> (i = 0; i &lt; <a class="code" href="group__ProgramID.html#gga289ec10e87cef7655799144bc898f262a4d686ec8bbbcbac78fb4526374cecb01">VBI_MAX_PID_CHANNELS</a>; ++i) {</div><div class="line">                        <span class="keywordflow">if</span> (0 == (lost_chs &amp; (1 &lt;&lt; i)))</div><div class="line">                                <span class="keywordflow">continue</span>;</div><div class="line"></div><div class="line">                        lc_state[i].pil = 0;</div><div class="line">                        lc_state[i].last_at = timestamp;</div><div class="line">                }</div><div class="line">        }</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span></div><div class="line">parse_test_file_line            (time_t *               timestamp,</div><div class="line">                                 <a class="code" href="structvbi__program__id.html">vbi_program_id</a> *       pid,</div><div class="line">                                 <span class="keyword">enum</span> vcr_state *       exp_state,</div><div class="line">                                 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span>           line_counter,</div><div class="line">                                 <span class="keyword">const</span> <span class="keywordtype">char</span> *           test_file_line)</div><div class="line">{</div><div class="line">        <span class="keyword">struct </span>tm tm;</div><div class="line">        <span class="keyword">const</span> <span class="keywordtype">char</span> *s;</div><div class="line">        <span class="keywordtype">char</span> *s_end;</div><div class="line">        <span class="keyword">const</span> <span class="keywordtype">char</span> *detail;</div><div class="line">        <span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> ul;</div><div class="line"></div><div class="line">        <span class="comment">/* Test file format (based on examples in EN 300 231):</span></div><div class="line"><span class="comment"></span></div><div class="line"><span class="comment">           One line of text for each PID change, with 4 or 9 fields</span></div><div class="line"><span class="comment">           separated by one or more tabs or spaces:</span></div><div class="line"><span class="comment"></span></div><div class="line"><span class="comment">           1. Name of the broadcasting network, e.g. BBC1.</span></div><div class="line"><span class="comment">           2. Date of the change: yyyymmddThhmmss (local time)</span></div><div class="line"><span class="comment">                              or  yyyymmddThhmmssZ (UTC)</span></div><div class="line"><span class="comment">              Lines must be sorted by this date, oldest first. Dates</span></div><div class="line"><span class="comment">              must not repeat unless these lines have different LCI</span></div><div class="line"><span class="comment">              fields.</span></div><div class="line"><span class="comment">           3. Label Channel Identifier (vbi_pid_channel): 0 ... n</span></div><div class="line"><span class="comment">              or the name VPS (channel 4).</span></div><div class="line"><span class="comment">           4. Label Update Flag: 0 or 1.</span></div><div class="line"><span class="comment">           5. Mode Identifier: 0 or 1 or x (any).</span></div><div class="line"><span class="comment">           6. Prepare to Record Flag: 0 or 1 or x (any).</span></div><div class="line"><span class="comment">           7. Program Identification Label: mmddThhmm or one of the</span></div><div class="line"><span class="comment">              names</span></div><div class="line"><span class="comment">              - TC (Timer Control code)</span></div><div class="line"><span class="comment">              - RI/T (Recording Inhibit/Terminate code)</span></div><div class="line"><span class="comment">              - INT (Interruption code)</span></div><div class="line"><span class="comment">              - CONT (Continuation code)</span></div><div class="line"><span class="comment">              - NSPV (No Specific PIL Value).</span></div><div class="line"><span class="comment">              A Program Type can be appended, separated by a slash:</span></div><div class="line"><span class="comment">              - /A to /Z (Series Code)</span></div><div class="line"><span class="comment">              - /NN (a hex number, e.g. /3F)</span></div><div class="line"><span class="comment">           8. Channel or Network Identifier: a name like BBC1.</span></div><div class="line"><span class="comment">           9. Expected VCR state:</span></div><div class="line"><span class="comment">              - STBY</span></div><div class="line"><span class="comment">              - SCAN</span></div><div class="line"><span class="comment">              - PTR</span></div><div class="line"><span class="comment">              - REC.</span></div><div class="line"><span class="comment"></span></div><div class="line"><span class="comment">           If fields 4 to 8 are omitted the transmission of the label</span></div><div class="line"><span class="comment">           on the given label channel ceases. If field 9 is omitted</span></div><div class="line"><span class="comment">           the same VCR state as before is expected.</span></div><div class="line"><span class="comment"></span></div><div class="line"><span class="comment">           All text after a number sign (#) is ignored.</span></div><div class="line"><span class="comment">        */</span></div><div class="line"></div><div class="line">        s = test_file_line;</div><div class="line"></div><div class="line">        <span class="comment">/* Network name ignored in this example. */</span></div><div class="line">        <span class="keywordflow">while</span> (isalnum (*s))</div><div class="line">                ++s;</div><div class="line">        detail = <span class="stringliteral">&quot;channel field&quot;</span>;</div><div class="line">        <span class="keywordflow">if</span> (!isspace (*s))</div><div class="line">                <span class="keywordflow">goto</span> invalid;</div><div class="line"></div><div class="line">        memset (&amp;tm, 0, <span class="keyword">sizeof</span> (tm));</div><div class="line">        tm.tm_isdst = -1; <span class="comment">/* unknown */</span></div><div class="line"></div><div class="line">        s = strptime (s, <span class="stringliteral">&quot;%n%Y%m%dT%H%M%S&quot;</span>, &amp;tm);</div><div class="line">        detail = <span class="stringliteral">&quot;date field&quot;</span>;</div><div class="line">        <span class="keywordflow">if</span> (NULL == s)</div><div class="line">                <span class="keywordflow">goto</span> invalid;</div><div class="line">        <span class="keywordflow">while</span> (isspace (*s))</div><div class="line">                ++s;</div><div class="line">        <span class="keywordflow">if</span> (<span class="charliteral">&#39;Z&#39;</span> == *s) {</div><div class="line">                ++s;</div><div class="line">                *timestamp = timegm (&amp;tm);</div><div class="line">        } <span class="keywordflow">else</span> {</div><div class="line">                *timestamp = mktime (&amp;tm);</div><div class="line">        }</div><div class="line">        <span class="keywordflow">if</span> ((time_t) -1 == *timestamp)</div><div class="line">                <span class="keywordflow">goto</span> invalid;</div><div class="line"></div><div class="line">        memset (pid, 0, <span class="keyword">sizeof</span> (*pid));</div><div class="line"></div><div class="line">        <span class="keywordflow">while</span> (isspace (*s))</div><div class="line">                ++s;</div><div class="line">        <span class="keywordflow">if</span> (0 == strncmp (s, <span class="stringliteral">&quot;VPS&quot;</span>, 3)) {</div><div class="line">                pid-&gt;<a class="code" href="structvbi__program__id.html#a90794327986da193ddb76d518331589d">channel</a> = <a class="code" href="group__ProgramID.html#gga289ec10e87cef7655799144bc898f262a232efb61f9f576d83a778ad18b90e296">VBI_PID_CHANNEL_VPS</a>;</div><div class="line">                s += 3;</div><div class="line">        } <span class="keywordflow">else</span> {</div><div class="line">                ul = strtoul (s, &amp;s_end, 0);</div><div class="line">                detail = <span class="stringliteral">&quot;LCI field&quot;</span>;</div><div class="line">                <span class="keywordflow">if</span> (s_end == s</div><div class="line">                    || ul &gt;= (<span class="keywordtype">unsigned</span> <span class="keywordtype">long</span>) VBI_MAX_PID_CHANNELS)</div><div class="line">                        <span class="keywordflow">goto</span> invalid;</div><div class="line">                pid-&gt;<a class="code" href="structvbi__program__id.html#a90794327986da193ddb76d518331589d">channel</a> = ul;</div><div class="line">                s = s_end;</div><div class="line">        }</div><div class="line"></div><div class="line">        <span class="keywordflow">while</span> (isspace (*s))</div><div class="line">                ++s;</div><div class="line">        <span class="keywordflow">if</span> (!isdigit (*s)) {</div><div class="line">                <span class="comment">/* Cease transmission on this label channel,</span></div><div class="line"><span class="comment">                   pid-&gt;pil = 0. */</span></div><div class="line">        } <span class="keywordflow">else</span> {</div><div class="line">                ul = strtoul (s, &amp;s_end, 0);</div><div class="line">                detail = <span class="stringliteral">&quot;LUF field&quot;</span>;</div><div class="line">                <span class="keywordflow">if</span> (s_end == s || ul &gt; 1)</div><div class="line">                        <span class="keywordflow">goto</span> invalid;</div><div class="line">                pid-&gt;<a class="code" href="structvbi__program__id.html#abdd578b10dfa50e422cf90f200899d84">luf</a> = ul;</div><div class="line">                s = s_end;</div><div class="line"></div><div class="line">                <span class="keywordflow">while</span> (isspace (*s))</div><div class="line">                        ++s;</div><div class="line">                <span class="keywordflow">if</span> (<span class="charliteral">&#39;x&#39;</span> == *s) {</div><div class="line">                        ++s;</div><div class="line">                } <span class="keywordflow">else</span> {</div><div class="line">                        ul = strtoul (s, &amp;s_end, 0);</div><div class="line">                        detail = <span class="stringliteral">&quot;MI field&quot;</span>;</div><div class="line">                        <span class="keywordflow">if</span> (s_end == s || ul &gt; 1)</div><div class="line">                                <span class="keywordflow">goto</span> invalid;</div><div class="line">                        pid-&gt;<a class="code" href="structvbi__program__id.html#a9cccb9d3856e8b459d09e67cd12908d4">mi</a> = ul;</div><div class="line">                        s = s_end;</div><div class="line">                }</div><div class="line"></div><div class="line">                <span class="keywordflow">while</span> (isspace (*s))</div><div class="line">                        ++s;</div><div class="line">                <span class="keywordflow">if</span> (<span class="charliteral">&#39;x&#39;</span> == *s) {</div><div class="line">                        ++s;</div><div class="line">                } <span class="keywordflow">else</span> {</div><div class="line">                        ul = strtoul (s, &amp;s_end, 0);</div><div class="line">                        detail = <span class="stringliteral">&quot;PRF field&quot;</span>;</div><div class="line">                        <span class="keywordflow">if</span> (s_end == s || ul &gt; 1)</div><div class="line">                                <span class="keywordflow">goto</span> invalid;</div><div class="line">                        pid-&gt;<a class="code" href="structvbi__program__id.html#a35a130af99faf5714b96da7f3d08c48e">prf</a> = ul;</div><div class="line">                        s = s_end;</div><div class="line">                }</div><div class="line"></div><div class="line">                <span class="keywordflow">while</span> (isspace (*s))</div><div class="line">                        ++s;</div><div class="line">                <span class="keywordflow">if</span> (0 == strncmp (s, <span class="stringliteral">&quot;CONT&quot;</span>, 4)) {</div><div class="line">                        pid-&gt;<a class="code" href="structvbi__program__id.html#a30c0862c008de112f4222e1208038d58">pil</a> = <a class="code" href="group__ProgramID.html#gga05589fbab0657f08285ebdfe93f5ec9ea4084b4cb78ad4667f7645101adebb3e1">VBI_PIL_CONTINUE</a>;</div><div class="line">                        s += 4;</div><div class="line">                } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (0 == strncmp (s, <span class="stringliteral">&quot;END&quot;</span>, 3)) {</div><div class="line">                        pid-&gt;<a class="code" href="structvbi__program__id.html#a30c0862c008de112f4222e1208038d58">pil</a> = <a name="a28"></a><a class="code" href="group__ProgramID.html#gga05589fbab0657f08285ebdfe93f5ec9ea6e6335917a64f23fc354338b033136a8">VBI_PIL_END</a>;</div><div class="line">                        s += 3;</div><div class="line">                } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (0 == strncmp (s, <span class="stringliteral">&quot;INT&quot;</span>, 3)) {</div><div class="line">                        pid-&gt;<a class="code" href="structvbi__program__id.html#a30c0862c008de112f4222e1208038d58">pil</a> = <a class="code" href="group__ProgramID.html#gga05589fbab0657f08285ebdfe93f5ec9ea835908e1f719f7761589ac1f3b968cb4">VBI_PIL_INTERRUPTION</a>;</div><div class="line">                        s += 3;</div><div class="line">                } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (0 == strncmp (s, <span class="stringliteral">&quot;NSPV&quot;</span>, 4)) {</div><div class="line">                        pid-&gt;<a class="code" href="structvbi__program__id.html#a30c0862c008de112f4222e1208038d58">pil</a> = <a class="code" href="group__ProgramID.html#gga05589fbab0657f08285ebdfe93f5ec9eac9b7c435e58a2f76a87f1acb221630f9">VBI_PIL_NSPV</a>;</div><div class="line">                        s += 4;</div><div class="line">                } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (0 == strncmp (s, <span class="stringliteral">&quot;RI/T&quot;</span>, 4)) {</div><div class="line">                        pid-&gt;<a class="code" href="structvbi__program__id.html#a30c0862c008de112f4222e1208038d58">pil</a> = <a class="code" href="group__ProgramID.html#gga05589fbab0657f08285ebdfe93f5ec9eaad30c6505f26ef2b6e26626afdff02dd">VBI_PIL_INHIBIT_TERMINATE</a>;</div><div class="line">                        s += 4;</div><div class="line">                } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (0 == strncmp (s, <span class="stringliteral">&quot;TC&quot;</span>, 2)) {</div><div class="line">                        pid-&gt;<a class="code" href="structvbi__program__id.html#a30c0862c008de112f4222e1208038d58">pil</a> = <a class="code" href="group__ProgramID.html#gga05589fbab0657f08285ebdfe93f5ec9eae7cbef095ebb79470785785bebdb2f8d">VBI_PIL_TIMER_CONTROL</a>;</div><div class="line">                        s += 2;</div><div class="line">                } <span class="keywordflow">else</span> {</div><div class="line">                        ul = strtoul (s, &amp;s_end, 10);</div><div class="line">                        detail = <span class="stringliteral">&quot;PIL field&quot;</span>;</div><div class="line">                        <span class="keywordflow">if</span> (s_end == s</div><div class="line">                            || ul % 100 &gt; 31</div><div class="line">                            || ul &gt; 1531)</div><div class="line">                                <span class="keywordflow">goto</span> invalid;</div><div class="line">                        s = s_end;</div><div class="line">                        <span class="keywordflow">if</span> (ul &gt; 0) {</div><div class="line">                                pid-&gt;<a class="code" href="structvbi__program__id.html#a30c0862c008de112f4222e1208038d58">pil</a> = <a name="a29"></a><a class="code" href="group__ProgramID.html#ga749715601c404fe3fb1d6273c950e9df">VBI_PIL</a> (ul / 100,</div><div class="line">                                                    ul % 100, 0, 0);</div><div class="line">                                <span class="keywordflow">if</span> (<span class="charliteral">&#39;T&#39;</span> != *s++)</div><div class="line">                                        <span class="keywordflow">goto</span> invalid;</div><div class="line">                                ul = strtoul (s, &amp;s_end, 10);</div><div class="line">                                <span class="keywordflow">if</span> (s_end == s</div><div class="line">                                    || ul % 100 &gt; 63</div><div class="line">                                    || ul &gt; 3163)</div><div class="line">                                        <span class="keywordflow">goto</span> invalid;</div><div class="line">                                s = s_end;</div><div class="line">                                pid-&gt;<a class="code" href="structvbi__program__id.html#a30c0862c008de112f4222e1208038d58">pil</a> |= <a class="code" href="group__ProgramID.html#ga749715601c404fe3fb1d6273c950e9df">VBI_PIL</a> (0, 0,</div><div class="line">                                                     ul / 100,</div><div class="line">                                                     ul % 100);</div><div class="line">                        }</div><div class="line">                }</div><div class="line"></div><div class="line">                <span class="keywordflow">if</span> (<span class="charliteral">&#39;/&#39;</span> == *s) {</div><div class="line">                        <span class="keywordflow">do</span> ++s;</div><div class="line">                        <span class="keywordflow">while</span> (isspace (*s));</div><div class="line">                        <span class="keywordflow">if</span> (isalpha (s[0]) &amp;&amp; 0x20 == s[1]) {</div><div class="line">                                <span class="comment">/* Series code. This isn&#39;t magic, EN</span></div><div class="line"><span class="comment">                                   300 231 just gives letters instead</span></div><div class="line"><span class="comment">                                   of the codes 0x80 ... 0xFF for</span></div><div class="line"><span class="comment">                                   easier reading. */</span></div><div class="line">                                pid-&gt;<a class="code" href="structvbi__program__id.html#a069f84e950d47f19a589cbe4a3603068">pty</a> = 0x80 | *s++;</div><div class="line">                        } <span class="keywordflow">else</span> {</div><div class="line">                                ul = strtoul (s, &amp;s_end, 16);</div><div class="line">                                detail = <span class="stringliteral">&quot;PTY field&quot;</span>;</div><div class="line">                                <span class="keywordflow">if</span> (s_end == s || ul &gt; 0xFF)</div><div class="line">                                        <span class="keywordflow">goto</span> invalid;</div><div class="line">                                pid-&gt;<a class="code" href="structvbi__program__id.html#a069f84e950d47f19a589cbe4a3603068">pty</a> = ul;</div><div class="line">                                s = s_end;</div><div class="line">                        }</div><div class="line">                } <span class="keywordflow">else</span> {</div><div class="line">                        pid-&gt;<a class="code" href="structvbi__program__id.html#a069f84e950d47f19a589cbe4a3603068">pty</a> = 0;</div><div class="line">                }</div><div class="line"></div><div class="line">                <span class="comment">/* Network name ignored in this example. */</span></div><div class="line">                <span class="keywordflow">while</span> (isspace (*s))</div><div class="line">                        ++s;</div><div class="line">                <span class="keywordflow">while</span> (isalnum (*s))</div><div class="line">                        ++s;</div><div class="line">                detail = <span class="stringliteral">&quot;CNI field&quot;</span>;</div><div class="line">                <span class="keywordflow">if</span> (0 != *s &amp;&amp; !isspace (*s))</div><div class="line">                        <span class="keywordflow">goto</span> invalid;</div><div class="line">                <span class="keywordflow">if</span> (<a class="code" href="group__ProgramID.html#gga289ec10e87cef7655799144bc898f262a232efb61f9f576d83a778ad18b90e296">VBI_PID_CHANNEL_VPS</a> == pid-&gt;<a class="code" href="structvbi__program__id.html#a90794327986da193ddb76d518331589d">channel</a>) {</div><div class="line">                        pid-&gt;<a name="a30"></a><a class="code" href="structvbi__program__id.html#a5ac7312ef52b908f7b55996d6d12b3bb">cni_type</a> = VBI_CNI_TYPE_VPS;</div><div class="line">                        pid-&gt;<a name="a31"></a><a class="code" href="structvbi__program__id.html#ab02c877d547812c4cc22df34e6b8794c">cni</a> = 0x1234;</div><div class="line">                } <span class="keywordflow">else</span> {</div><div class="line">                        pid-&gt;<a class="code" href="structvbi__program__id.html#a5ac7312ef52b908f7b55996d6d12b3bb">cni_type</a> = VBI_CNI_TYPE_8302;</div><div class="line">                        pid-&gt;<a class="code" href="structvbi__program__id.html#ab02c877d547812c4cc22df34e6b8794c">cni</a> = 0x1234;</div><div class="line">                }</div><div class="line">        }</div><div class="line"></div><div class="line">        <span class="keywordflow">while</span> (isspace (*s))</div><div class="line">                ++s;</div><div class="line">        <span class="keywordflow">if</span> (<span class="charliteral">&#39;#&#39;</span> == *s || 0 == *s) {</div><div class="line">                *exp_state = -1; <span class="comment">/* no change */</span></div><div class="line">                <span class="keywordflow">return</span>;</div><div class="line">        } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (0 == strncmp (s, <span class="stringliteral">&quot;PTR&quot;</span>, 3)) {</div><div class="line">                *exp_state = VCR_STATE_PTR;</div><div class="line">                s += 3;</div><div class="line">        } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (0 == strncmp (s, <span class="stringliteral">&quot;REC&quot;</span>, 3)) {</div><div class="line">                *exp_state = VCR_STATE_REC;</div><div class="line">                s += 3;</div><div class="line">        } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (0 == strncmp (s, <span class="stringliteral">&quot;SCAN&quot;</span>, 4)) {</div><div class="line">                *exp_state = VCR_STATE_SCAN;</div><div class="line">                s += 4;</div><div class="line">        } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (0 == strncmp (s, <span class="stringliteral">&quot;STBY&quot;</span>, 4)) {</div><div class="line">                *exp_state = VCR_STATE_STBY;</div><div class="line">                s += 4;</div><div class="line">        } <span class="keywordflow">else</span> {</div><div class="line">                detail = <span class="stringliteral">&quot;VCR state field&quot;</span>;</div><div class="line">                <span class="keywordflow">goto</span> invalid;</div><div class="line">        }</div><div class="line"></div><div class="line">        <span class="keywordflow">while</span> (isspace (*s))</div><div class="line">                ++s;</div><div class="line"></div><div class="line">        <span class="keywordflow">if</span> (<span class="charliteral">&#39;#&#39;</span> == *s || 0 == *s)</div><div class="line">                <span class="keywordflow">return</span>;</div><div class="line"></div><div class="line">        detail = <span class="stringliteral">&quot;garbage at end of line&quot;</span>;</div><div class="line"></div><div class="line"> invalid:</div><div class="line">        fprintf (stderr, <span class="stringliteral">&quot;Error in test file line %u, %s:\n%s\n&quot;</span>,</div><div class="line">                 line_counter, detail, test_file_line);</div><div class="line">        exit (EXIT_FAILURE);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span></div><div class="line">simulate_signals                (<span class="keywordtype">void</span>)</div><div class="line">{</div><div class="line">        <span class="keyword">static</span> <span class="keywordtype">char</span> buffer[256];</div><div class="line">        <span class="keyword">static</span> <a class="code" href="structvbi__program__id.html">vbi_program_id</a> test_pid[<a class="code" href="group__ProgramID.html#gga289ec10e87cef7655799144bc898f262a4d686ec8bbbcbac78fb4526374cecb01">VBI_MAX_PID_CHANNELS</a>];</div><div class="line">        <span class="keyword">static</span> <a class="code" href="structvbi__program__id.html">vbi_program_id</a> next_pid;</div><div class="line">        <span class="keyword">static</span> time_t next_event_time = 0;</div><div class="line">        <span class="keyword">static</span> <span class="keyword">enum</span> vcr_state next_exp_vcr_state = (<span class="keyword">enum</span> vcr_state) -1;</div><div class="line">        <span class="keyword">static</span> <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> line_counter;</div><div class="line">        <a class="code" href="group__ProgramID.html#ga289ec10e87cef7655799144bc898f262">vbi_pid_channel</a> i;</div><div class="line"></div><div class="line">        <span class="keywordflow">while</span> (timestamp &gt;= next_event_time) {</div><div class="line">                <span class="keywordflow">if</span> (0 != buffer[0]) {</div><div class="line">                        printf (<span class="stringliteral">&quot;&gt; %s&quot;</span>, buffer);</div><div class="line">                        test_pid[next_pid.<a class="code" href="structvbi__program__id.html#a90794327986da193ddb76d518331589d">channel</a>] = next_pid;</div><div class="line">                        <span class="keywordflow">if</span> ((<span class="keyword">enum</span> vcr_state) -1 == next_exp_vcr_state)</div><div class="line">                                test_exp_vcr_state = test_exp_vcr_state;</div><div class="line">                        <span class="keywordflow">else</span></div><div class="line">                                test_exp_vcr_state = next_exp_vcr_state;</div><div class="line">                }</div><div class="line"></div><div class="line">                <span class="keywordflow">for</span> (;;) {</div><div class="line">                        <span class="keyword">const</span> <span class="keywordtype">char</span> *s;</div><div class="line"></div><div class="line">                        <span class="keywordflow">if</span> (NULL == fgets (buffer, <span class="keyword">sizeof</span> (buffer),</div><div class="line">                                           stdin)) {</div><div class="line">                                printf (<span class="stringliteral">&quot;End of test file.\n&quot;</span>);</div><div class="line">                                next_event_time = INT_MAX;</div><div class="line">                                quit = TRUE;</div><div class="line">                                <span class="keywordflow">break</span>;</div><div class="line">                        }</div><div class="line"></div><div class="line">                        s = buffer;</div><div class="line"></div><div class="line">                        <span class="keywordflow">while</span> (isspace (*s))</div><div class="line">                                ++s;</div><div class="line">                        <span class="keywordflow">if</span> (0 == *s)</div><div class="line">                                <span class="keywordflow">continue</span>;</div><div class="line"></div><div class="line">                        <span class="keywordflow">if</span> (<span class="charliteral">&#39;#&#39;</span> == *s) {</div><div class="line">                                printf (<span class="stringliteral">&quot;&gt; %s&quot;</span>, s);</div><div class="line">                                <span class="keywordflow">continue</span>;</div><div class="line">                        }</div><div class="line"></div><div class="line">                        parse_test_file_line (&amp;next_event_time,</div><div class="line">                                              &amp;next_pid,</div><div class="line">                                              &amp;next_exp_vcr_state,</div><div class="line">                                              line_counter, s);</div><div class="line">                        ++line_counter;</div><div class="line"></div><div class="line">                        <span class="keywordflow">break</span>;</div><div class="line">                }</div><div class="line">        }</div><div class="line"></div><div class="line">        <span class="comment">/* See standby_loop(). */</span></div><div class="line">        audience_time = (time_t) timestamp;</div><div class="line"></div><div class="line">        <span class="comment">/* We stop recording before examining the received PIDs so we</span></div><div class="line"><span class="comment">           can respond to a new PID immediately. */</span></div><div class="line">        <span class="keywordflow">if</span> (VCR_STATE_REC == vcr_state</div><div class="line">            &amp;&amp; timestamp &gt;= delayed_stop_at) {</div><div class="line">                stop_recording_now ();</div><div class="line">                assert (VCR_STATE_SCAN == vcr_state);</div><div class="line">                remove_program_if_ended (curr_program,</div><div class="line">                                         &amp;delayed_stop_pid);</div><div class="line">        }</div><div class="line"></div><div class="line">        <span class="comment">/* Note in reality PIDs may arrive in any order, with a delay</span></div><div class="line"><span class="comment">           of several frames between them. */</span></div><div class="line">        <span class="keywordflow">for</span> (i = 0; i &lt; <a class="code" href="group__ProgramID.html#gga289ec10e87cef7655799144bc898f262a4d686ec8bbbcbac78fb4526374cecb01">VBI_MAX_PID_CHANNELS</a>; ++i) {</div><div class="line">                <span class="keywordflow">if</span> (0 != test_pid[i].pil) {</div><div class="line">                        <a class="code" href="structvbi__event.html">vbi_event</a> ev;</div><div class="line"></div><div class="line">                        memset (&amp;ev, 0, <span class="keyword">sizeof</span> (ev));</div><div class="line">                        ev.ev.prog_id = &amp;test_pid[i];</div><div class="line"></div><div class="line">                        <a class="code" href="structevent__handler.html">event_handler</a> (&amp;ev, <span class="comment">/* user_data */</span> NULL);</div><div class="line">                }</div><div class="line">        }</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span></div><div class="line">capture_and_decode_frame        (<span class="keywordtype">void</span>)</div><div class="line">{</div><div class="line">        <span class="keyword">struct </span>timeval timeout;</div><div class="line">        <a name="_a32"></a><a class="code" href="structvbi__capture__buffer.html">vbi_capture_buffer</a> *sliced_buffer;</div><div class="line">        <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> n_lines;</div><div class="line">        <span class="keywordtype">int</span> r;</div><div class="line"></div><div class="line">        <span class="comment">/* Don&#39;t wait more than two seconds for the driver</span></div><div class="line"><span class="comment">           to return data. */</span></div><div class="line">        timeout.tv_sec = 2;</div><div class="line">        timeout.tv_usec = 0;</div><div class="line"></div><div class="line">        r = <a name="a33"></a><a class="code" href="group__Device.html#ga58dcf2387b685b7c1c09a729f07893c8">vbi_capture_pull</a> (cap,</div><div class="line">                              <span class="comment">/* raw_buffer */</span> NULL,</div><div class="line">                              &amp;sliced_buffer,</div><div class="line">                              &amp;timeout);</div><div class="line">        <span class="keywordflow">switch</span> (r) {</div><div class="line">        <span class="keywordflow">case</span> -1:</div><div class="line">                fprintf (stderr,</div><div class="line">                         <span class="stringliteral">&quot;VBI read error: %s.\n&quot;</span>,</div><div class="line">                         strerror (errno));</div><div class="line">                <span class="comment">/* Could be ignored, esp. EIO from some</span></div><div class="line"><span class="comment">                   drivers. */</span></div><div class="line">                exit (EXIT_FAILURE);</div><div class="line"></div><div class="line">        <span class="keywordflow">case</span> 0: </div><div class="line">                fprintf (stderr, <span class="stringliteral">&quot;VBI read timeout\n&quot;</span>);</div><div class="line">                exit (EXIT_FAILURE);</div><div class="line"></div><div class="line">        <span class="keywordflow">case</span> 1: <span class="comment">/* success */</span></div><div class="line">                <span class="keywordflow">break</span>;</div><div class="line"></div><div class="line">        <span class="keywordflow">default</span>:</div><div class="line">                assert (0);</div><div class="line">        }</div><div class="line"></div><div class="line">        timestamp = sliced_buffer-&gt;timestamp;</div><div class="line">        n_lines = sliced_buffer-&gt;size / <span class="keyword">sizeof</span> (<a name="_a34"></a><a class="code" href="structvbi__sliced.html">vbi_sliced</a>);</div><div class="line"></div><div class="line">        <span class="comment">/* See standby_loop(). */</span></div><div class="line">        audience_time = (time_t) timestamp;</div><div class="line"></div><div class="line">        <span class="comment">/* We stop recording before examining the received PIDs so we</span></div><div class="line"><span class="comment">           can respond to a new PID immediately. */</span></div><div class="line">        <span class="keywordflow">if</span> (VCR_STATE_REC == vcr_state</div><div class="line">            &amp;&amp; timestamp &gt;= delayed_stop_at) {</div><div class="line">                stop_recording_now ();</div><div class="line">                assert (VCR_STATE_SCAN == vcr_state);</div><div class="line">                remove_program_if_ended (curr_program,</div><div class="line">                                         &amp;delayed_stop_pid);</div><div class="line">        }</div><div class="line"></div><div class="line">        <span class="comment">/* Calls event_handler(). */</span></div><div class="line">        <a name="a35"></a><a class="code" href="group__Service.html#ga2e2201e3b2bab9b7fb1bb66ade716772">vbi_decode</a> (dec, (<a class="code" href="structvbi__sliced.html">vbi_sliced</a> *) sliced_buffer-&gt;data,</div><div class="line">                    n_lines, timestamp);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span></div><div class="line">close_vbi_device                (<span class="keywordtype">void</span>)</div><div class="line">{</div><div class="line">        <a name="a36"></a><a class="code" href="group__Device.html#gaec518b62f39b83c80b06cc0a4affbee6">vbi_capture_delete</a> (cap);</div><div class="line">        cap = NULL;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span></div><div class="line">open_vbi_device                 (<span class="keywordtype">void</span>)</div><div class="line">{</div><div class="line">        vbi_service_set services;</div><div class="line">        <span class="keywordtype">char</span> *errstr;</div><div class="line"></div><div class="line">        services = (VBI_SLICED_TELETEXT_B |</div><div class="line">                    VBI_SLICED_VPS);</div><div class="line"></div><div class="line">        cap = <a name="a37"></a><a class="code" href="group__Device.html#ga85ba4554b337ecb053168bb88f713e5f">vbi_capture_v4l2_new</a> (dev_name,</div><div class="line">                                    <span class="comment">/* buffers */</span> 5,</div><div class="line">                                    &amp;services,</div><div class="line">                                    <span class="comment">/* strict */</span> 0,</div><div class="line">                                    &amp;errstr,</div><div class="line">                                    <span class="comment">/* verbose */</span> FALSE);</div><div class="line">        <span class="keywordflow">if</span> (NULL == cap) {</div><div class="line">                fprintf (stderr,</div><div class="line">                         <span class="stringliteral">&quot;Cannot capture VBI data from %s &quot;</span></div><div class="line">                         <span class="stringliteral">&quot;with V4L2 interface:\n&quot;</span></div><div class="line">                         <span class="stringliteral">&quot;%s\n&quot;</span>,</div><div class="line">                         dev_name, errstr);</div><div class="line"></div><div class="line">                free (errstr);</div><div class="line"></div><div class="line">                exit (EXIT_FAILURE);</div><div class="line">        }</div><div class="line">}</div><div class="line"></div><div class="line"><span class="comment">/* We wait in this function until we receive the expected PIL(s) or a</span></div><div class="line"><span class="comment">   program starts and ends as scheduled, and record it. */</span></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span></div><div class="line">capture_loop                    (<span class="keywordtype">void</span>)</div><div class="line">{</div><div class="line">        <span class="keywordtype">double</span> last_timestamp;</div><div class="line"></div><div class="line">        assert (VCR_STATE_STBY == vcr_state);</div><div class="line"></div><div class="line">        <span class="keywordflow">if</span> (!test_mode)</div><div class="line">                open_vbi_device ();</div><div class="line"></div><div class="line">        <span class="comment">/* Reset the VBI decoder. */</span></div><div class="line">        <a name="a38"></a><a class="code" href="group__Service.html#ga76b4210fb90365e6f09426fcde7ebec6">vbi_channel_switched</a> (dec, 0);</div><div class="line"></div><div class="line">        change_vcr_state (VCR_STATE_SCAN);</div><div class="line"></div><div class="line">        last_timestamp = 0;</div><div class="line"></div><div class="line">        <span class="keywordflow">while</span> (VCR_STATE_STBY != vcr_state &amp;&amp; !quit) {</div><div class="line">                <span class="keywordflow">if</span> (test_mode) {</div><div class="line">                        simulate_signals ();</div><div class="line">                } <span class="keywordflow">else</span> {</div><div class="line">                        capture_and_decode_frame ();</div><div class="line">                }</div><div class="line"></div><div class="line">                <span class="comment">/* Once per second is enough. */</span></div><div class="line">                <span class="keywordflow">if</span> ((<span class="keywordtype">long</span>) last_timestamp != (<span class="keywordtype">long</span>) timestamp) {</div><div class="line">                        <span class="keywordflow">if</span> (!timer_control_mode) {</div><div class="line">                                <span class="comment">/* May enable timer control mode. */</span></div><div class="line">                                pdc_signal_check ();</div><div class="line">                        }</div><div class="line"></div><div class="line">                        <span class="keywordflow">if</span> (timer_control_mode)</div><div class="line">                                timer_control ();</div><div class="line">                }</div><div class="line"></div><div class="line">                last_timestamp = timestamp;</div><div class="line"></div><div class="line">                <span class="keywordflow">if</span> (VCR_STATE_SCAN == vcr_state</div><div class="line">                    &amp;&amp; !in_pil_validity_window ()) {</div><div class="line">                        change_vcr_state (VCR_STATE_STBY);</div><div class="line">                }</div><div class="line"></div><div class="line">                <span class="keywordflow">if</span> (test_mode) {</div><div class="line">                        <span class="keywordflow">if</span> ((<span class="keyword">enum</span> vcr_state) -1 != test_exp_vcr_state</div><div class="line">                            &amp;&amp; test_exp_vcr_state != vcr_state) {</div><div class="line">                                printf (<span class="stringliteral">&quot;*** Unexpected VCR state %s\n&quot;</span>,</div><div class="line">                                        vcr_state_name (vcr_state));</div><div class="line"></div><div class="line">                                exit_code = EXIT_FAILURE;</div><div class="line">                        }</div><div class="line"></div><div class="line">                        <span class="comment">/* Advance by one second. Note a VPS signal is</span></div><div class="line"><span class="comment">                           transmitted on each frame, 25 times per</span></div><div class="line"><span class="comment">                           second, but we simulate at most one PID</span></div><div class="line"><span class="comment">                           change per second per label channel. */</span></div><div class="line">                        ++timestamp;</div><div class="line">                }</div><div class="line">        }</div><div class="line"></div><div class="line">        <span class="keywordflow">if</span> (!test_mode)</div><div class="line">                close_vbi_device ();</div><div class="line">}</div><div class="line"></div><div class="line"><span class="comment">/* We wait in this function until the starting time of the earliest</span></div><div class="line"><span class="comment">   program on the recording schedule is approaching. */</span></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span></div><div class="line">standby_loop                    (<span class="keywordtype">void</span>)</div><div class="line">{</div><div class="line">        <span class="keywordflow">while</span> (!quit) {</div><div class="line">                <span class="keyword">struct </span>program *p;</div><div class="line">                time_t first_scan;</div><div class="line"></div><div class="line">                assert (VCR_STATE_STBY == vcr_state);</div><div class="line"></div><div class="line">                <span class="keywordflow">if</span> (test_mode) {</div><div class="line">                        <span class="comment">/* Simulated current time. */</span></div><div class="line">                        audience_time = (time_t) timestamp;</div><div class="line">                } <span class="keywordflow">else</span> {</div><div class="line">                        <span class="comment">/* The current time of the intended audience</span></div><div class="line"><span class="comment">                           of the tuned in network according to the</span></div><div class="line"><span class="comment">                           network. It may differ from system time if</span></div><div class="line"><span class="comment">                           the system is not in sync with UTC or if we</span></div><div class="line"><span class="comment">                           receive the TV signal with a delay. For</span></div><div class="line"><span class="comment">                           simplicity we will not determine the offset</span></div><div class="line"><span class="comment">                           in this example, see VBI_EVENT_LOCAL_TIME</span></div><div class="line"><span class="comment">                           if you want to try that. */</span></div><div class="line">                        audience_time = time (NULL);</div><div class="line">                }</div><div class="line"></div><div class="line">                remove_stale_programs_from_schedule ();</div><div class="line">                <span class="keywordflow">if</span> (NULL == schedule) {</div><div class="line">                        printf (<span class="stringliteral">&quot;Recording schedule is empty.\n&quot;</span>);</div><div class="line">                        <span class="keywordflow">break</span>;</div><div class="line">                }</div><div class="line"></div><div class="line">                first_scan = schedule-&gt;start_time;</div><div class="line">                <span class="keywordflow">for</span> (p = schedule; NULL != p; p = p-&gt;next) {</div><div class="line">                        <span class="keywordflow">if</span> (p-&gt;start_time &lt; first_scan)</div><div class="line">                                first_scan = p-&gt;start_time;</div><div class="line">                        <span class="keywordflow">if</span> (p-&gt;pil_valid_start &lt; first_scan)</div><div class="line">                                first_scan = p-&gt;pil_valid_start;</div><div class="line">                }</div><div class="line"></div><div class="line">                <span class="keywordflow">while</span> (first_scan &gt; audience_time) {</div><div class="line">                        <span class="keywordtype">char</span> buffer[80];</div><div class="line">                        <span class="keyword">struct </span>tm tm;</div><div class="line"></div><div class="line">                        memset (&amp;tm, 0, <span class="keyword">sizeof</span> (tm));</div><div class="line">                        localtime_r (&amp;first_scan, &amp;tm);</div><div class="line">                        strftime (buffer, <span class="keyword">sizeof</span> (buffer),</div><div class="line">                                  <span class="stringliteral">&quot;%Y-%m-%d %H:%M:%S %Z&quot;</span>, &amp;tm);</div><div class="line"></div><div class="line">                        msg (<span class="stringliteral">&quot;Sleeping until %s.\n&quot;</span>, buffer);</div><div class="line"></div><div class="line">                        <span class="keywordflow">if</span> (test_mode) {</div><div class="line">                                audience_time = first_scan;</div><div class="line">                                timestamp = first_scan;</div><div class="line">                        } <span class="keywordflow">else</span> {</div><div class="line">                                <span class="comment">/* In a loop because the sleep()</span></div><div class="line"><span class="comment">                                   function may abort earlier. */</span></div><div class="line">                                sleep (first_scan - audience_time);</div><div class="line"></div><div class="line">                                audience_time = time (NULL);</div><div class="line">                        }</div><div class="line">                }</div><div class="line"></div><div class="line">                capture_loop ();</div><div class="line">        }</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span></div><div class="line">reset_state                     (<span class="keywordtype">void</span>)</div><div class="line">{</div><div class="line">        <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> i;</div><div class="line"></div><div class="line">        audience_time = 0.0;</div><div class="line">        timestamp = 0.0;</div><div class="line"></div><div class="line">        <span class="keywordflow">for</span> (i = 0; i &lt; <a class="code" href="group__ProgramID.html#gga289ec10e87cef7655799144bc898f262a4d686ec8bbbcbac78fb4526374cecb01">VBI_MAX_PID_CHANNELS</a>; ++i) {</div><div class="line">                lc_state[i].pil = 0; <span class="comment">/* none received */</span></div><div class="line">                lc_state[i].last_at = 0.0;</div><div class="line">        }</div><div class="line"></div><div class="line">        vcr_state = VCR_STATE_STBY;</div><div class="line">        vcr_state_since = 0.0;</div><div class="line"></div><div class="line">        timer_control_mode = FALSE;</div><div class="line"></div><div class="line">        delayed_stop_at = DBL_MAX;</div><div class="line"></div><div class="line">        test_exp_vcr_state = (<span class="keyword">enum</span> vcr_state) -1; <span class="comment">/* unknown */</span></div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span></div><div class="line">add_program_to_schedule         (<span class="keyword">const</span> <span class="keyword">struct</span> tm *      start_tm,</div><div class="line">                                 <span class="keyword">const</span> <span class="keyword">struct</span> tm *      end_tm,</div><div class="line">                                 <span class="keyword">const</span> <span class="keyword">struct</span> tm *      pdc_tm)</div><div class="line">{</div><div class="line">        <span class="keyword">struct </span>program *p;</div><div class="line">        <span class="keyword">struct </span>program **pp;</div><div class="line">        <span class="keyword">struct </span>tm tm;</div><div class="line">        time_t pil_time;</div><div class="line"></div><div class="line">        <span class="comment">/* Note PILs represent the originally announced start date of</span></div><div class="line"><span class="comment">           the program in the time zone of the intended audience. When</span></div><div class="line"><span class="comment">           we convert pdc_tm to a PIL we assume that zone is the same</span></div><div class="line"><span class="comment">           as the system time zone (TZ environment variable), and</span></div><div class="line"><span class="comment">           start_tm, end_tm and pdc_tm are also given relative to this</span></div><div class="line"><span class="comment">           time zone. We do not consider the case where a program</span></div><div class="line"><span class="comment">           straddles a daylight saving time discontinuity, e.g. starts</span></div><div class="line"><span class="comment">           in the CET zone and ends in the CEST zone. */</span></div><div class="line"></div><div class="line">        p = calloc (1, <span class="keyword">sizeof</span> (*p));</div><div class="line">        assert (NULL != p);</div><div class="line"></div><div class="line">        tm = *start_tm;</div><div class="line">        tm.tm_isdst = -1; <span class="comment">/* unknown */</span></div><div class="line">        p-&gt;start_time = mktime (&amp;tm);</div><div class="line">        <span class="keywordflow">if</span> ((time_t) -1 == p-&gt;start_time) {</div><div class="line">                fprintf (stderr, <span class="stringliteral">&quot;Invalid start time.\n&quot;</span>);</div><div class="line">                exit (EXIT_FAILURE);</div><div class="line">        }</div><div class="line"></div><div class="line">        tm = *start_tm;</div><div class="line">        tm.tm_isdst = -1; <span class="comment">/* unknown */</span></div><div class="line">        tm.tm_hour = end_tm-&gt;tm_hour;</div><div class="line">        tm.tm_min = end_tm-&gt;tm_min;</div><div class="line">        <span class="keywordflow">if</span> (end_tm-&gt;tm_hour &lt; start_tm-&gt;tm_hour) {</div><div class="line">                <span class="comment">/* mktime() should handle a 32nd. */</span></div><div class="line">                ++tm.tm_mday;</div><div class="line">        }</div><div class="line">        p-&gt;end_time = mktime (&amp;tm);</div><div class="line">        <span class="keywordflow">if</span> ((time_t) -1 == p-&gt;end_time) {</div><div class="line">                fprintf (stderr, <span class="stringliteral">&quot;Invalid end time.\n&quot;</span>);</div><div class="line">                exit (EXIT_FAILURE);</div><div class="line">        }</div><div class="line"></div><div class="line">        tm = *start_tm;</div><div class="line">        tm.tm_isdst = -1; <span class="comment">/* unknown */</span></div><div class="line">        tm.tm_hour = pdc_tm-&gt;tm_hour;</div><div class="line">        tm.tm_min = pdc_tm-&gt;tm_min;</div><div class="line">        <span class="keywordflow">if</span> (pdc_tm-&gt;tm_hour &gt;= start_tm-&gt;tm_hour + 12) {</div><div class="line">                <span class="comment">/* mktime() should handle a 0th. */</span></div><div class="line">                --tm.tm_mday;</div><div class="line">        } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (pdc_tm-&gt;tm_hour + 12 &lt; start_tm-&gt;tm_hour) {</div><div class="line">                ++tm.tm_mday;</div><div class="line">        }</div><div class="line"></div><div class="line">        <span class="comment">/* Normalize day and month. */</span></div><div class="line">        pil_time = mktime (&amp;tm);</div><div class="line">        <span class="keywordflow">if</span> ((time_t) -1 == pil_time</div><div class="line">            || NULL == localtime_r (&amp;pil_time, &amp;tm)) {</div><div class="line">                fprintf (stderr, <span class="stringliteral">&quot;Cannot determine PIL month/day.\n&quot;</span>);</div><div class="line">                exit (EXIT_FAILURE);</div><div class="line">        }</div><div class="line"></div><div class="line">        p-&gt;pil = <a class="code" href="group__ProgramID.html#ga749715601c404fe3fb1d6273c950e9df">VBI_PIL</a> (tm.tm_mon + 1, <span class="comment">/* 1 ... 12 */</span></div><div class="line">                          tm.tm_mday,</div><div class="line">                          tm.tm_hour,</div><div class="line">                          tm.tm_min);</div><div class="line"></div><div class="line">        <span class="keywordflow">if</span> (!<a name="a39"></a><a class="code" href="group__ProgramID.html#gac256d7e11100b73967b68cd90d578b0e">vbi_pil_validity_window</a> (&amp;p-&gt;pil_valid_start,</div><div class="line">                                      &amp;p-&gt;pil_valid_end,</div><div class="line">                                      p-&gt;pil,</div><div class="line">                                      p-&gt;start_time,</div><div class="line">                                      NULL <span class="comment">/* system tz */</span>)) {</div><div class="line">                fprintf (stderr, <span class="stringliteral">&quot;Cannot determine PIL validity.\n&quot;</span>);</div><div class="line">                exit (EXIT_FAILURE);</div><div class="line">        }</div><div class="line"></div><div class="line">        p-&gt;index = 0;</div><div class="line">        <span class="keywordflow">for</span> (pp = &amp;schedule; NULL != *pp; pp = &amp;(*pp)-&gt;next)</div><div class="line">                ++p-&gt;index;</div><div class="line"></div><div class="line">        *pp = p;</div><div class="line"></div><div class="line">        if (0) {</div><div class="line">                printf (<span class="stringliteral">&quot;Program %u start: &quot;</span>, p-&gt;index);</div><div class="line">                print_time (p-&gt;start_time);</div><div class="line">                printf (<span class="stringliteral">&quot;End:              &quot;</span>);</div><div class="line">                print_time (p-&gt;end_time);</div><div class="line">                printf (<span class="stringliteral">&quot;PIL:              &quot;</span>);</div><div class="line">                print_time (pil_time);</div><div class="line">                printf (<span class="stringliteral">&quot;PIL valid from:   &quot;</span>);</div><div class="line">                print_time (p-&gt;pil_valid_start);</div><div class="line">                printf (<span class="stringliteral">&quot;PIL valid until:  &quot;</span>);</div><div class="line">                print_time (p-&gt;pil_valid_end);</div><div class="line">        }</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span></div><div class="line">usage                           (FILE *                 fp)</div><div class="line">{</div><div class="line">        fprintf (fp,</div><div class="line"><span class="stringliteral">&quot;Please specify the start time of a program in the format\n&quot;</span></div><div class="line"><span class="stringliteral">&quot;YYYY-MM-DD HH:MM, the end time HH:MM and a VPS/PDC time HH:MM.\n&quot;</span>);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span></div><div class="line">parse_args                      (<span class="keywordtype">int</span>                    argc,</div><div class="line">                                 <span class="keywordtype">char</span> **                argv)</div><div class="line">{</div><div class="line">        <span class="keyword">struct </span>tm start_tm;</div><div class="line">        <span class="keyword">struct </span>tm end_tm;</div><div class="line">        <span class="keyword">struct </span>tm pdc_tm;</div><div class="line"></div><div class="line">        dev_name = <span class="stringliteral">&quot;/dev/vbi&quot;</span>;</div><div class="line"></div><div class="line">        <span class="keywordflow">for</span> (;;) {</div><div class="line">                <span class="keywordtype">int</span> c;</div><div class="line"></div><div class="line">                c = getopt (argc, argv, <span class="stringliteral">&quot;d:ht&quot;</span>);</div><div class="line"></div><div class="line">                <span class="keywordflow">if</span> (-1 == c)</div><div class="line">                        <span class="keywordflow">break</span>;</div><div class="line"></div><div class="line">                <span class="keywordflow">switch</span> (c) {</div><div class="line">                <span class="keywordflow">case</span> <span class="charliteral">&#39;d&#39;</span>:</div><div class="line">                        dev_name = optarg;</div><div class="line">                        <span class="keywordflow">break</span>;</div><div class="line"></div><div class="line">                <span class="keywordflow">case</span> <span class="charliteral">&#39;h&#39;</span>:</div><div class="line">                        usage (stdout);</div><div class="line">                        exit (EXIT_SUCCESS);</div><div class="line"></div><div class="line">                <span class="keywordflow">case</span> <span class="charliteral">&#39;t&#39;</span>:</div><div class="line">                        test_mode = TRUE;</div><div class="line">                        <span class="keywordflow">break</span>;</div><div class="line"></div><div class="line">                <span class="keywordflow">default</span>:</div><div class="line">                        usage (stderr);</div><div class="line">                        exit (EXIT_FAILURE);</div><div class="line">                }</div><div class="line">        }</div><div class="line"></div><div class="line">        <span class="keywordflow">while</span> (argc - optind &gt;= 4) {</div><div class="line">                memset (&amp;start_tm, 0, <span class="keyword">sizeof</span> (<span class="keyword">struct</span> tm));</div><div class="line">                <span class="keywordflow">if</span> (NULL == strptime (argv[optind + 0], <span class="stringliteral">&quot;%Y-%m-%d&quot;</span>,</div><div class="line">                                      &amp;start_tm))</div><div class="line">                        <span class="keywordflow">goto</span> invalid;</div><div class="line">                <span class="keywordflow">if</span> (NULL == strptime (argv[optind + 1], <span class="stringliteral">&quot;%H:%M&quot;</span>,</div><div class="line">                                      &amp;start_tm))</div><div class="line">                        <span class="keywordflow">goto</span> invalid;</div><div class="line"></div><div class="line">                memset (&amp;end_tm, 0, <span class="keyword">sizeof</span> (<span class="keyword">struct</span> tm));</div><div class="line">                <span class="keywordflow">if</span> (NULL == strptime (argv[optind + 2], <span class="stringliteral">&quot;%H:%M&quot;</span>,</div><div class="line">                                      &amp;end_tm))</div><div class="line">                        <span class="keywordflow">goto</span> invalid;</div><div class="line"></div><div class="line">                memset (&amp;pdc_tm, 0, <span class="keyword">sizeof</span> (<span class="keyword">struct</span> tm));</div><div class="line">                <span class="keywordflow">if</span> (NULL == strptime (argv[optind + 3], <span class="stringliteral">&quot;%H:%M&quot;</span>,</div><div class="line">                                      &amp;pdc_tm))</div><div class="line">                        <span class="keywordflow">goto</span> invalid;</div><div class="line"></div><div class="line">                add_program_to_schedule (&amp;start_tm, &amp;end_tm, &amp;pdc_tm);</div><div class="line"></div><div class="line">                optind += 4;</div><div class="line">        }</div><div class="line"></div><div class="line">        <span class="keywordflow">if</span> (argc != optind)</div><div class="line">                <span class="keywordflow">goto</span> invalid;</div><div class="line"></div><div class="line">        <span class="keywordflow">return</span>;</div><div class="line"></div><div class="line"> invalid:</div><div class="line">        usage (stderr);</div><div class="line">        exit (EXIT_FAILURE);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keywordtype">int</span></div><div class="line">main                            (<span class="keywordtype">int</span>                    argc,</div><div class="line">                                 <span class="keywordtype">char</span> **                argv)</div><div class="line">{</div><div class="line">        vbi_bool success;</div><div class="line"></div><div class="line">        setlocale (LC_ALL, <span class="stringliteral">&quot;&quot;</span>);</div><div class="line"></div><div class="line">        parse_args (argc, argv);</div><div class="line"></div><div class="line">        exit_code = EXIT_SUCCESS;</div><div class="line"></div><div class="line">        dec = <a name="a40"></a><a class="code" href="group__Service.html#ga3c09b7fa196326f51409a91e2857ba5e">vbi_decoder_new</a> ();</div><div class="line">        assert (NULL != dec);</div><div class="line"></div><div class="line">        success = <a name="a41"></a><a class="code" href="group__Event.html#ga6692bb41583ca67af5701360f321e3d7">vbi_event_handler_register</a> (dec, VBI_EVENT_PROG_ID,</div><div class="line">                                              <a class="code" href="structevent__handler.html">event_handler</a>,</div><div class="line">                                              <span class="comment">/* user_data */</span> NULL);</div><div class="line">        assert (success);</div><div class="line"></div><div class="line">        reset_state ();</div><div class="line"></div><div class="line">        standby_loop ();</div><div class="line"></div><div class="line">        <a name="a42"></a><a class="code" href="group__Service.html#gab3f52f0b71746c9081c053a33cad7bce">vbi_decoder_delete</a> (dec);</div><div class="line"></div><div class="line">        <span class="keywordflow">while</span> (NULL != schedule)</div><div class="line">                remove_program_from_schedule (schedule);</div><div class="line"></div><div class="line">        exit (exit_code);</div><div class="line">}</div></div><!-- fragment --> </div><!-- contents -->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated by &#160;<a href="http://www.doxygen.org/index.html">
<img class="footer" src="doxygen.png" alt="doxygen"/>
</a> 1.8.11
</small></address>
</body>
</html>