tvhtime: start adding time processing support to TVH

This commit is contained in:
Adam Sutton 2013-02-07 14:26:23 +00:00
parent 5c4c611e59
commit b043cf3729
6 changed files with 296 additions and 3 deletions

View file

@ -109,7 +109,8 @@ SRCS = src/main.c \
src/config2.c \
src/lang_codes.c \
src/lang_str.c \
src/imagecache.c
src/imagecache.c \
src/tvhtime.c
SRCS += src/epggrab/module.c\
src/epggrab/channel.c\

View file

@ -29,6 +29,7 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <time.h>
#include <linux/dvb/frontend.h>
#include <linux/dvb/dmx.h>
@ -41,6 +42,7 @@
#include "psi.h"
#include "notify.h"
#include "cwc.h"
#include "tvhtime.h"
#if TDT_TRACE
#define TRACE(_pre, _fmt, ...)\
@ -1074,6 +1076,54 @@ dvb_pmt_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len,
return 0;
}
/*
* Time Offset table handler
*/
static int
dvb_tot_callback(th_dvb_mux_instance_t *tdmi, uint8_t *buf, int len,
uint8_t tableid, void *opaque)
{
uint16_t mjd;
uint8_t hour, min, sec;
int year, mon, day;
struct tm utc;
if (tableid != 0x73)
return -1;
/* DVB format MJD, Hour, Min, Sec */
mjd = (buf[0] << 8) | buf[1];
hour = bcdtoint(buf[2]);
min = bcdtoint(buf[3]);
sec = bcdtoint(buf[4]);
/* Convert MJD (using algo from EN 300 468 v1.13.1 Annex C) */
year = (int)((mjd - 15078.2) / 365.25);
mon = (int)((mjd - 14956.1 - (int)(year * 365.25)) / 30.6001);
day = mjd - 14956 - (int)(year * 365.25) - (int)(mon * 30.6001);
if (mon == 14 || mon == 15) {
year++;
mon -= 12;
}
mon--;
tvhlog(LOG_DEBUG, "tdt-tot", "time is %04d/%02d/%02d %02d:%02d:%02d",
year+1900, mon, day, hour, min, sec);
/* Convert to UTC time_t */
utc.tm_wday = 0;
utc.tm_yday = 0;
utc.tm_isdst = 0;
utc.tm_year = year;
utc.tm_mon = mon - 1;
utc.tm_mday = day;
utc.tm_hour = hour;
utc.tm_min = min;
utc.tm_sec = sec;
tvhtime_update(&utc);
return 0;
}
/**
* Demux for default DVB tables that we want
@ -1097,6 +1147,10 @@ dvb_table_add_default_dvb(th_dvb_mux_instance_t *tdmi)
tdt_add(tdmi, 0, 0, dvb_pidx11_callback, NULL, "pidx11",
TDT_QUICKREQ | TDT_CRC, 0x11);
/* Time Offset Table */
tdt_add(tdmi, 0, 0, dvb_tot_callback, NULL, "tot", TDT_CRC, 0x14);
}

160
src/tvhtime.c Normal file
View file

@ -0,0 +1,160 @@
#include <time.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/time.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdint.h>
#include <stdlib.h>
#include "tvhtime.h"
#include "tvheadend.h"
#include "settings.h"
uint32_t tvhtime_update_enabled;
uint32_t tvhtime_ntp_enabled;
uint32_t tvhtime_tolerance;
/*
* NTP processing
*/
#define NTPD_BASE 0x4e545030 /* "NTP0" */
#define NTPD_UNIT 2
typedef struct
{
int mode; /* 0 - if valid set
* use values,
* clear valid
* 1 - if valid set
* if count before and after read of values is equal,
* use values
* clear valid
*/
int count;
time_t clockTimeStampSec;
int clockTimeStampUSec;
time_t receiveTimeStampSec;
int receiveTimeStampUSec;
int leap;
int precision;
int nsamples;
int valid;
int pad[10];
} ntp_shm_t;
static ntp_shm_t *
ntp_shm_init ( void )
{
int shmid, unit, mode;
static ntp_shm_t *shmptr = NULL;
if (shmptr != NULL)
return shmptr;
unit = getuid() ? 2 : 0;
mode = getuid() ? 0666 : 0600;
shmid = shmget((key_t)NTPD_BASE + unit, sizeof(ntp_shm_t), IPC_CREAT | mode);
if (shmid == -1)
return NULL;
shmptr = shmat(shmid, 0, 0);
memset(shmptr, 0, sizeof(ntp_shm_t));
if (shmptr) {
shmptr->mode = 1;
shmptr->precision = -1;
shmptr->nsamples = 1;
}
return shmptr;
}
/*
* Update time
*/
void
tvhtime_update ( struct tm *tm )
{
time_t now;
struct timeval tv;
ntp_shm_t *ntp_shm;
int64_t t1, t2;
/* Current and reported time */
now = mktime(tm);
gettimeofday(&tv, NULL);
/* Delta */
t1 = now * 1000000;
t2 = tv.tv_sec * 1000000 + tv.tv_usec;
#if NTP_TRACE
tvhlog(LOG_DEBUG, "ntp", "delta = %"PRId64" us\n", t2 - t1);
#endif
/* Update local clock */
if (tvhtime_update_enabled)
if (llabs(t2 - t1) > tvhtime_tolerance)
stime(&now);
/* NTP */
if (tvhtime_ntp_enabled) {
if (!(ntp_shm = ntp_shm_init()))
return;
ntp_shm->valid = 0;
ntp_shm->count++;
ntp_shm->clockTimeStampSec = now;
ntp_shm->clockTimeStampUSec = 0;
ntp_shm->receiveTimeStampSec = tv.tv_sec;
ntp_shm->receiveTimeStampUSec = (int)tv.tv_usec;
ntp_shm->count++;
ntp_shm->valid = 1;
}
}
/* Initialise */
void tvhtime_init ( void )
{
htsmsg_t *m = hts_settings_load("tvhtime/config");
if (htsmsg_get_u32(m, "update_enabled", &tvhtime_update_enabled))
tvhtime_update_enabled = 0;
if (htsmsg_get_u32(m, "ntp_enabled", &tvhtime_ntp_enabled))
tvhtime_ntp_enabled = 0;
if (htsmsg_get_u32(m, "tolerance", &tvhtime_tolerance))
tvhtime_tolerance = 5000;
}
static void tvhtime_save ( void )
{
htsmsg_t *m = htsmsg_create_map();
htsmsg_add_u32(m, "update_enabled", tvhtime_update_enabled);
htsmsg_add_u32(m, "ntp_enabled", tvhtime_ntp_enabled);
htsmsg_add_u32(m, "tolerance", tvhtime_tolerance);
hts_settings_save(m, "tvhtime/config");
}
void tvhtime_set_update_enabled ( uint32_t on )
{
if (tvhtime_update_enabled == on)
return;
tvhtime_update_enabled = on;
tvhtime_save();
}
void tvhtime_set_ntp_enabled ( uint32_t on )
{
if (tvhtime_ntp_enabled == on)
return;
tvhtime_ntp_enabled = on;
tvhtime_save();
}
void tvhtime_set_tolerance ( uint32_t v )
{
if (tvhtime_tolerance == v)
return;
tvhtime_tolerance = v;
tvhtime_save();
}

34
src/tvhtime.h Normal file
View file

@ -0,0 +1,34 @@
/*
* TVheadend - time processing
*
* Copyright (C) 2013 Adam Sutton
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __TVH_TIME_H__
#define __TVH_TIME_H_
extern uint32_t tvhtime_update_enabled;
extern uint32_t tvhtime_ntp_enabled;
extern uint32_t tvhtime_tolerance;
void tvhtime_init ( void );
void tvhtime_update ( struct tm *now );
void tvhtime_set_update_enabled ( uint32_t on );
void tvhtime_set_ntp_enabled ( uint32_t on );
void tvhtime_set_tolerance ( uint32_t v );
#endif /* __TVH_TIME_H__ */

View file

@ -49,6 +49,7 @@
#include "subscriptions.h"
#include "imagecache.h"
#include "timeshift.h"
#include "tvhtime.h"
/**
*
@ -1974,6 +1975,12 @@ extjs_config(http_connection_t *hc, const char *remain, void *opaque)
/* Misc */
pthread_mutex_lock(&global_lock);
m = config_get_all();
/* Time */
htsmsg_add_u32(m, "tvhtime_update_enabled", tvhtime_update_enabled);
htsmsg_add_u32(m, "tvhtime_ntp_enabled", tvhtime_ntp_enabled);
htsmsg_add_u32(m, "tvhtime_tolerance", tvhtime_tolerance);
pthread_mutex_unlock(&global_lock);
/* Image cache */
@ -2001,6 +2008,15 @@ extjs_config(http_connection_t *hc, const char *remain, void *opaque)
save |= config_set_language(str);
if (save)
config_save();
/* Time */
if ((str = http_arg_get(&hc->hc_req_args, "tvhtime_update_enabled")))
tvhtime_set_update_enabled(!!str);
if ((str = http_arg_get(&hc->hc_req_args, "tvhtime_ntp_enabled")))
tvhtime_set_ntp_enabled(!!str);
if ((str = http_arg_get(&hc->hc_req_args, "tvhtime_tolerance")))
tvhtime_set_tolerance(atoi(str));
pthread_mutex_unlock(&global_lock);
/* Image Cache */

View file

@ -39,7 +39,9 @@ tvheadend.miscconf = function() {
root : 'config'
}, [ 'muxconfpath', 'language',
'imagecache_enabled', 'imagecache_ok_period',
'imagecache_fail_period', 'imagecache_ignore_sslcert']);
'imagecache_fail_period', 'imagecache_ignore_sslcert',
'tvhtime_update_enabled', 'tvhtime_ntp_enabled',
'tvhtime_tolerance']);
/* ****************************************************************
* Form Fields
@ -75,6 +77,32 @@ tvheadend.miscconf = function() {
fromLegend: 'Available'
});
/*
* Time/Date
*/
var tvhtimeUpdateEnabled = new Ext.form.Checkbox({
name: 'tvhtime_update_enabled',
fieldLabel: 'Update time'
});
var tvhtimeNtpEnabled = new Ext.form.Checkbox({
name: 'tvhtime_ntp_enabled',
fieldLabel: 'Enable NTP driver'
});
var tvhtimeTolerance = new Ext.form.NumberField({
name: 'tvhtime_tolerance',
fieldLabel: 'Update tolerance (ms)'
});
var tvhtimePanel = new Ext.form.FieldSet({
title: 'Time Update',
width: 700,
autoHeight: true,
collapsible: true,
items : [ tvhtimeUpdateEnabled, tvhtimeNtpEnabled, tvhtimeTolerance ]
});
/*
* Image cache
*/
@ -140,7 +168,7 @@ tvheadend.miscconf = function() {
defaultType : 'textfield',
autoHeight : true,
items : [ language, dvbscanPath,
imagecachePanel ],
imagecachePanel, tvhtimePanel ],
tbar : [ saveButton, '->', helpButton ]
});