linuxdvb: started to work on linuxdvb code.

Lots of in progress stuff but its been sat uncommitted for a few weeks
due to inactivity and I don't want to lose it due to stupidity!
This commit is contained in:
Adam Sutton 2013-05-21 20:06:30 +01:00
parent 00f0137bb6
commit 474e1b71dc
16 changed files with 544 additions and 43 deletions

View file

@ -164,34 +164,15 @@ SRCS-$(CONFIG_MPEGTS) += \
src/epggrab/module/opentv.c \
src/epggrab/support/freesat_huffman.c \
# Timeshift
SRCS-${CONFIG_TIMESHIFT} += \
src/timeshift.c \
src/timeshift/timeshift_filemgr.c \
src/timeshift/timeshift_writer.c \
src/timeshift/timeshift_reader.c \
# DVB
SRCS-${CONFIG_LINUXDVB} += \
src/dvb/dvb.c \
src/dvb/dvb_adapter.c \
src/dvb/dvb_support.c \
src/dvb/dvb_charset.c \
src/dvb/dvb_fe.c \
src/dvb/dvb_tables.c \
src/dvb/diseqc.c \
src/dvb/dvb_linux.c \
src/dvb/dvb_hardware.c \
src/dvb/dvb_network.c \
src/dvb/dvb_multiplex.c \
src/dvb/dvb_service.c \
src/dvb/dvb_preconf.c \
src/dvb/dvb_satconf.c \
src/dvb/dvb_input_filtered.c \
src/dvb/dvb_input_raw.c \
src/webui/extjs_dvb.c \
src/muxes.c \
src/tvadapters.c \
src/input/mpegts/linuxdvb/linuxdvb.c \
src/input/mpegts/linuxdvb/linuxdvb_adapter.c \
# src/input/mpegts/linuxdvb/linuxdvb_input.c \
# src/input/mpegts/linuxdvb/linuxdvb_network.c \
# src/input/mpegts/linuxdvb/linuxdvb_mux.c \
# src/input/mpegts/linuxdvb/linuxdvb_service.c \
# IPTV
SRCS-${CONFIG_IPTV} += \
@ -205,6 +186,13 @@ SRCS-$(CONFIG_TSFILE) += \
src/input/mpegts/tsfile/tsfile_input.c \
src/input/mpegts/tsfile/tsfile_mux.c \
# Timeshift
SRCS-${CONFIG_TIMESHIFT} += \
src/timeshift.c \
src/timeshift/timeshift_filemgr.c \
src/timeshift/timeshift_writer.c \
src/timeshift/timeshift_reader.c \
# Inotify
SRCS-${CONFIG_INOTIFY} += \
src/dvr/dvr_inotify.c \
@ -286,7 +274,7 @@ ${PROG}: check_config $(OBJS) $(ALLDEPS)
$(CC) -o $@ $(OBJS) $(CFLAGS) $(LDFLAGS)
# Object
${BUILDDIR}/%.o: %.c
${BUILDDIR}/%.o: %.c $(BUILDDIR)
@mkdir -p $(dir $@)
$(CC) -MD -MP $(CFLAGS) -c -o $@ $<

7
configure vendored
View file

@ -86,6 +86,13 @@ fi
# DVB API
#
check_cc_header 'linux/dvb/version' dvbapi
if enabled_or_auto linuxdvb; then
if enabled dvbapi; then
enable linuxdvb
elif enabled linuxdvb; then
die "Linux DVB API not found (use --disable-linuxdvb)"
fi
fi
#
# Gzip

View file

@ -219,7 +219,7 @@ static void _epggrab_load ( void )
}
/* Load module config (channels) */
#if ENABLE_LINUXDVB
#if 0//ENABLE_LINUXDVB
eit_load();
opentv_load();
#endif
@ -379,7 +379,7 @@ void epggrab_init ( void )
epggrab_epgdb_periodicsave = 0;
/* Lists */
#if ENABLE_LINUXDVB
#if 0//ENABLE_LINUXDVB
extern TAILQ_HEAD(, epggrab_ota_mux) ota_mux_all;
TAILQ_INIT(&ota_mux_all);
#endif
@ -388,7 +388,7 @@ void epggrab_init ( void )
pthread_cond_init(&epggrab_cond, NULL);
/* Initialise modules */
#if ENABLE_LINUXDVB
#if 0//ENABLE_LINUXDVB
eit_init();
opentv_init();
#endif
@ -397,7 +397,7 @@ void epggrab_init ( void )
/* Load config */
_epggrab_load();
#if ENABLE_LINUXDVB
#if 0//ENABLE_LINUXDVB
epggrab_ota_load();
#endif

1
src/input/mpegps/v4l.h Symbolic link
View file

@ -0,0 +1 @@
v4l/v4l.h

View file

@ -242,7 +242,8 @@ struct mpegts_mux
* Functions
*/
int (*mm_start) ( mpegts_mux_t *mm, const char *reason, int weight );
int (*mm_start) (mpegts_mux_t *mm, const char *reason, int weight);
void (*mm_stop) (mpegts_mux_t *mm);
void (*mm_open_table) (mpegts_mux_t*,mpegts_table_t*);
void (*mm_close_table) (mpegts_mux_t*,mpegts_table_t*);

View file

@ -490,6 +490,8 @@ dvb_nit_callback
if (len < 7)
return -1;
tvhtrace(dstr, " section %d last %d current %d", ptr[3], ptr[4], ptr[2]&1);
/* Ignore "next" */
if (!(ptr[2] & 0x01))
return -1;
@ -613,6 +615,8 @@ dvb_sdt_callback
if(len < 8)
return -1;
tvhtrace("sdt", " section %d last %d current %d", ptr[3], ptr[4], ptr[2]&1);
/* Ignore next */
if((ptr[2] & 1) == 0)
return -1;

View file

@ -0,0 +1,31 @@
/*
* Tvheadend - Linux DVB input system
*
* 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_LINUX_DVB_H__
#define __TVH_LINUX_DVB_H__
void linuxdvb_init ( int mask );
#endif /* __TVH_LINUX_DVB_H__ */
/******************************************************************************
* Editor Configuration
*
* vim:sts=2:ts=2:sw=2:et
*****************************************************************************/

View file

@ -0,0 +1,41 @@
/*
* Tvheadend - Linux DVB input system
*
* 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/>.
*/
#include "tvheadend.h"
#include "input.h"
#include "linuxdvb_private.h"
#include <sys/types.h>
#include <dirent.h>
void linuxdvb_init ( int adapter_mask )
{
/* Scan for hardware */
int a;
DIR *dp = opendir("/dev/dvb");
struct dirent *de;
while ((de = readdir(dp))) {
if (sscanf(de->d_name, "adapter%d", &a) != 1) continue;
if (a & adapter_mask)
linuxdvb_adapter_create(a);
}
/* Load configuration */
// TODO
}

View file

@ -0,0 +1,160 @@
/*
* Tvheadend - Linux DVB input system
*
* 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/>.
*/
#include "tvheadend.h"
#include "linuxdvb_private.h"
#include <sys/types.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdlib.h>
#include <dirent.h>
#include <fcntl.h>
/*
* Get bus information
*/
#if 0
static void
get_host_connection ( linuxdvb_adapter_t *la, int a )
{
FILE *fp;
int speed;
char path[512], buf[512];
/* Check for subsystem */
#define DVB_DEV_PATH "/sys/class/dvb/dvb%d.frontend0/device"
snprintf(path, sizeof(path), DVB_DEV_PATH "/subsystem", a);
if (readlink(tpath, buf, sizeof(buf)) != -1) {
char *bus = basename(buf);
if (!strcmp(bus, "pci")) {
i->bus = BUS_PCI;
} else if (!strcmp(bus, "usb")) {
i->bus = BUS_USB1;
snprintf(path, sizeof(path), DVB_DEV_PATH "/speed", a);
if ((fp = fopen(path, "r"))) {
if (fscanf(fp, "%d", &speed) == 1) {
if (speed > 480) {
i->bus = USB3;
} else if (speed == 480) {
i->bus = USB2;
}
}
fclose(fp);
}
} else {
tvhlog(LOG_WARN, "linuxdvb",
"could not determine host connection for adapter%d", a);
}
}
/* Get ID */
snprintf(path, sizeof(path), DVB_DEV_PATH, a);
if (readlink(tpath, buf, sizeof(buf)) != -1)
strncpy(i->id, basename(buf), sizeof(i->id));
}
#endif
/*
* Check is free
*/
static int
linuxdvb_adapter_is_free ( mpegts_input_t *mi )
{
linuxdvb_hardware_t *lh;
linuxdvb_adapter_t *la = (linuxdvb_adapter_t*)mi;
TAILQ_FOREACH(lh, &la->lh_childs, lh_parent_link)
if (!lh->lh_is_free(lh))
return 0;
return 1;
}
/*
* Get current weight
*/
static int
linuxdvb_adapter_current_weight ( mpegts_input_t *mi )
{
int w = 0;
linuxdvb_hardware_t *lh;
linuxdvb_adapter_t *la = (linuxdvb_adapter_t*)mi;
TAILQ_FOREACH(lh, &la->lh_childs, lh_parent_link)
w = MAX(w, lh->lh_current_weight(lh));
return w;
}
/*
* Load an adapter
*/
linuxdvb_adapter_t *
linuxdvb_adapter_create ( int adapter )
{
int i, r, fd;
char fe_path[512], dmx_path[512], dvr_path[512];
linuxdvb_adapter_t *la = NULL;
struct dvb_frontend_info dfi;
/* Process each frontend */
for (i = 0; i < 32; i++) {
snprintf(fe_path, sizeof(fe_path), "/dev/dvb/adapter%d/frontend%d", adapter, i);
/* No access */
if (access(fe_path, R_OK | W_OK)) continue;
/* Get frontend info */
fd = tvh_open(fe_path, O_RDONLY | O_NONBLOCK, 0);
if (fd == -1) {
tvhlog(LOG_ERR, "linuxdvb", "unable to open %s", fe_path);
continue;
}
r = ioctl(fd, FE_GET_INFO, &dfi);
close(fd);
if(r) {
tvhlog(LOG_ERR, "linuxdvb", "unable to query %s", fe_path);
continue;
}
/* DVR/DMX (bit of a guess) */
snprintf(dmx_path, sizeof(dmx_path), "/dev/dvb/adapter%d/demux%d", adapter, i);
if (access(dmx_path, R_OK | W_OK)) {
snprintf(dmx_path, sizeof(dmx_path), "/dev/dvb/adapter%d/demux0", adapter);
if (access(dmx_path, R_OK | W_OK)) continue;
}
snprintf(dvr_path, sizeof(dvr_path), "/dev/dvb/adapter%d/dvr%d", adapter, i);
if (access(dvr_path, R_OK | W_OK)) {
snprintf(dvr_path, sizeof(dvr_path), "/dev/dvb/adapter%d/dvr0", adapter);
if (access(dvr_path, R_OK | W_OK)) continue;
}
/* Create adapter */
if (!la) {
//la = linuxdvb_hardware_create(linuxdvb_adapter_t);
la->mi_is_free = linuxdvb_adapter_is_free;
la->mi_current_weight = linuxdvb_adapter_current_weight;
}
/* Create frontend */
//linuxdvb_frontend_create(la, fe_path, dmx_path, dvr_path, &dfi);
}
return la;
}

View file

@ -0,0 +1,150 @@
/*
* Tvheadend - Linux DVB frontend
*
* 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/>.
*/
#include "tvheadend.h"
#include "linuxdvb_private.h"
#if 0
static int
linuxdvb_frontend_is_free ( mpegts_input_t *mi )
{
linuxdvb_frontend_t *ldf = (linuxdvb_frontend_t*)mi;
linuxdvb_adapter_t *lda = ldf->mi_adapter;
LIST_FOREACH(ldf, &lda->lda_frontends, mi_adapter_link)
if (!mpegts_input_is_free((mpegts_input_t*)ldf))
return 0;
return 1;
}
static int
linuxdvb_frontend_current_weight ( mpegts_input_t *mi )
{
int w = 0;
linuxdvb_frontend_t *ldf = (linuxdvb_frontend_t*)mi;
linuxdvb_adapter_t *lda = ldf->mi_adapter;
LIST_FOREACH(ldf, &lda->lda_frontends, mi_adapter_link)
w = MAX(w, mpegts_input_current_weight((mpegts_input_t*)ldf));
return w;
}
#endif
static void
linuxdvb_frontend_stop_mux
( mpegts_input_t *mi, mpegts_mux_instance_t *mmi )
{
}
static int
linuxdvb_frontend_start_mux
( mpegts_input_t *mi, mpegts_mux_instance_t *mmi )
{
int r;
linuxdvb_frontend_t *lfe = (linuxdvb_frontend_t*)mi;
mpegts_mux_instance_t *cur = LIST_FIRST(&mi->mi_mux_active);
/* Currently active */
if (cur != NULL) {
/* Already tuned */
if (mmi == cur)
return 0;
/* Stop current */
mmi->mmi_mux->mm_stop(mmi->mmi_mux);
}
assert(LIST_FIRST(&mi->mi_mux_active) == NULL);
/* Start adapter */
linuxdvb_adapter_start(lfe->lfe_parent);
/* Tune */
r = ;
/* Failed */
if (r != 0) {
tvhlog(LOG_ERR, "linuxdvb", "'%s' failed to tune '%s' error %s",
lfe->lfe_path, "TODO", strerror(errno));
if (errno == EINVAL)
mmi->mmi_tune_failed = 1;
return SM_CODE_TUNING_FAILED;
}
/* Start monitor */
time(&lfe->lfe_monitor);
lfe->lfe_monitor += 4;
gtiemr_arm_ms(&lfe->lfe_monitor_timer, linuxdvb_frontend_monitor, lfe, 50);
/* Send alert */
// TODO: should this be moved elsewhere?
return 0;
}
static int
linuxdvb_frontend_open_service
( mpegts_input_t *mi, mpegts_service_t *ms )
{
}
static void
linuxdvb_frontend_close_service
( mpegts_input_t *mi, mpegts_service_t *ms )
{
}
linuxdvb_frontend_t *
linuxdvb_frontend_create
( linuxdvb_adapter_t *adapter,
const char *fe_path,
const char *dmx_path,
const char *dvr_path,
const struct dvb_frontend_info *fe_info )
{
const idclass_t *idc;
/* Class */
if (fe_info->type == FE_QPSK)
idc = &linuxdvb_frontend_dvbs_class;
else if (fe_info->type == FE_QAM)
idc = &linuxdvb_frontend_dvbc_class;
else if (fe_info->type == FE_OFDM)
idc = &linuxdvb_frontend_dvbt_class;
else if (fe_info->type == FE_ATSC)
idc = &linuxdvb_frontend_atsc_class;
else {
tvhlog(LOG_ERR, "linuxdvb", "unknown FE type %d", fe_info->type);
return NULL;
}
linuxdvb_frontend_t *lfe
= mpegts_input_create0(calloc(1, sizeof(linuxdvb_frontend_t)), idc, NULL);
lfe->lfe_fe_path = strdup(fe_path);
lfe->lfe_dmx_path = strdup(dmx_path);
lfe->lfe_dvr_path = strdup(dvr_path);
memcpy(&lfe->lfe_fe_info, fe_info, sizeof(struct dvb_frontend_info));
lfe->mi_start_mux = linuxdvb_frontend_start_mux;
lfe->mi_stop_mux = linuxdvb_frontend_stop_mux;
lfe->mi_open_service = linuxdvb_frontend_open_service;
lfe->mi_close_service = linuxdvb_frontend_close_service;
lfe->mi_is_free = linuxdvb_frontend_is_free;
lfe->mi_current_weight = linuxdvb_frontend_current_weight;
return lfe;
}

View file

@ -0,0 +1,83 @@
/*
* Tvheadend - Linux DVB private data
*
* 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_LINUXDVB_PRIVATE_H__
#define __TVH_LINUXDVB_PRIVATE_H__
#include "input/mpegts.h"
typedef struct linuxdvb_hardware linuxdvb_hardware_t;
typedef struct linuxdvb_adapter linuxdvb_adapter_t;
typedef struct linuxdvb_frontend linuxdvb_frontend_t;
typedef TAILQ_HEAD(,linuxdvb_hardware) linuxdvb_hardware_queue_t;
struct linuxdvb_hardware
{
mpegts_input_t; // this is actually redundant in HW
/* HW tree */
linuxdvb_hardware_t *lh_parent;
TAILQ_ENTRY(linuxdvb_hardware) lh_parent_link;
TAILQ_HEAD(,linuxdvb_hardware) lh_childs;
/* These replicate the mpegts_input_t callbacks but work down the tree */
int (*lh_is_free) (linuxdvb_hardware_t *lh);
int (*lh_current_weight) (linuxdvb_hardware_t *lh);
};
struct linuxdvb_adapter
{
linuxdvb_hardware_t;
/*
* Hardware info
*/
char *la_path;
char *la_dev_id;
enum {
BUS_NONE = 0,
BUS_PCI,
BUS_USB1,
BUS_USB2,
BUS_USB3
} la_dev_bus;
};
linuxdvb_adapter_t *linuxdvb_adapter_create (int a);
struct linuxdvb_frontend
{
linuxdvb_hardware_t;
/*
* Frontend info
*/
struct dvb_frontend_info lfe_fe_info;
char *lfe_fe_path;
char lfe_dmx_path;
char lfe_dvr_path;
};
linuxdvb_frontend_t *linuxdvb_frontend_create
( linuxdvb_adapter_t *la, const char *fe_path,
const char *dmx_path, const char *dvr_path,
const struct dvb_frontend_info *fe_info );
#endif /* __TVH_LINUXDVB_PRIVATE_H__ */

View file

@ -195,6 +195,47 @@ mpegts_mux_start ( mpegts_mux_t *mm, const char *reason, int weight )
return 0;
}
static void
mpegts_mux_stop ( mpegts_mux_t *mm )
{
service_t *s, *t;
mpegts_mux_instance_t *mmi = mm->mm_active;
mpegts_input_t *mi;
/* Flush all subscribers */
if (mmi) {
mi = mmi->mmi_input;
s = LIST_FIRST(&mi->mi_transports);
while (s) {
t = s;
s = LIST_NEXT(t, s_active_link);
if (((mpegts_service_t*)s)->s_dvb_mux != mm)
continue;
service_remove_subscriber(s, NULL, SM_CODE_SUBSCRIPTION_OVERRIDDEN);
}
}
/* Flush all tables */
mpegts_table_flush_all(mm);
/* Alert listeners */
// TODO
/* Scanning */
if (mm->mm_initial_scan_status == MM_SCAN_CURRENT) {
mpegts_network_t *mn = mm->mm_network;
TAILQ_REMOVE(&mn->mn_initial_scan_current_queue, mm, mm_initial_scan_link);
mm->mm_initial_scan_status = MM_SCAN_PENDING;
TAILQ_INSERT_TAIL(&mn->mn_initial_scan_pending_queue, mm, mm_initial_scan_link);
mpegts_network_schedule_initial_scan(mn);
}
/* Clear */
mm->mm_active = NULL;
}
static void
mpegts_mux_open_table ( mpegts_mux_t *mm, mpegts_table_t *mt )
{
@ -245,6 +286,7 @@ mpegts_mux_create0
LIST_INSERT_HEAD(&mn->mn_muxes, mm, mm_network_link);
mm->mm_network = mn;
mm->mm_start = mpegts_mux_start;
mm->mm_stop = mpegts_mux_stop;
mpegts_mux_initial_scan_link(mm);
/* Table processing */

View file

@ -429,7 +429,6 @@ main(int argc, char **argv)
*opt_pidpath = "/var/run/tvheadend.pid",
#if ENABLE_LINUXDVB
*opt_dvb_adapters = NULL,
*opt_dvb_raw = NULL,
#endif
*opt_bindaddr = NULL,
*opt_subscribe = NULL;
@ -727,6 +726,9 @@ main(int argc, char **argv)
#if ENABLE_IPTV
iptv_init();
#endif
#if ENABLE_LINUXDVB
linuxdvb_init(adapter_mask);
#endif
if(opt_subscribe != NULL)
subscription_dummy_join(opt_subscribe, 1);

View file

@ -2391,7 +2391,7 @@ extjs_start(void)
NULL, extjs_tvadapters, ACCESS_ADMIN);
#endif
#if ENABLE_LINUXDVB
#if 0//ENABLE_LINUXDVB
extjs_start_dvb();
#endif

View file

@ -29,11 +29,6 @@
#include "access.h"
#include "epg.h"
#include "channels.h"
#if ENABLE_LINUXDVB
#include "dvr/dvr.h"
#include "dvb/dvb.h"
#include "dvb/dvb_support.h"
#endif
extern char tvh_binshasum[20];

View file

@ -42,10 +42,6 @@
#include "plumbing/globalheaders.h"
#include "epg.h"
#include "muxer.h"
#if ENABLE_LINUXDVB
#include "dvb/dvb.h"
#include "dvb/dvb_support.h"
#endif
#include "imagecache.h"
#include "tcp.h"