Compare commits

...
Sign in to create a new pull request.

86 commits

Author SHA1 Message Date
Adam Sutton
faee94bcb3 Fix #1459 - fix removal of all autorec recordings on startup
There were 2 issues here:
- recent changes meant that recordings were purged on every startup
- long standing issue meant complete recordings were removed on
  removal of an autorec rule (which I don't think was intended).
(cherry picked from commit d23f60b031)
2012-12-27 00:50:13 +00:00
John Törnblom
661124c7a3 muxers: make sure pvr muxer is freed
(cherry picked from commit bf59755681)
2012-12-27 00:14:17 +00:00
John Törnblom
e09a52f2c6 muxers: make sure the default file descriptor for the matroska muxer is an invalid one, not stdout.
(cherry picked from commit 70f0801c9b)
2012-12-27 00:14:17 +00:00
John Törnblom
72b4cd2a2a muxers: make sure the default file descriptor for the passthrough muxer is an invalid one, not stdout.
(cherry picked from commit 442d695445)
2012-12-19 20:32:57 +00:00
Jaroslav Kysela
98f5e898fd Fix #1453 - Fix autorec init issue (duplicate entries)
With previous init change, the scheduled events may be duplicated. Split
the dvr_autorec_init() to two phases:

1) load the autorec list
2) update the scheduled events after dvr db is initialized
(cherry picked from commit 4419dde14b)
2012-12-19 20:32:40 +00:00
Adam Sutton
165e3d4cb0 Fix #1454 - Remove usage of non re-entrant strtok()
Thanks to Jaroslav Kysela <perex@perex.cz> for providing the initial fix.
(cherry picked from commit 86fac417c2)
(cherry picked from commit 7d97d1f648)
(cherry picked from commit a420c83a0e)
2012-12-19 20:32:37 +00:00
Adam Sutton
c9e438e148 Fix #1423 - ensure that XMLTV grabber search does not crash.
It appears that if paths are duplicated in the PATH env variable the
internal search algorithm failed to detect this and could crash due to
an assert in the internal modlue registration code.
(cherry picked from commit 563b8f8c51)
2012-12-19 20:31:56 +00:00
Jernej Fijačko
b6862fe94a [PR-178] Close file pointer after the call to fb_size(fp)
(cherry picked from commit 5d2197c30f)
2012-12-19 20:31:56 +00:00
Adam Sutton
e444d80a23 Fix #1407 - skip unused ISO 8859 control codes.
This had the effect of placing unwanted spaces into various channel
names where the broadcaster was sending these control chars.

Thanks to Rene Herbrich for diagnosing this.
(cherry picked from commit 8a48fe8214)
2012-12-19 20:31:49 +00:00
John Törnblom
897d243dbc Fix #1266 - make sure there is metadata available before atempting to mux it with a recording
(cherry picked from commit ed5d7e4977)
2012-12-19 20:31:33 +00:00
Adam Sutton
3aae092860 Fix #1397 - only load adapter config if tab is enabled.
(cherry picked from commit e74f53574c)
2012-12-19 20:31:33 +00:00
Adam Sutton
4f9f348503 Fix #1393 - minor aesthetic change, remove trailing slash from user config DVR directory.
(cherry picked from commit c05f93da53)
2012-12-19 20:31:26 +00:00
Adam Sutton
0e589a3a43 Fix #1369 - move iptv service type store inside main tab function else it causes a 401 error for non-admin UI users.
(cherry picked from commit 254872a8f8)
(cherry picked from commit 777e4108b9)
2012-12-19 20:31:14 +00:00
John Törnblom
90236176ed htsp: fix 'use after free' of the htsp logname when the connection to the client is lost.
(cherry picked from commit fd6f813d83)
2012-12-19 20:31:05 +00:00
Andreas Öman
e8b55993af htsp: Plug possible memory leak at HTSP disconnect
If subscriber is slow we will leak memory because buffered packets
will not be free'd upon HTSP session close
(cherry picked from commit 683b0f9c8b)
2012-12-19 20:30:58 +00:00
Adam Sutton
4a67395ccc support: Tarball generation script.
(cherry picked from commit ddad1d21dc)
2012-12-19 20:30:51 +00:00
Adam Sutton
40a8920a2a Fix mistake in EPG episode numbering serialisation.
(cherry picked from commit 7a7f57072d)
2012-11-07 10:46:15 +00:00
Andreas Öman
ca5f880027 [memleak] Plug possible memleak when stream content changes
(cherry picked from commit a2cf987afa)
2012-11-07 10:39:01 +00:00
Andreas Öman
10f7cb6f5c [memleak] Plug memory leak in service destruction
(cherry picked from commit 9338b9529e)
2012-11-07 10:38:33 +00:00
Andreas Öman
4380a8051d [memleak] Plug memory leak in epggrab config handling
(cherry picked from commit 2ef7dac597)
2012-11-07 10:38:01 +00:00
Andreas Öman
29dff2d94f h264parser: Treat SPS and PPS id as unsigned
There is a change of crash otherwise if we get a corrupt bitstream
(cherry picked from commit 0d8d8a2da1)
2012-11-05 15:54:46 +00:00
Joakim Hernberg
699d0464fc Fix #1332 - add support for Ku Band lnb with lof 11300 KHz.
(cherry picked from commit ab422204c8)
2012-11-05 12:19:08 +00:00
Andreas Öman
c109026800 HTSP: Handle partial write()s
(cherry picked from commit d5deb9d19d)
2012-11-05 12:09:50 +00:00
Adam Sutton
144ec7dd14 Fix #1377 - check for EOVERFLOW when reading from DVB device.
This can be returned as a result of a failure to read quickly enough from
the DVR device. This appears to happen quite regularly on channel zap for
certain cards. It's non-fatal and the system will auto recover immediately.

For now I've left the exit on other error in, but have added an error
message so we know its happening (the biggest problem was this was happening
silently before).

This may also relate to #1134, so might be worth back porting to 3.2.
(cherry picked from commit 03ff972756)
2012-11-05 11:53:24 +00:00
Adam Sutton
2aa067c73a Fix #1355, #1356 - Fix problem with DVR dup detect.
I have completely removed global duplicate detection at this stage until
such time as I can do things properly. This means a user can ALWAYS manually
override and force a recording of a show.

For now duplicate detection only exists within the context or a series
link. So it will only record the "first?" instance of a given episode in
a give series link.

This is still a bit of a hack until I provide the user with the ability
to control the configuration and implement all the hooks properly.
(cherry picked from commit fbe2db0710)
2012-11-05 11:53:24 +00:00
Adam Sutton
72e369a839 Fix #1226 - remove block to creating empty channels.
(cherry picked from commit 31b1d5b57d)
2012-11-05 11:53:24 +00:00
Adam Sutton
74e73a98e9 Fix #1352 - check return value of setuid/setgid calls.
Also slightly changed the logic so its possible to fork as non-root, though
you must explicitly list your username and group with -u and -g as I do not
want to break built in defaults for compatibility.
(cherry picked from commit a3a917cc29)
2012-11-05 11:53:24 +00:00
Adam Sutton
959d727be8 Fix mistake in dd_progid parsing.
(cherry picked from commit 6b2429bad7)
2012-11-05 11:53:24 +00:00
Adam Sutton
e9fe361907 Fix #1367 - Add protection to stop opentv crashing on bad title descriptor.
(cherry picked from commit d761985f3b)
2012-11-05 11:53:12 +00:00
Adam Sutton
b4c0cfe108 Added quantal and removed hardy from latest dev builds.
(cherry picked from commit f83df17715)

Conflicts:

	support/launchpad-ppa
2012-11-05 11:45:43 +00:00
Andreas Öman
940bc46014 Don't pass uninitialized mem to epoll_ctl()
(cherry picked from commit 2ac1b249df)
2012-11-05 11:44:58 +00:00
Andreas Öman
82dc9c035d Plug some memory leaks
(cherry picked from commit c8e56a2865)
2012-11-05 11:44:57 +00:00
Andreas Öman
008b7058ac Don't have code with side effects in assert()
Including code with side effects in assert() is bad because
it won't be executed if compiled with NDEBUG
(cherry picked from commit cd52d7c216)
2012-11-05 11:44:57 +00:00
Adam Sutton
8a29f8baf8 Stop disabled muxes being re-added to the scan list on startup.
(cherry picked from commit 72d90ee2cd)
2012-11-05 11:44:57 +00:00
John Törnblom
97e0d05070 Let the muxer deref packets all the time. If there is an error, the packet will be droped.
(cherry picked from commit 77a6f4df8d)
2012-10-23 09:56:27 +01:00
John Törnblom
90f4cdef23 make sure the muxer is closed only when its been initilized.
(cherry picked from commit 0d4c30b7da)
2012-10-23 09:56:27 +01:00
John Törnblom
5ebb86fbf1 Log the reason for stoping a http stream.
(cherry picked from commit 5b07fa5b35)
2012-10-23 09:56:27 +01:00
Adam Sutton
e3231ec004 SID to channel number config option was not being stored or loaded.
(cherry picked from commit 3236c4ac62)
2012-10-22 12:44:25 +01:00
Jernej Fijačko
af060cb70d Fix a memory leak in avc_convert_pkt
(cherry picked from commit 899e833cab)
2012-10-22 12:41:27 +01:00
Adam Sutton
9b447c8ed7 Fix open file handle bug and reduce mux config scan depth. Fixes #1325.
(cherry picked from commit 7b6ed15eb9)
2012-10-22 12:41:27 +01:00
John Törnblom
c74b0cf130 buffer ts packets earlier in the call chain.
(cherry picked from commit b232f5ee06)
2012-10-15 11:50:09 +01:00
John Törnblom
6fe1bb5e7c changed the muxer api a bit, the pkt packet type can differ and needs to be casted (from void*).
(cherry picked from commit d84f92028e)
2012-10-15 11:50:09 +01:00
Adam Sutton
4bd0c355b4 Revert "Add the concept of onid into the DVB structures, this will help overcome a few minor issues."
This reverts commit 9ee800a572.

Conflicts:

	src/epggrab/module/eit.c
2012-10-15 10:55:32 +01:00
Adam Sutton
304a6ce26e Revert "[PR-153] check the network id when matching encoding list entries"
This reverts commit 091a4d608b.
2012-10-15 10:53:47 +01:00
Adam Sutton
4303374f77 Redo fix for service primary epg prio check.
(cherry picked from commit 4a10fbfe8f)
2012-10-12 13:14:40 +01:00
Adam Sutton
89071bf55f Revert "Correct inverted prio test for primary EPG service."
This reverts commit 9ebb1f9c4d.
(cherry picked from commit 57ae0b32a9)
2012-10-12 13:14:40 +01:00
Adam Sutton
5bc5d30c66 Change eventDeleted to eventDelete to be consistent. Also minor refactoring to mirror doc section re-ordering.
(cherry picked from commit 626bff4245)
2012-10-12 11:26:06 +01:00
Adam Sutton
2ad41d959f Correct inverted prio test for primary EPG service.
(cherry picked from commit 9ebb1f9c4d)
2012-10-12 10:17:33 +01:00
Adam Sutton
aa42a1c4af Revert "[PR-159] Fix diseqc 1.1 support for use with uncommited switches"
This has caused problems as reported in #1319, until those are fixed it
will be pulled from the release.

This reverts commit af291917ae.
2012-10-12 09:42:11 +01:00
Mariusz Bialonczyk
091a4d608b [PR-153] check the network id when matching encoding list entries
(cherry picked from commit 7faccbaf66)
2012-10-11 15:11:27 +01:00
Adam Sutton
3e3c54100a [PR-153] Generalise the PL specific portions of PR-153
The original patch provided a very PL specific patch, this has now
been expanded to be more general and work better with the previous
charset PR.
(cherry picked from commit 495247bd67)
2012-10-11 15:11:27 +01:00
Mariusz Bialonczyk
8a7db81088 [PR-153] Provide automatic charset overrides for certain services
Certain services on some networks are transmitted with incorrect
charset encodings. The user has the ability to manually override
these, but this provide initial defaults for known bad services.

Mostly this relates to Polish DVB-S providers at this time.
(cherry picked from commit ddbed8be8c)
2012-10-11 15:11:27 +01:00
Adam Sutton
2dc947c5dc Series link fields were not being checked. Fixes #1318.
(cherry picked from commit 852e1ee397)
2012-10-11 15:11:27 +01:00
Adam Sutton
1bc2dd9a25 Fix problems with XMLTV time processing.
(cherry picked from commit a13f3b8119)
2012-10-11 15:11:27 +01:00
Andreas Öman
4e2ed9f406 Avoid infinte loop in read_golomb_ue()
(cherry picked from commit ce019c896d)
2012-10-11 15:11:27 +01:00
Adam Sutton
4daa250749 Remove confusing debug about invalid TSID, this can happen a lot during re-tuning.
(cherry picked from commit 33c91a4606)
2012-10-11 15:11:27 +01:00
Adam Sutton
6d3874c262 Remove horrible printf that got left in.
(cherry picked from commit e42ee19d7b)
2012-10-11 15:11:27 +01:00
Adam Sutton
9ee800a572 Add the concept of onid into the DVB structures, this will help overcome a few minor issues.
(cherry picked from commit 1cc67b75e8)
2012-10-11 15:11:27 +01:00
Adam Sutton
78605b4a81 Update support/version to use more explicit version tags.
(cherry picked from commit 9cac818532)
2012-10-10 15:50:32 +01:00
Johan Abbors
b80fdefe16 Fix version for launchpad builds using recipes
Git operations are not allowed in launchpad, thus the version number
must be extracted from the changeleg.
(cherry picked from commit 1a7e2b489f)
2012-10-10 15:50:32 +01:00
Adam Sutton
bf9b74be15 Update to previous duplicate mux fix, this should do a better job.
(cherry picked from commit 16fdfd2547)
2012-10-10 15:47:55 +01:00
Adam Sutton
274dd64c2c Fix duplicate mux issues by pushing all mux freq to 1KHz boundary. Fixes #1310.
This is really considered a hack, it will be replaced with a better internal
DVB structure in 3.4.
(cherry picked from commit afd468ef83)
2012-10-10 15:47:54 +01:00
Adam Sutton
c4ec5aae9e Modify hts_settings_remove to also remove (empty) dirs.
(cherry picked from commit 1ad73ec803)
2012-10-10 15:47:54 +01:00
Joakim Hernberg
af291917ae [PR-159] Fix diseqc 1.1 support for use with uncommited switches
(cherry picked from commit bfa18f5440)
2012-10-10 15:47:54 +01:00
Jacek Tomasiak
7fc4b013c8 Added debian build files to gitignore
(cherry picked from commit 977a35375f)
2012-10-10 15:47:54 +01:00
Adam Sutton
4dce901813 [PR-155] Ensure any existing configuration is honoured.
(cherry picked from commit 1d7fd005e0)
2012-10-10 15:47:54 +01:00
Jacek Tomasiak
713d8cf511 [PR-155] Change dvb charset to allow proper overriding.
dvb_charset field (in service UI config) now overrides any DVB provided
values rather than simply acting as a default for where values are not
specified.

This helps fix problems both where providers fail to specify the charset
(and ISO6937 is not used) and also where the simply specify the wrong
charset entirely.
(cherry picked from commit aff490c6b2)
2012-10-10 15:47:54 +01:00
Adam Sutton
a652cbe541 Fix printing error in epggrab.
(cherry picked from commit 7e71efaeef)
2012-10-10 15:47:54 +01:00
Adam Sutton
7771a7d7ef Hide the UI top bar as it takes up screen space. Fixes #1296.
(cherry picked from commit 9f07d4f3c9)
2012-10-10 15:47:54 +01:00
Adam Sutton
fca3d93575 Fix problem with genre compat between HTSP v5 and v6.
(cherry picked from commit 6dd6f1ca11)
2012-10-10 15:47:54 +01:00
Adam Sutton
7687dd4ecd Added some extra debug and protection when getting mux config. 2012-10-04 21:55:22 +01:00
Adam Sutton
a0bf0d1d8f Some support scripts. 2012-10-04 21:55:22 +01:00
Adam Sutton
9c44621116 Fix JS stray comma. Fixes #1299. 2012-10-04 21:55:04 +01:00
Jernej Fijačko
91cdb11c0d xmltv_load_grabbers - only call closedir when opendir was successfull
I'm working on an android build and it crashes here if opendir returns NULL. Not sure if this is also an issue on other systems.
2012-10-03 11:47:56 +01:00
Adam Sutton
da7869ebe8 Ensure adapters panel properly resizes. 2012-10-03 11:47:46 +01:00
xhaggi
c8d4befefa webui: set auto scrolling to true for general tv adapter panel
Without this you can't scroll down to the save button of this panel.
2012-10-03 11:47:38 +01:00
Adam Sutton
1b357d7040 Update documentation, also shift a few UI config values around and make some stuff a bit clearer. Fixes #1280. Relates #1150. 2012-10-03 11:47:22 +01:00
Adam Sutton
eee0a98600 Stop crash if existing sub exists where all services are currently less than 10%. Fixes #1289 2012-10-03 11:47:22 +01:00
Adam Sutton
de85fef7c2 Updated the build system for better consistency. Also make it easier to do source builds for things like launchpad PPAs. 2012-10-03 11:47:22 +01:00
Adam Sutton
48bc79843a Fix minor printing error. Fixes #1265. 2012-10-03 11:47:22 +01:00
Andreas Öman
391f5912fe Add lucid targets 2012-10-03 11:47:22 +01:00
Adam Sutton
329c7566aa Ensure that disabled muxes are immediately detuned. Fixes #1258. 2012-09-27 15:29:54 +01:00
Adam Sutton
1c2dcd94bf Add missing parantheses. 2012-09-27 13:34:11 +01:00
Adam Sutton
4e57ef651b Ensure that ch_epg_now and next get cleared to stop false usage (getref/putref in timer callback). Fixes #1257. 2012-09-26 12:54:14 +01:00
Adam Sutton
34c1fcb0bc Fix erroneous duplicate sending of event description in HTSP. May fix possible XBMC display problems. 2012-09-26 12:41:24 +01:00
Adam Sutton
4ef346bda0 Remove hard requirement on avahi and zlib in configure command as zlib breaks on Lucid due to broken pkg-config. 2012-09-25 17:06:34 +01:00
83 changed files with 1742 additions and 516 deletions

8
.gitignore vendored
View file

@ -1,6 +1,8 @@
build.*
.config.mk
src/version.c
.cproject
.project
.settings
@ -8,3 +10,9 @@ data/dvb-scan
*.pyc
.*.sw[op]
debian/files
debian/tvheadend
debian/tvheadend-dbg
debian/tvheadend*substvars
debian/tvheadend*.debhelper*

View file

@ -1,16 +1,12 @@
BUILD_DEPS=`awk 'BEGIN {cnt = 1;} /^Build-Depends:/ {split($0, line, ":");split(line[2], deps, ",");for (i in deps) {d = deps[i];sub(/^ */, "", d);sub(/ *$/, "", d);split(d, tokens, " ");packages[cnt] = tokens[1];cnt++;}} END {out = ""; for(i = 1; i <= cnt; i++) {out = out packages[i] " ";} print out; }' debian/control`
CHANGELOG=debian/changelog
NOW=`date -R`
VER=`git describe | sed "s/\([0-9]*\)\.\([0-9]*\)-\([0-9]*\)-.*/\1.\2.\3/"`
VER=`$(dirname $0)/support/version`
[ -z "${DEBDIST:-}" ] && DEBDIST=""
build()
{
echo >${CHANGELOG} "tvheadend (${VER}) unstable; urgency=low"
echo >>${CHANGELOG}
echo >>${CHANGELOG} " * The full changelog can be found at "
echo >>${CHANGELOG} " http://www.lonelycoder.com/tvheadend/download"
echo >>${CHANGELOG}
echo >>${CHANGELOG} " -- Andreas Öman <andreas@lonelycoder.com> ${NOW}"
$(dirname $0)/support/changelog "$CHANGELOG" "$DEBDIST" "$VER"
export JOBSARGS
export JARGS
@ -18,22 +14,22 @@ build()
dpkg-buildpackage -b -us -uc
for a in ../tvheadend*${VER}*.deb; do
versioned_artifact "$a" deb application/x-deb `basename $a`
versioned_artifact "$a" deb application/x-deb `basename $a`
done
for a in ../tvheadend*${VER}*.changes; do
versioned_artifact "$a" changes text/plain `basename $a`
versioned_artifact "$a" changes text/plain `basename $a`
done
}
clean()
{
for a in ../tvheadend*${VER}*.deb; do
rm -f "$a"
rm -f "$a"
done
for a in ../tvheadend*${VER}*.changes; do
rm -f "$a"
rm -f "$a"
done
rm -f ${CHANGELOG}
@ -43,8 +39,8 @@ clean()
deps()
{
if [[ $EUID -ne 0 ]]; then
echo "Build dependencies must be installed as root"
exit 1
echo "Build dependencies must be installed as root"
exit 1
fi
apt-get -y install ${BUILD_DEPS}
}

3
Autobuild/lucid-amd64.sh Normal file
View file

@ -0,0 +1,3 @@
AUTOBUILD_CONFIGURE_EXTRA="${AUTOBUILD_CONFIGURE_EXTRA:-} --arch=x86_64"
DEBDIST=lucid
source Autobuild/debian.sh

3
Autobuild/lucid-i386.sh Normal file
View file

@ -0,0 +1,3 @@
AUTOBUILD_CONFIGURE_EXTRA="${AUTOBUILD_CONFIGURE_EXTRA:-} --arch=i686"
DEBDIST=lucid
source Autobuild/debian.sh

View file

@ -1,2 +1,3 @@
AUTOBUILD_CONFIGURE_EXTRA="${AUTOBUILD_CONFIGURE_EXTRA:-_} --arch=x86_64"
AUTOBUILD_CONFIGURE_EXTRA="${AUTOBUILD_CONFIGURE_EXTRA:-} --arch=x86_64"
DEBDIST=precise
source Autobuild/debian.sh

View file

@ -1,2 +1,3 @@
AUTOBUILD_CONFIGURE_EXTRA="${AUTOBUILD_CONFIGURE_EXTRA:-_} --arch=i686"
AUTOBUILD_CONFIGURE_EXTRA="${AUTOBUILD_CONFIGURE_EXTRA:-} --arch=i686"
DEBDIST=precise
source Autobuild/debian.sh

View file

@ -146,6 +146,7 @@ SRCS += src/muxer.c \
SRCS-${CONFIG_LINUXDVB} += \
src/dvb/dvb.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 \
@ -232,9 +233,8 @@ distclean: clean
rm -f ${CURDIR}/.config.mk
# Create buildversion.h
src/version.c: $(BUILDDIR)/buildversion.h
$(BUILDDIR)/buildversion.h: FORCE
@$(CURDIR)/support/version.sh $(CURDIR) $@
src/version.c: FORCE
@$(CURDIR)/support/version $@ > /dev/null
FORCE:
# Include dependency files if they exist.

18
README
View file

@ -1,8 +1,7 @@
Tvheadend TV streaming server
=============================
(c) 2006 - 2010 Andreas Öman, et al.
(c) 2006 - 2012 Andreas Öman, et al.
How to build for Linux
@ -12,17 +11,20 @@ First you need to configure:
$ ./configure
If any dependencies are missing the configure script will complain.
You then have the option to disable that particular module/subsystem.
If any dependencies are missing the configure script will complain or attempt
to disable optional features.
$ make
Build the binary, after build the binary resides in 'build.Linux/'.
Build the binary, after build the binary resides in 'build.linux/'.
Thus, to start it, just type:
$ build.linux/tvheadend
$ ./build.linux/tvheadend
Settings are stored in $HOME/.hts/tvheadend
For more information and latest versions, please visit:
http://www.lonelycoder.com/hts/
Further information
===================
For more information about building, including generating packages please
visit https://www.lonelycoder.com/redmine/projects/tvheadend/wiki/Building

415
data/conf/charset Normal file
View file

@ -0,0 +1,415 @@
[
{
"tsid": 200,
"onid": 318,
"charset": "ISO6937",
"sid": 13878,
"description": "ESP2 NE Polish"
},
{
"tsid": 200,
"onid": 318,
"charset": "ISO6937",
"sid": 13865,
"description": "Hotbird Eutelsat (Eurosport)"
},
{
"tsid": 300,
"onid": 318,
"charset": "ISO8859-2",
"sid": 15206,
"description": "Animal Planet HD"
},
{
"tsid": 400,
"onid": 318,
"charset": "ISO8859-2",
"sid": 13020,
"description": "Hotbird 13.0 Cyfra+ Canal+ HD Polska"
},
{
"tsid": 400,
"onid": 318,
"charset": "ISO8859-2",
"sid": 13022,
"description": "Hotbird 13.0 Cyfra+ Canal+ Sport HD Polska"
},
{
"tsid": 400,
"onid": 318,
"charset": "ISO8859-2",
"sid": 13023,
"description": "Hotbird 13.0 Cyfra+ National Geographic HD Polska"
},
{
"tsid": 400,
"onid": 318,
"charset": "ISO8859-2",
"sid": 13025,
"description": "Hotbird 13.0 Cyfra+ Filmbox HD"
},
{
"tsid": 400,
"onid": 318,
"charset": "ISO8859-2",
"sid": 13026,
"description": "Hotbird 13.0 Cyfra+ AXN Spin HD"
},
{
"tsid": 400,
"onid": 318,
"charset": "ISO8859-2",
"sid": 13027,
"description": "Hotbird 13.0 Cyfra+ TVN 7 HD"
},
{
"tsid": 400,
"onid": 318,
"charset": "ISO8859-2",
"sid": 13070,
"description": "Hotbird 13.0 Cyfra+ ESP HD PL"
},
{
"tsid": 400,
"onid": 318,
"charset": "ISO8859-2",
"sid": 13081,
"description": "EUROSPORT HD"
},
{
"tsid": 400,
"onid": 318,
"charset": "ISO8859-2",
"sid": 13082,
"description": "EUROSPORT HD"
},
{
"tsid": 1000,
"onid": 318,
"charset": "ISO8859-2",
"sid": 4314,
"description": "nSport"
},
{
"tsid": 1000,
"onid": 318,
"charset": "ISO6937",
"sid": 0,
"description": "Hotbird 13.0 Grupa ITI"
},
{
"tsid": 1100,
"onid": 318,
"charset": "ISO8859-2",
"sid": 0,
"description": "Hotbird 13.0 Cyfra+"
},
{
"tsid": 1500,
"onid": 318,
"charset": "ISO8859-2",
"sid": 5110,
"description": "TV Info"
},
{
"tsid": 1500,
"onid": 318,
"charset": "ISO8859-2",
"sid": 5108,
"description": "Fox Polska"
},
{
"tsid": 1500,
"onid": 318,
"charset": "ISO8859-2",
"sid": 5102,
"description": "TVS"
},
{
"tsid": 1500,
"onid": 318,
"charset": "ISO8859-2",
"sid": 5122,
"description": "Animal Planet Poland"
},
{
"tsid": 1500,
"onid": 318,
"charset": "ISO6937",
"sid": 0,
"description": "Hotbird 13.0 Cyfra+"
},
{
"tsid": 1600,
"onid": 318,
"charset": "ISO8859-2",
"sid": 0,
"description": "Hotbird 13.0 EskaTV, TVN"
},
{
"tsid": 1800,
"onid": 200,
"charset": "ISO6937",
"sid": 3623,
"description": "Hotbird 13.0 Polo TV"
},
{
"tsid": 7400,
"onid": 113,
"charset": "ISO6937",
"sid": 0,
"description": "Hotbird 13.0 Cyfrowy Polsat"
},
{
"tsid": 7800,
"onid": 113,
"charset": "ISO8859-2",
"sid": 0,
"description": "Hotbird 13.0 Cyfrowy Polsat"
},
{
"tsid": 7900,
"onid": 113,
"charset": "ISO6937",
"sid": 10510,
"description": "TV6 Polska"
},
{
"tsid": 7900,
"onid": 113,
"charset": "ISO6937",
"sid": 10508,
"description": "Hotbird 13.0 Cyfrowy Polsat Jim Jam"
},
{
"tsid": 7900,
"onid": 113,
"charset": "ISO6937",
"sid": 10521,
"description": "SuperStacja"
},
{
"tsid": 7900,
"onid": 113,
"charset": "ISO6937",
"sid": 10520,
"description": "Travel Channel"
},
{
"tsid": 7900,
"onid": 113,
"charset": "ISO8859-2",
"sid": 0,
"description": "Hotbird 13.0 Cyfrowy Polsat"
},
{
"tsid": 8100,
"onid": 318,
"charset": "ISO6937",
"sid": 14911,
"description": "UNIVERSAL POL"
},
{
"tsid": 8100,
"onid": 318,
"charset": "ISO6937",
"sid": 14910,
"description": "Sport Klub POL"
},
{
"tsid": 8100,
"onid": 318,
"charset": "ISO8859-2",
"sid": 0,
"description": "Hotbird 13.0 Eutelsat (Universal)"
},
{
"tsid": 11000,
"onid": 318,
"charset": "ISO6937",
"sid": 0,
"description": "Hotbird 13.0 Cyfra+"
},
{
"tsid": 11400,
"onid": 318,
"charset": "ISO8859-2",
"sid": 15716,
"description": "Discovery Channel Polska"
},
{
"tsid": 11400,
"onid": 318,
"charset": "ISO8859-2",
"sid": 15701,
"description": "Discovery Science Polska"
},
{
"tsid": 11400,
"onid": 318,
"charset": "ISO8859-2",
"sid": 15703,
"description": "Discovery World Polska"
},
{
"tsid": 11400,
"onid": 318,
"charset": "ISO6937",
"sid": 0,
"description": "Hotbird 13.0 Cyfra+"
},
{
"tsid": 11600,
"onid": 318,
"charset": "ISO6937",
"sid": 3514,
"description": "Disney XD Polska"
},
{
"tsid": 11600,
"onid": 318,
"charset": "ISO8859-2",
"sid": 0,
"description": "Hotbird 13.0 BBC HD, ITI"
},
{
"tsid": 11900,
"onid": 318,
"charset": "ISO6937",
"sid": 0,
"description": "Hotbird 13.0 Cyfra+"
},
{
"tsid": 12200,
"onid": 318,
"charset": "ISO6937",
"sid": 0,
"description": "Hotbird 13.0 Disney Channel Polska, TCM and other"
},
{
"tsid": 12800,
"onid": 318,
"charset": "ISO6937",
"sid": 24,
"description": "CC Family."
},
{
"tsid": 12800,
"onid": 318,
"charset": "ISO6937",
"sid": 6,
"description": "Viacom Blink!"
},
{
"tsid": 12800,
"onid": 318,
"charset": "ISO6937",
"sid": 22,
"description": "MTV Polska."
},
{
"tsid": 12800,
"onid": 318,
"charset": "ISO6937",
"sid": 30,
"description": "Comedy Central Polska."
},
{
"tsid": 12800,
"onid": 318,
"charset": "ISO6937",
"sid": 25,
"description": "VIVA Polska."
},
{
"tsid": 12800,
"onid": 318,
"charset": "ISO8859-2",
"sid": 0,
"description": "Hotbird 13.0 Viacom ... MTV / VH1 Polska"
},
{
"tsid": 13000,
"onid": 318,
"charset": "ISO6937",
"sid": 14612,
"description": "Investigation Discovery Polska"
},
{
"tsid": 13000,
"onid": 318,
"charset": "ISO6937",
"sid": 14613,
"description": "TLC Polska"
},
{
"tsid": 13000,
"onid": 318,
"charset": "ISO6937",
"sid": 14602,
"description": "BBC Entertainment Poland"
},
{
"tsid": 13000,
"onid": 318,
"charset": "ISO6937",
"sid": 14603,
"description": "BBC Knowledge Poland"
},
{
"tsid": 13000,
"onid": 318,
"charset": "ISO8859-2",
"sid": 0,
"description": "Hotbird 13.0 BBC Polska, TLC and other"
},
{
"tsid": 13100,
"onid": 318,
"charset": "ISO6937",
"sid": 7322,
"description": "TV5 Monde Europe"
},
{
"tsid": 13100,
"onid": 318,
"charset": "ISO6937",
"sid": 7324,
"description": "Hotbird 13.0 Crime and Investigation"
},
{
"tsid": 13200,
"onid": 113,
"charset": "ISO88959-2",
"sid": 13104,
"description": "Polsat Sport"
},
{
"tsid": 13200,
"onid": 113,
"charset": "ISO88959-2",
"sid": 13105,
"description": "Polsat Sport Extra"
},
{
"tsid": 13200,
"onid": 113,
"charset": "ISO88959-2",
"sid": 13107,
"description": "TV Biznes"
},
{
"tsid": 13200,
"onid": 113,
"charset": "ISO6937",
"sid": 0,
"description": "Hotbird 13.0 Cyfrowy Polsat"
},
{
"tsid": 15700,
"onid": 318,
"charset": "ISO6937",
"sid": 10626,
"description": "Hotbird 13.0 Disco TV"
}
]

2
debian/rules vendored
View file

@ -5,7 +5,7 @@ export DH_VERBOSE=1
dh $@
override_dh_auto_configure:
dh_auto_configure -- ${JOBSARGS} --enable-avahi --enable-zlib
dh_auto_configure -- ${JOBSARGS}
override_dh_auto_build:
make ${JARGS}

View file

@ -47,12 +47,18 @@ The columns have the following functions:
<dd>
Only match events from the given channel.
<dt>Series Link
<dd>
Checkbox indicates that a series link (using EPG provided info) is being
used, rather than a simple title match. The title field is still populated,
for clarity, with the title of the event used to create the series link.
<dt>Channel tag
<dd>
Only match events from the channels which are included in the given tag.
Tags are used for grouping channels and is configured by the administrator.
<dt>Content group
<dt>Genre
<dd>
Only match events belonging to the given content group.
@ -65,6 +71,14 @@ The columns have the following functions:
<dd>
Only record events if they are scheduled +-15 minutes from this given time.
<dt>Priority
<dd>
The priority to give any recordings scheduled by this auto recording rule.
<dt>DVR configuration
<dd>
Select the DVR configuration profile to be used for scheduled recordings.
<dt>Created by
<dd>
Free text field, but will be copied to the recording session.

View file

@ -61,8 +61,11 @@ The columns have the following functions:
<dt>Video Recorder
<dd>
Enables access to all video recording functions. This also include administration
of the auto recordings.
Enables access to all video recording functions. This also include administration of the auto recordings.
<dt>All Configs (VR)
<dd>
Allow use of and configuration of DVR configuration profiles.
<dt>Web interface
<dd>

View file

@ -31,12 +31,20 @@
Changing name of a channel does not interfere with scheduled
recordings etc.
<dt>XML-TV Source
<dd>Name of the XML-TV channel. If you have XML-TV enabled you can
select which XML-TV channel to obtain data from. By default
Tvheadend tries to match the name itself, but sometimes it might
not match between the XML-TV source and the TV provider so in
such cases you can change it yourself.
<dt>Play
<dd>Play the channel using the VLC plugin (if available) else it will
display a direct link that can be used to open in preferred media
player.
<dt>EPG Grab Source
<dd>Name of the Internet based EPG provider (typically XMLTV) channel
that should be used to update this channels EPG info.
By default Tvheadend tries to match the name itself, but sometimes
it might not match correctly in which case you can do the mapping
manually.
<p>
Over the air (OTA) sources do NOT need to be mapped in this way, the
linking is implicitly tied since they are all part of the DVB system.
<dt>Tags
<dd>Each channel can be bound to a zero, one or many tags.

View file

@ -22,7 +22,9 @@
<dt>Adapter name
<dd>
You can change the display name for the adapter.
You can change the display name for the adapter. This is highly recommended
for multi-adapter setups with adapters that report the same name to avoid
confusion.
<dt>Autodetect muxes
<dd>
@ -30,6 +32,15 @@
on the same network. If this checkbox is enabled, Tvheadend will
automatically create new muxes as it receives configuration for them
via the DVB networks.
<dt>Skip initial scan
<dd>
By default Tvheadend will rescan all muxes before more detailed background
scanning (including EPG scans) can be properly started. This is to verify
all muxes are still valid.
<br/>
This will not stop the ability to watch live TV, however for most setups
this option can be checked.
<dt>Idle scanning
<dd>
@ -37,11 +48,71 @@
muxes and tune to them to verify that they are still working.
If your adapter have problems with lots of tuning, try to disable this.
<dt>Detailed logging
<dt>Close device handle when idle
<dd>
If this is enabled, Tvheadend will log more information related to
this specific adapter. You might wanna enable this if you have some
kind of issues in order to better diagnose the problems.
This will attempt to close all available device handles. This can be
necessary to allow some devices to go into low power states.
<br/>
However this option has been known to cause problems with some multi tuner
DVB cards. If you have signal problems, try disabling this option.
<br/>
Note: this option has no effect if idle scanning is enabled.
<dt>Skip service availability check when mapping
<dd>
By default Tvheadend will validate that a service can be correctly
received (including any descrambling) when mapping channels. You can disable
this checking by enabling this option.
<dt>Use SID as channel number during mapping
<dd>
If you enable this option then the initial mapping of channels will use
the service ID as the channel number, should no local channel number be
provided in the service information tables.
<dt>Monitor signal quality
<dd>
If you enable this option Tvheadend will attempt to monitor signal quality
of a mux using an internal metric. If the calculated quality falls to low
the mux/adapter will generally be ignored.
<dt>Disable PMT monitoring
<dd>
This disable monitoring Program Map Table (PMT) for all services on a mux.
<br/>
Most people should not require this, but because this involves creating a
lot of table filters, some DVB cards have problems and report errors related
to too many open file descriptors. If this happens try enabling this option.
<dt>Write full DVB MUX to disk
<dd>
If this is enabled, Tvheadend will store the full mux stream to disk for
debugging and development purposes. Don't enable this unless you know what
you're doing.
<dt>Original Network ID
<dd>
If you experience problems caused by overlaps between multiple network
providers this option can be used to filter which network ID is received
by a given adapter.
<dt>Extra priority
<dd>
This field can be used to define a priority ordering for adapters. This will
be used when determining which adapter to use to service a subscription
request. It could be used for example to prefer a DVB-S adapter over a
DVB-T one.
<dt>DiSEqC version (DVB-S only)
<dd>
If you're using a DiSEqC switch, then specify the version here.
<dt>Turn off LNB when idle
<dd>
This option can be enabled to disable the power to the LNB when the adapter
is not in use. This can reduce power consumption, however for poorly shieled
multi tuner setups you may some inteference when the LNB is re-enabled.
</dl>
</dl>
@ -79,7 +150,16 @@
<dt>Modulation
<dd>Information about the modulation used on the mux. Can not be changed
<dt>Polarisation
<dd>Information about the polarisation used on the mux. Can not be changed
<dt>Satellite config (DVB-S only)
<dd>The satellite configuration in use on this mux. Can not be changed.
<dt>Frontend status
<dd>The status of the frontend signal last time the mux was tuned. Can not be changed
<dt>Mux id
<dd>Unique ID for this mux in the dvb network. Can not be changed
@ -116,6 +196,9 @@
<dt>Service name
<dd>Service name as given in the DVB stream. Can not be changed
<dt>Play
<dd>Open the VLC plugin window to play this service.
<dt>Channel name
<dd>Double-click on this column to map the service to a channel.
@ -126,8 +209,8 @@
but fail to correctly announce it. To fix this you can set the default
charset to use when none is specified by the broadcaster.
<dt>EIT
<dd>Uncheck this if EIT data should not be retreived for this service.
<dt>EPG
<dd>Uncheck this if EPG data should not be retreived for this service.
<dt>Type
<dd>Type of service. Can not be changed
@ -144,9 +227,47 @@
<dt>Information button
<dd>Press this to get a popup with more information about the service
</dl>
</dl>
<p>
A word about DVB adapters
<dl>
<dt>Satellite config (DVB-S only)</dt>
Satellite configurations in use on this adapter (for controlling
switch equipment). The default entry will work fine for non-switched
setups.
<ul>
<li>To edit a cell, double-click on it. After a cell is changed it
will flags one of its corner to red to indicated that it has been
changed. To commit these changes back to Tvheadend press the
'Save changes' button. In order to change a Checkbox cell you only
have to click once in it.
<li>To delete one or more entries, select the lines (by clicking once on
them), and press the 'Delete selected' button. A popup
will ask you to confirm your request. Note, that if you have
automatic mux discovery enabled the mux will probably come back
quite soon.
</ul>
The columns have the following functions:
<dl>
<dt>Name
<dd>Descriptive name for this configuration
<dt>Switchport
<dd>Port number to select for this configuration (numbering begins at 0).
<dt>LNB type
<dd>Select the LNB type from the list of supported LNBs. If your LNB
is not supported please contact the Tvheadend team.
<dt>Comment
<dd>General comment to remind you what this is for.
</dl>
</dl>
<h2>A word about DVB adapters</h2>
<p>
A DVB adapter represents a piece of hardware attached to the system.
DVB receivers with dual tuners will present themselves as two adapters
@ -169,6 +290,5 @@
Warning2: Suspending a system is (from a USB driver perspective) equivalent
to a unplug/insert event. Thus, suspending a system running Tvheadend
with USB adapters is not recommended at the moment.
</dl>
</div>

View file

@ -13,11 +13,22 @@
<dd>Path to where Tvheadend will write recorded events. If components of
the path does not exist, Tvheadend will try to create them.
<dt>Media container
<dd>Select the container format used to store recordings.
<dt>DVR Log retention time (days)
<dd>Time that Tvheadend will keep information about the recording in
its internal database. Notice that the actual recorded file will not
be deleted when the log entry is deleted.
<dt>Extra time before recordings (minutes)
<dd>Specify the number of minutes to record before the events scheduled
start time. Used to cope with small scheduling errors.
<dt>Extra time after recordings (minutes)
<dd>Specify the number of minutes to record after the events scheduled
stop time. Used to cope with small scheduling errors.
<dt>Make sub-directories per day
<dd>If checked, Tvheadend will create a new directory per day in the
recording system path. Only days when anything is recorded will be
@ -52,6 +63,17 @@
<dd>If checked, Tvheadend will include the season and episode in the
title (if such info is available).
<dt>Remove all unsafe characters from filename
<dd>If checked, all characters that could possibly cause problems for
filenaming will be removed.
<dt>Replace whitespace in title with '-'
<dd>If checked, all whitespace characters will be replaced with '-'.
<dt>Tag files with metadata
<dd>If checked, media containers that support metadata will be tagged with
the metadata associated with the event being recorded.
<dt>Post-processor command
<dd>Command to run after finishing a recording. The command will be
run in background and is executed even if a recording is aborted

View file

@ -3,56 +3,78 @@
<p>
This tab is used to configure EPG grabbing capabilities. TVheadend supports
a variety of different EPG grabbing mechanisms. These fall into 3 broad
categories, within which there are a variety of specific grabber implementations.
categories, within which there are a variety of specific grabber
implementations.
</p>
<h2>Grabber Types</h2>
<ul>
<li>Over the Air (OTA) - these receive EPG data directly from the DVB network. This is often the easiest way to get up and running, and does provide timely updates should scheduling change. However the information isn't always as rich as some of the other grabbers.</li>
<li>Interanl - These are grabbers which can be internally initiated from within TVheadend based on IP based grabbing solutions (see below). This can be a quick way to get richer EPG data where you don't have decent OTA support.</li>
<li>External - These provide the option to run the grabber scripts externally and to pump the data into TVheadend via Unix domain sockets. It provides more complex configurations using things like cronjob's etc.</li>
<li>Over-the-Air (OTA) - These grabbers receive EPG data directly from the DVB network. This is often the easiest way to get up and running and does provide timely updates should scheduling change. However the information isn't always as rich as some of the other grabbers.
<li>Internal - These are grabbers which can be internally initiated from within TVheadend using a very simple scheduler. These are typically Internet based services. This can be a quick way to get richer EPG data where you don't have decent OTA support.
<li>External - These provide the option to run grabber scripts externally and to send data into TVheadend via Unix domain sockets. It provides the ability to run more complex configurations using things like cronjob's, script chains, etc.
</ul>
<h2>Grabber Modules</h2>
<ul>
<li>EIT - This is a DVB standards compatible EIT grabber. Typically it will
retrieve now/next information, though on some networks there may be more
extensive data published.</li>
<li>OpenTV - This is a proprietary OTA EPG grabber. Its known to be used on the SKY networks, but others may use it. You need two configuration files to define settings for your particular network, if you don't see yours listed please visit IRC #hts for help.</li>
<li>XMLTV - This is a IP network based scraper, for more information about XMLTV please visit <a href="http://www.xmltv.org">http://www.xmltv.org</a>. To make use of the internal XMLTV grabber you must have tv_find_grabbers installed. If you install new grabbers you will need to restart TVheadend to pick these up asthey're loaded at startup.</li>
<li>PyEPG - This is another IP network based scraper. It currently only supports the Atlas UK system (for which you need a key), but it does provide a very rich EPG data set. For more information see <a href='http://github.com/adamsutton/PyEPG'>http://github.com/adamsutton/PyEPG</a>.</li>
extensive data published.
<li>Freesat/view - This is an extended version of EIT that is used by the Free-to-air DVB providers in the UK. It includes additional information such as series links and episode identifiers.
<li>OpenTV - This is a proprietary OTA EPG grabber. Its known to be used on the SKY networks, but others may use it. You need two configuration files to define settings for your particular network, if you don't see yours listed please visit IRC #hts for help.
<li>XMLTV - This is am Internet based suite of scripts, for more information about XMLTV please visit <a href="http://www.xmltv.org">http://www.xmltv.org</a>. To make use of the internal XMLTV grabber you typically require the xmltv-utils package to be installed. If you install new grabbers you will need to restart TVheadend to pick these up as they're loaded at startup. If you see no XMLTV grabbers listed then most probably XMLTV is not properly installed and in the PATH.
<li>PyEPG - This is another Internet based scraper. It currently only supports the Atlas UK system (for which you need a key), but it does provide a very rich EPG data set. For more information see <a href='http://github.com/adamsutton/PyEPG'>http://github.com/adamsutton/PyEPG</a>.</li>
</ul>
<h2>Configuration options</h2>
<p>
<h3>General Config</h3>
<dl>
<dt>Update channel name
<dd>Automatically update channel names using information provided
by the enabled EPG providers.
<dt>Update channel number
<dd>Automatically update channel numbers using information provided
by the enabled EPG providers.
<dt>Update channel name
<dd>Automatically update channel icons using information provided
by the enabled EPG providers.
</dl>
<h3>Internal Grabber</h3>
<dl>
<dt>Module:
<dd>Select which internal grabber to use.
<dt>Grab interval
<dd>Time period between grabs.
<dt>External interfaces
<dd>Check tick boxes for whichever you want to make available, the Path column displays where the unix socket you need to use lives.
<dt>OTA interfaces
<dd>Check tick boxes for whichever you want to use.
<dd>Time period between grabs. Value and unit are indepdently set.
</dl>
Changes to any of these settings must be confirmed by pressing the
'Save configuration' button before taking effect.
</p>
<h3>Over-the-air Grabbers</h3>
<p>
Checkbox list to enable/disable available modules.
By default all grabbers should be enabled.
<h3>External interfaces</h3>
<p>
Checkbox list to enable/disable available modules. The path field
contains the absolute path of the unix domain socket into which EPG
data can be sent.`
<p>
To send data to the socket use the command "netcat -u SOCKET_PATH".
<br/>
Note: for some systems the netcat flags can vary so please consult the
man page.
<h2>Notes</h2>
<p>
To apply any changes please use the [Save configuration button]
<p>
XMLTV/PyEPG - if you are using the internal versions of these modules then
you must first configure them (if required) externally as TVHeadend provides
no support for this. Once configured though TVheadend will do the rest.
</p>
<p>
Mixed grabbers - Although as much as possible is done to avoid contention, generally speaking using a mixture of grabbers should be avoided (where each grabber updates the same channels). They typically tend to contain differing information which results in them "fighting" over which information is correct and can result in a high level of EPG update messages.
you must first configure them externally as Tvheadend provides
no support for this. Nor does it provide the ability to pass command line
options (for this use the external interface).
</p>
</div>

View file

@ -0,0 +1,48 @@
<div class="hts-doc-text">
Tvheadend support receiving streams from compatible IPTV services. Currently
the only compatible services are those that broadcast using MPEGTS over
multicast UDP.
<p>
The services are listed / edited in a grid.
<ul>
<li>To edit a cell, double click on it. After a cell is changed it
will flags one of its corner to red to indicated that it has been
changed. To commit these changes back to Tvheadend press the
'Save changes' button. In order to change a Checkbox cell you only
have to click once in it.
<li>To add a new entry, press the 'Add entry' button. The new (empty) entry
will be created on the server but will not be in its enabled state.
You can now change all the cells to the desired values, check the
'enable' box and then press 'Save changes' to activate the new entry.
<li>To delete one or more entries, select the lines (by clicking once on
them), and press the 'Delete selected' button. A pop up
will ask you to confirm your request.
</ul>
<p>
The columns have the following functions:
<dl>
<dt>Enabled
<dd>If selected, the IPTV service will be enabled an use for channel
subscriptions.
<dt>Channel name
<dd>Select the channel this service will be mapped to.
<dt>Interface
<dd>The ethernet interface to receive data on.
<dt>Group
<dd>The multicast group to register with to receive data.
<dt>UDP Port
<dd>Server UDP port
</dl>
</div>

View file

@ -6,10 +6,19 @@
</p>
<dl>
<dt>DVB scan files path:
<dd>Select the path to use for DVB scan configuration files. Typically</dt>
dvb-apps stores these in /usr/share/dvb/. Leave blank to use TVH's internal
file set (probably stored at /usr/share/tvheadend/data/dvb-scan/)</dd>
</dl>
<dt>Default Language(s)
<dd>
Select the list of languages (in order of priority) to be used for supplying
EPG information to clients that don't provide their own configuration.
<p>
The EPG information is NOT translated, this only applies to EPG providers
that give information (titles, descriptions, etc..) in multiple languages.
<dt>DVB scan files path:
<dd>
Select the path to use for DVB scan configuration files. Typically
dvb-apps stores these in /usr/share/dvb/. Leave blank to use TVH's internal
file set.
</dl>
</div>

View file

@ -21,20 +21,21 @@ sorted based on start time.
expression. If you don't know what a regular expression is this means
that you can type just parts of the title and filter on that too.
(No need for exact matching).
<dt>[Only include channel...]
<dt>[Filter channel...]
<dd>
Only display events from the selected channel.
<dt>[Only include tag...]
Only display events from the selected channel. Channels in the drop down are
ordered by channel number and can be filtered (by name) by typing in the box.
<dt>[Filter tag...]
<dd>
Only display events from the channels which are included in the selected tag.
Tags are used for grouping channels and is configured by the administrator.
<dt>[Only include content...]
<dt>[Filter content type...]
<dd>
Most DVB networks classify their events into content groups. This field
allows you to filter based on content type.
</dl>
Thus, if you only would like to browse Movies from your HD-channels you
would select 'HD channels' in the [Only include tag...]-field, and select
would select 'HDTV' in the [Filter tag...]-field, and select
'Movie / Drama' in the [Only include content...]-field.
<p>
Notice that you don't have to press a 'Search' button, the grid immediately
@ -45,8 +46,8 @@ sorted based on start time.
<dt>Paging
<dd>
In an installation with many (hundreds of) channels and full EPG feed from
both DVB and XMLTV there will be tens of thousands of events in the database.
In large installations with many channels and full EPG feed there could be
tens of thousands of events in the database.
Therefore the EPG display employs a paging bar at the bottom of the grid.
Use it to browse backwards and forwards in the EPG. It also displays the
total amount of events matched by the current query.
@ -57,6 +58,12 @@ sorted based on start time.
about the event. It also allows the user to schedule the event for recording
by clicking on the [Record program] button.
<p>
For EPG providers that supply series link information there will also be a
[Record series] button that will record all entries in the series.
<p>
For events without any series link information, a [Autorec] button will be
provided to create a pseudo series link using hte Autorec feature.
<p>
<img src="docresources/epg2.png">
<p>
To close the popup, just close it with the [X] window button.
@ -67,7 +74,7 @@ sorted based on start time.
<dt>Autorecordings
<dd>
Should you wish to record all events matching a specific query. (Record
your favorite TV-show, etc) you can press the 'Create Autorec' button
your favorite TV-show, etc) you can press the [Create Autorec] button
in the top toolbar.
<p>
A popup with details about the to-be-created autorecording rule needs to
@ -78,5 +85,11 @@ sorted based on start time.
The autorecordings can later be changed/deleted in under the
'Digital Video Recorder'-tag. Use that editor if you temporary want
to disable an autorecording or make adjustments, etc.
<dt>Watch TV
<dd>
If you want to watch live TV in the web UI, the [Watch TV] button will pop-up
a VLC plugin window (if you don't have the plugin installed a direct URL should be
provided to load into your preferred media player).
</dl>
</div>

View file

@ -28,7 +28,6 @@
<dl>
<dt>HTSP (Home TV Streaming Protocol), supported by Showtime Media player and <a href="http://www.xbmc.org/">XBMC</a>
<dt>The Built-in Digital Video Recorder
<dt>RTSP server
</dl>
<dt>Modern web user interface
@ -48,14 +47,14 @@
<dt>Digital Video Recorder
<dd>
Built in video recorder stores recorded programs as
<a href="http://www.matroska.org/">Matroska (.mkv)</a> files.
Built in video recorder stores recorded programs as either
<a href="http://www.matroska.org/">Matroska (.mkv)</a> or MPEG TS (.ts) files.
Multiple simultaneous recordings are supported.
All original streams (multiple audio tracks, etc) are recorded.
<dt>Electronic Program Guide
<dd>
Imports data from DVB and <a href="http://www.xmltv.org">XMLTV</a>.
Imports data from DVB and Internet providers such as <a href="http://www.xmltv.org">XMLTV</a>.
Searchable from the web user interface. Results can be scheduled
for recording with a single click.

View file

@ -3,8 +3,8 @@
<center>
<h1>HTS Tvheadend 2.11</h1>
&copy; 2006 - 2010, Andreas Öman, et al.<br><br>
<h1>HTS Tvheadend 3.2</h1>
&copy; 2006 - 2012, Andreas Öman, et al.<br><br>
<img style="padding: 0px" src="docresources/tvheadendlogo.png">
</center>

View file

@ -186,8 +186,6 @@ avc_convert_pkt(th_pkt_t *src)
pkt->pkt_header = NULL;
pkt->pkt_payload = NULL;
pkt->pkt_payload = malloc(sizeof(pktbuf_t));
pkt->pkt_payload->pb_refcount=1;
if (src->pkt_header) {
sbuf_t headers;
sbuf_init(&headers);

View file

@ -46,6 +46,13 @@ skip_bits(bitstream_t *bs, int num)
bs->offset += num;
}
int
bs_eof(const bitstream_t *bs)
{
return bs->offset >= bs->len;
}
unsigned int
read_bits(bitstream_t *bs, int num)
{
@ -76,7 +83,7 @@ read_golomb_ue(bitstream_t *bs)
{
int b, lzb = -1;
for(b = 0; !b; lzb++)
for(b = 0; !b && !bs_eof(bs); lzb++)
b = read_bits1(bs);
return (1 << lzb) - 1 + read_bits(bs, lzb);

View file

@ -44,4 +44,6 @@ unsigned int remaining_bits(bitstream_t *gb);
void put_bits(bitstream_t *bs, int val, int num);
int bs_eof(const bitstream_t *bs);
#endif /* BITSTREAM_H_ */

View file

@ -210,14 +210,14 @@ channel_find_by_name(const char *name, int create, int channel_number)
{
channel_t skel, *ch;
if (!name || !*name) return NULL;
lock_assert(&global_lock);
skel.ch_name = (char *)name;
ch = RB_FIND(&channel_name_tree, &skel, ch_name_link, channelcmp);
if(ch != NULL || create == 0)
return ch;
if (name) {
skel.ch_name = (char *)name;
ch = RB_FIND(&channel_name_tree, &skel, ch_name_link, channelcmp);
if(ch != NULL || create == 0)
return ch;
}
return channel_create2(name, channel_number);
}

View file

@ -20,9 +20,11 @@
#include "tvheadend.h"
#include "dvb.h"
#include "dvb_support.h"
#include "dvb_charset.h"
void
dvb_init(uint32_t adapter_mask)
{
dvb_charset_init();
dvb_adapter_init(adapter_mask);
}

View file

@ -215,7 +215,7 @@ typedef struct th_dvb_adapter {
struct dvb_satconf_queue tda_satconfs;
struct th_dvb_mux_instance_list tda_mux_hash[TDA_MUX_HASH_WIDTH];
struct th_dvb_mux_instance_list tda_mux_list;
uint32_t tda_dump_muxes;
@ -395,7 +395,7 @@ void dvb_mux_add_to_scan_queue (th_dvb_mux_instance_t *tdmi);
/**
* DVB Transport (aka DVB service)
*/
void dvb_transport_load(th_dvb_mux_instance_t *tdmi);
void dvb_transport_load(th_dvb_mux_instance_t *tdmi, const char *tdmi_identifier);
struct service *dvb_transport_find(th_dvb_mux_instance_t *tdmi,
uint16_t sid, int pmt_pid,

View file

@ -88,6 +88,7 @@ tda_save(th_dvb_adapter_t *tda)
htsmsg_add_u32(m, "idlescan", tda->tda_idlescan);
htsmsg_add_u32(m, "idleclose", tda->tda_idleclose);
htsmsg_add_u32(m, "skip_checksubscr", tda->tda_skip_checksubscr);
htsmsg_add_u32(m, "sidtochan", tda->tda_sidtochan);
htsmsg_add_u32(m, "qmon", tda->tda_qmon);
htsmsg_add_u32(m, "dump_muxes", tda->tda_dump_muxes);
htsmsg_add_u32(m, "poweroff", tda->tda_poweroff);
@ -481,7 +482,9 @@ dvb_adapter_start ( th_dvb_adapter_t *tda )
/* Start DVR thread */
if (tda->tda_dvr_pipe[0] == -1) {
assert(pipe(tda->tda_dvr_pipe) != -1);
int err = pipe(tda->tda_dvr_pipe);
assert(err != -1);
fcntl(tda->tda_dvr_pipe[0], F_SETFD, fcntl(tda->tda_dvr_pipe[0], F_GETFD) | FD_CLOEXEC);
fcntl(tda->tda_dvr_pipe[0], F_SETFL, fcntl(tda->tda_dvr_pipe[0], F_GETFL) | O_NONBLOCK);
fcntl(tda->tda_dvr_pipe[1], F_SETFD, fcntl(tda->tda_dvr_pipe[1], F_GETFD) | FD_CLOEXEC);
@ -509,7 +512,8 @@ dvb_adapter_stop ( th_dvb_adapter_t *tda )
/* Stop DVR thread */
if (tda->tda_dvr_pipe[0] != -1) {
tvhlog(LOG_DEBUG, "dvb", "%s stopping thread", tda->tda_rootpath);
assert(write(tda->tda_dvr_pipe[1], "", 1) == 1);
int err = write(tda->tda_dvr_pipe[1], "", 1);
assert(err != -1);
pthread_join(tda->tda_dvr_thread, NULL);
close(tda->tda_dvr_pipe[0]);
close(tda->tda_dvr_pipe[1]);
@ -567,6 +571,7 @@ dvb_adapter_init(uint32_t adapter_mask)
htsmsg_get_u32(c, "idlescan", &tda->tda_idlescan);
htsmsg_get_u32(c, "idleclose", &tda->tda_idleclose);
htsmsg_get_u32(c, "skip_checksubscr", &tda->tda_skip_checksubscr);
htsmsg_get_u32(c, "sidtochan", &tda->tda_sidtochan);
htsmsg_get_u32(c, "qmon", &tda->tda_qmon);
htsmsg_get_u32(c, "dump_muxes", &tda->tda_dump_muxes);
htsmsg_get_u32(c, "poweroff", &tda->tda_poweroff);
@ -742,6 +747,7 @@ dvb_adapter_input_dvr(void *aux)
/* Create poll */
efd = epoll_create(2);
memset(&ev, 0, sizeof(ev));
ev.events = EPOLLIN;
ev.data.fd = fd;
epoll_ctl(efd, EPOLL_CTL_ADD, fd, &ev);
@ -760,8 +766,16 @@ dvb_adapter_input_dvr(void *aux)
if (c < 0) {
if (errno == EAGAIN || errno == EINTR)
continue;
else
else if (errno == EOVERFLOW) {
tvhlog(LOG_WARNING, "dvb", "\"%s\" read() EOVERFLOW",
tda->tda_identifier);
continue;
} else {
// TODO: should we try to recover?
tvhlog(LOG_ERR, "dvb", "\"%s\" read() error %d",
tda->tda_identifier, errno);
break;
}
}
r += c;
@ -803,7 +817,7 @@ dvb_adapter_input_dvr(void *aux)
pthread_mutex_unlock(&tda->tda_delivery_mutex);
/* reset buffer */
if (r) {memmove(tsb, tsb+i, r);printf("move");}
if (r) memmove(tsb, tsb+i, r);
i = 0;
}

96
src/dvb/dvb_charset.c Normal file
View file

@ -0,0 +1,96 @@
/*
* tvheadend, charset list
* Copyright (C) 2012 Mariusz Białończyk
*
* 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 <string.h>
#include "tvheadend.h"
#include "settings.h"
#include "dvb/dvb_charset.h"
/*
* Process a file
*/
static void _charset_load_file()
{
htsmsg_t *l, *e;
htsmsg_field_t *f;
dvb_charset_t *enc;
const char *charset;
uint32_t tsid, onid, sid;
int i = 0;
l = hts_settings_load("charset");
if (l)
{
HTSMSG_FOREACH(f, l) {
if ((e = htsmsg_get_map_by_field(f))) {
tsid = onid = sid = 0;
htsmsg_get_u32(e, "onid", &onid);
htsmsg_get_u32(e, "tsid", &tsid);
htsmsg_get_u32(e, "sid", &sid);
charset = htsmsg_get_str(e, "charset");
if (tsid == 0 || onid == 0 || !charset)
continue;
enc = calloc(1, sizeof(dvb_charset_t));
if (enc)
{
enc->onid = onid;
enc->tsid = tsid;
enc->sid = sid;
enc->charset = strdup(charset);
LIST_INSERT_HEAD(&dvb_charset_list, enc, link);
i++;
}
}
};
htsmsg_destroy(l);
};
if (i > 0)
tvhlog(LOG_INFO, "charset", "%d entries loaded", i);
}
/*
* Initialise the charset list
*/
void dvb_charset_init ( void )
{
_charset_load_file();
}
/*
* Find default charset
*/
const char *dvb_charset_find
( uint16_t tsid, uint16_t sid )
{
dvb_charset_t *ret = NULL, *enc;
LIST_FOREACH(enc, &dvb_charset_list, link) {
if (tsid == enc->tsid) {
if (sid == enc->sid) {
ret = enc;
break;
} else if (!enc->sid) {
ret = enc;
}
}
}
return ret ? ret->charset : NULL;
}

37
src/dvb/dvb_charset.h Normal file
View file

@ -0,0 +1,37 @@
/*
* tvheadend, dvb charset config
* Copyright (C) 2012 Mariusz Białończyk
*
* 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_DVB_CHARSET_H__
#define __TVH_DVB_CHARSET_H__
typedef struct dvb_charset {
LIST_ENTRY(dvb_charset) link;
uint16_t onid;
uint16_t tsid;
uint16_t sid;
const char *charset;
} dvb_charset_t;
LIST_HEAD(,dvb_charset) dvb_charset_list;
void dvb_charset_init ( void );
const char *dvb_charset_find
(uint16_t tsid, uint16_t sid);
#endif /* __TVH_DVB_CHARSET_H__ */

View file

@ -104,7 +104,10 @@ static int
tdmi_compare_key(const struct dvb_mux_conf *a,
const struct dvb_mux_conf *b)
{
return a->dmc_fe_params.frequency == b->dmc_fe_params.frequency &&
int32_t fd = (int32_t)a->dmc_fe_params.frequency
- (int32_t)b->dmc_fe_params.frequency;
fd = labs(fd);
return fd < 2000 &&
a->dmc_polarisation == b->dmc_polarisation &&
a->dmc_satconf == b->dmc_satconf;
}
@ -155,15 +158,12 @@ dvb_mux_create(th_dvb_adapter_t *tda, const struct dvb_mux_conf *dmc,
dvb_satconf_t *satconf)
{
th_dvb_mux_instance_t *tdmi, *c;
unsigned int hash;
char buf[200];
lock_assert(&global_lock);
hash = (dmc->dmc_fe_params.frequency +
dmc->dmc_polarisation) % TDA_MUX_HASH_WIDTH;
LIST_FOREACH(tdmi, &tda->tda_mux_hash[hash], tdmi_adapter_hash_link) {
/* HACK - we hash/compare based on 2KHz spacing and compare on +/-500Hz */
LIST_FOREACH(tdmi, &tda->tda_mux_list, tdmi_adapter_hash_link) {
if(tdmi_compare_key(&tdmi->tdmi_conf, dmc))
break; /* Mux already exist */
}
@ -172,6 +172,7 @@ dvb_mux_create(th_dvb_adapter_t *tda, const struct dvb_mux_conf *dmc,
/* Update stuff ... */
int save = 0;
char buf2[1024];
buf2[0] = 0;
if(tdmi_compare_conf(tda->tda_type, &tdmi->tdmi_conf, dmc)) {
#if DVB_API_VERSION >= 5
@ -189,19 +190,25 @@ dvb_mux_create(th_dvb_adapter_t *tda, const struct dvb_mux_conf *dmc,
dvb_mux_rolloff2str(tdmi->tdmi_conf.dmc_fe_rolloff),
dvb_mux_rolloff2str(dmc->dmc_fe_rolloff));
sprintf(buf2, "%s)", buf2);
#else
buf2[0] = 0;
#endif
memcpy(&tdmi->tdmi_conf, dmc, sizeof(struct dvb_mux_conf));
save = 1;
}
if(tdmi->tdmi_transport_stream_id != tsid) {
if(tsid != 0xFFFF && tdmi->tdmi_transport_stream_id != tsid) {
tdmi->tdmi_transport_stream_id = tsid;
save = 1;
}
/* HACK - load old transports and remove old mux config */
if(identifier) {
save = 1;
dvb_transport_load(tdmi, identifier);
hts_settings_remove("dvbmuxes/%s/%s",
tda->tda_identifier, identifier);
}
if(save) {
dvb_mux_save(tdmi);
dvb_mux_nicename(buf, sizeof(buf), tdmi);
@ -268,7 +275,7 @@ dvb_mux_create(th_dvb_adapter_t *tda, const struct dvb_mux_conf *dmc,
tdmi, tdmi_satconf_link);
}
LIST_INSERT_HEAD(&tda->tda_mux_hash[hash], tdmi, tdmi_adapter_hash_link);
LIST_INSERT_HEAD(&tda->tda_mux_list, tdmi, tdmi_adapter_hash_link);
LIST_INSERT_HEAD(&tda->tda_muxes, tdmi, tdmi_adapter_link);
if(source != NULL) {
@ -279,15 +286,17 @@ dvb_mux_create(th_dvb_adapter_t *tda, const struct dvb_mux_conf *dmc,
dvb_adapter_notify(tda);
}
dvb_transport_load(tdmi);
dvb_transport_load(tdmi, identifier);
dvb_mux_notify(tdmi);
if(enabled && initialscan) {
tda->tda_initial_num_mux++;
tdmi->tdmi_table_initial = 1;
mux_link_initial(tda, tdmi);
} else {
dvb_mux_add_to_scan_queue(tdmi);
if(enabled) {
if(initialscan) {
tda->tda_initial_num_mux++;
tdmi->tdmi_table_initial = 1;
mux_link_initial(tda, tdmi);
} else {
dvb_mux_add_to_scan_queue(tdmi);
}
}
return tdmi;
@ -864,6 +873,9 @@ tdmi_set_enable(th_dvb_mux_instance_t *tdmi, int enabled)
if(tdmi->tdmi_enabled) {
if(tda->tda_mux_current == tdmi)
dvb_fe_stop(tdmi, 0);
if(tdmi->tdmi_scan_queue != NULL) {
TAILQ_REMOVE(tdmi->tdmi_scan_queue, tdmi, tdmi_scan_link);
tdmi->tdmi_scan_queue = NULL;
@ -1174,8 +1186,8 @@ dvb_mux_copy(th_dvb_adapter_t *dst, th_dvb_mux_instance_t *tdmi_src,
if(t_src->s_svcname != NULL)
t_dst->s_svcname = strdup(t_src->s_svcname);
if(t_src->s_dvb_default_charset != NULL)
t_dst->s_dvb_default_charset = strdup(t_src->s_dvb_default_charset);
if(t_src->s_dvb_charset != NULL)
t_dst->s_dvb_charset = strdup(t_src->s_dvb_charset);
if(t_src->s_ch != NULL)
service_map_channel(t_dst, t_src->s_ch, 0);

View file

@ -296,6 +296,7 @@ dvb_lnblist_get(void)
add_to_lnblist(array, "C-Band");
add_to_lnblist(array, "C-Multi");
add_to_lnblist(array, "Circular 10750");
add_to_lnblist(array, "Ku 11300");
return array;
}
@ -338,5 +339,9 @@ dvb_lnb_get_frequencies(const char *id, int *f_low, int *f_hi, int *f_switch)
*f_low = 10750000;
*f_hi = 0;
*f_switch = 0;
} else if(!strcmp(id, "Ku 11300")) {
*f_low = 11300000;
*f_hi = 0;
*f_switch = 0;
}
}

View file

@ -95,10 +95,7 @@ static inline size_t conv_8859(int conv,
(*dstlen)--;
dst++;
} else if (c <= 0x9f) {
// codes 0x80 - 0x9f (control codes) are mapped to ' '
*dst = ' ';
(*dstlen)--;
dst++;
// codes 0x80 - 0x9f (control codes) are ignored
} else {
// map according to character table, skipping
// unmapped chars (value 0 in the table)
@ -135,10 +132,7 @@ static inline size_t conv_6937(const uint8_t *src, size_t srclen,
(*dstlen)--;
dst++;
} else if (c <= 0x9f) {
// codes 0x80 - 0x9f (control codes) are mapped to ' '
*dst = ' ';
(*dstlen)--;
dst++;
// codes 0x80 - 0x9f (control codes) are ignored
} else {
uint16_t uc;
if (c >= 0xc0 && c <= 0xcf) {
@ -202,7 +196,7 @@ static inline size_t dvb_convert(int conv,
*/
int
dvb_get_string(char *dst, size_t dstlen, const uint8_t *src, size_t srclen, char *dvb_default_charset, dvb_string_conv_t *conv)
dvb_get_string(char *dst, size_t dstlen, const uint8_t *src, size_t srclen, const char *dvb_charset, dvb_string_conv_t *conv)
{
int ic;
size_t len, outlen;
@ -220,6 +214,7 @@ dvb_get_string(char *dst, size_t dstlen, const uint8_t *src, size_t srclen, char
conv++;
}
// automatic charset detection
switch(src[0]) {
case 0:
return -1;
@ -250,16 +245,17 @@ dvb_get_string(char *dst, size_t dstlen, const uint8_t *src, size_t srclen, char
return -1;
default:
if (dvb_default_charset != NULL && sscanf(dvb_default_charset, "ISO8859-%d", &i) > 0) {
if (i > 0 && i < 16) {
ic = convert_iso_8859[i];
} else {
ic = convert_iso6937;
}
ic = convert_iso6937;
break;
}
// manual charset override
if (dvb_charset != NULL && dvb_charset[0] != 0) {
if (sscanf(dvb_charset, "ISO8859-%d", &i) > 0 && i > 0 && i < 16) {
ic = convert_iso_8859[i];
} else {
ic = convert_iso6937;
}
break;
}
if(srclen < 1) {
@ -284,7 +280,7 @@ dvb_get_string(char *dst, size_t dstlen, const uint8_t *src, size_t srclen, char
int
dvb_get_string_with_len(char *dst, size_t dstlen,
const uint8_t *buf, size_t buflen, char *dvb_default_charset,
const uint8_t *buf, size_t buflen, const char *dvb_charset,
dvb_string_conv_t *conv)
{
int l = buf[0];
@ -292,7 +288,7 @@ dvb_get_string_with_len(char *dst, size_t dstlen,
if(l + 1 > buflen)
return -1;
if(dvb_get_string(dst, dstlen, buf + 1, l, dvb_default_charset, conv))
if(dvb_get_string(dst, dstlen, buf + 1, l, dvb_charset, conv))
return -1;
return l + 1;

View file

@ -62,11 +62,11 @@ typedef struct dvb_string_conv
} dvb_string_conv_t;
int dvb_get_string(char *dst, size_t dstlen, const uint8_t *src,
const size_t srclen, char *dvb_default_charset,
const size_t srclen, const char *dvb_charset,
dvb_string_conv_t *conv);
int dvb_get_string_with_len(char *dst, size_t dstlen,
const uint8_t *buf, size_t buflen, char *dvb_default_charset,
const uint8_t *buf, size_t buflen, const char *dvb_charset,
dvb_string_conv_t *conv);
#define bcdtoint(i) ((((i & 0xf0) >> 4) * 10) + (i & 0x0f))

View file

@ -186,12 +186,59 @@ dvb_transport_refresh(service_t *t)
}
/**
*
*/
static void
dvb_transport_save(service_t *t)
{
htsmsg_t *m = htsmsg_create_map();
lock_assert(&global_lock);
htsmsg_add_u32(m, "service_id", t->s_dvb_service_id);
htsmsg_add_u32(m, "pmt", t->s_pmt_pid);
htsmsg_add_u32(m, "stype", t->s_servicetype);
htsmsg_add_u32(m, "scrambled", t->s_scrambled);
htsmsg_add_u32(m, "channel", t->s_channel_number);
if(t->s_provider != NULL)
htsmsg_add_str(m, "provider", t->s_provider);
if(t->s_svcname != NULL)
htsmsg_add_str(m, "servicename", t->s_svcname);
if(t->s_ch != NULL) {
htsmsg_add_str(m, "channelname", t->s_ch->ch_name);
htsmsg_add_u32(m, "mapped", 1);
}
if(t->s_dvb_charset != NULL)
htsmsg_add_str(m, "dvb_charset", t->s_dvb_charset);
htsmsg_add_u32(m, "dvb_eit_enable", t->s_dvb_eit_enable);
if(t->s_default_authority)
htsmsg_add_str(m, "default_authority", t->s_default_authority);
pthread_mutex_lock(&t->s_stream_mutex);
psi_save_service_settings(m, t);
pthread_mutex_unlock(&t->s_stream_mutex);
hts_settings_save(m, "dvbtransports/%s/%s",
t->s_dvb_mux_instance->tdmi_identifier,
t->s_identifier);
htsmsg_destroy(m);
dvb_transport_notify(t);
}
/**
* Load config for the given mux
*/
void
dvb_transport_load(th_dvb_mux_instance_t *tdmi)
dvb_transport_load(th_dvb_mux_instance_t *tdmi, const char *tdmi_identifier)
{
htsmsg_t *l, *c;
htsmsg_field_t *f;
@ -199,10 +246,17 @@ dvb_transport_load(th_dvb_mux_instance_t *tdmi)
const char *s;
unsigned int u32;
service_t *t;
int old;
lock_assert(&global_lock);
if((l = hts_settings_load("dvbtransports/%s", tdmi->tdmi_identifier)) == NULL)
/* HACK - use provided identifier to load config incase we've migrated
* mux freq */
if (!tdmi_identifier)
tdmi_identifier = tdmi->tdmi_identifier;
old = strcmp(tdmi_identifier, tdmi->tdmi_identifier);
if((l = hts_settings_load("dvbtransports/%s", tdmi_identifier)) == NULL)
return;
HTSMSG_FOREACH(f, l) {
@ -237,8 +291,9 @@ dvb_transport_load(th_dvb_mux_instance_t *tdmi)
psi_load_service_settings(c, t);
pthread_mutex_unlock(&t->s_stream_mutex);
s = htsmsg_get_str(c, "dvb_default_charset");
t->s_dvb_default_charset = s ? strdup(s) : NULL;
if (!(s = htsmsg_get_str(c, "dvb_charset")))
s = htsmsg_get_str(c, "dvb_default_charset");
t->s_dvb_charset = s ? strdup(s) : NULL;
s = htsmsg_get_str(c, "default_authority");
t->s_default_authority = s ? strdup(s) : NULL;
@ -253,57 +308,22 @@ dvb_transport_load(th_dvb_mux_instance_t *tdmi)
if(s && u32)
service_map_channel(t, channel_find_by_name(s, 1, 0), 0);
/* HACK - force save for old config */
if(old)
dvb_transport_save(t);
}
/* HACK - remove old settings */
if(old) {
HTSMSG_FOREACH(f, l)
hts_settings_remove("dvbtransports/%s/%s", tdmi_identifier, f->hmf_name);
hts_settings_remove("dvbtransports/%s", tdmi_identifier);
}
htsmsg_destroy(l);
}
/**
*
*/
static void
dvb_transport_save(service_t *t)
{
htsmsg_t *m = htsmsg_create_map();
lock_assert(&global_lock);
htsmsg_add_u32(m, "service_id", t->s_dvb_service_id);
htsmsg_add_u32(m, "pmt", t->s_pmt_pid);
htsmsg_add_u32(m, "stype", t->s_servicetype);
htsmsg_add_u32(m, "scrambled", t->s_scrambled);
htsmsg_add_u32(m, "channel", t->s_channel_number);
if(t->s_provider != NULL)
htsmsg_add_str(m, "provider", t->s_provider);
if(t->s_svcname != NULL)
htsmsg_add_str(m, "servicename", t->s_svcname);
if(t->s_ch != NULL) {
htsmsg_add_str(m, "channelname", t->s_ch->ch_name);
htsmsg_add_u32(m, "mapped", 1);
}
if(t->s_dvb_default_charset != NULL)
htsmsg_add_str(m, "dvb_default_charset", t->s_dvb_default_charset);
htsmsg_add_u32(m, "dvb_eit_enable", t->s_dvb_eit_enable);
if(t->s_default_authority)
htsmsg_add_str(m, "default_authority", t->s_default_authority);
pthread_mutex_lock(&t->s_stream_mutex);
psi_save_service_settings(m, t);
pthread_mutex_unlock(&t->s_stream_mutex);
hts_settings_save(m, "dvbtransports/%s/%s",
t->s_dvb_mux_instance->tdmi_identifier,
t->s_identifier);
htsmsg_destroy(m);
dvb_transport_notify(t);
}
/**
* Called to get quality for the given transport
@ -459,8 +479,8 @@ dvb_transport_build_msg(service_t *t)
if(t->s_ch != NULL)
htsmsg_add_str(m, "channelname", t->s_ch->ch_name);
if(t->s_dvb_default_charset != NULL)
htsmsg_add_str(m, "dvb_default_charset", t->s_dvb_default_charset);
if(t->s_dvb_charset != NULL)
htsmsg_add_str(m, "dvb_charset", t->s_dvb_charset);
htsmsg_add_u32(m, "dvb_eit_enable", t->s_dvb_eit_enable);

View file

@ -247,6 +247,8 @@ void dvr_config_delete(const char *name);
void dvr_entry_notify(dvr_entry_t *de);
void dvr_entry_save(dvr_entry_t *de);
const char *dvr_entry_status(dvr_entry_t *de);
const char *dvr_entry_schedstatus(dvr_entry_t *de);
@ -280,6 +282,8 @@ void dvr_init(void);
void dvr_autorec_init(void);
void dvr_autorec_update(void);
void dvr_destroy_by_channel(channel_t *ch);
void dvr_rec_subscribe(dvr_entry_t *de);

View file

@ -38,12 +38,14 @@ dtable_t *autorec_dt;
TAILQ_HEAD(dvr_autorec_entry_queue, dvr_autorec_entry);
static int dvr_autorec_in_init = 0;
struct dvr_autorec_entry_queue autorec_entries;
static void dvr_autorec_changed(dvr_autorec_entry_t *dae);
static void dvr_autorec_changed(dvr_autorec_entry_t *dae, int purge);
/**
*
* Unlink - and remove any unstarted
*/
static void
dvr_autorec_purge_spawns(dvr_autorec_entry_t *dae)
@ -53,7 +55,10 @@ dvr_autorec_purge_spawns(dvr_autorec_entry_t *dae)
while((de = LIST_FIRST(&dae->dae_spawns)) != NULL) {
LIST_REMOVE(de, de_autorec_link);
de->de_autorec = NULL;
dvr_entry_cancel(de);
if (de->de_sched_state == DVR_SCHEDULED)
dvr_entry_cancel(de);
else
dvr_entry_save(de);
}
}
@ -77,11 +82,14 @@ autorec_cmp(dvr_autorec_entry_t *dae, epg_broadcast_t *e)
(dae->dae_title == NULL ||
dae->dae_title[0] == '\0') &&
dae->dae_brand == NULL &&
dae->dae_season == NULL)
dae->dae_season == NULL &&
dae->dae_serieslink == NULL)
return 0; // Avoid super wildcard match
// Note: we always test season first, though it will only be set
// if configured
if(dae->dae_serieslink)
if (!e->serieslink || dae->dae_serieslink != e->serieslink) return 0;
if(dae->dae_season)
if (!e->episode->season || dae->dae_season != e->episode->season) return 0;
if(dae->dae_brand)
@ -199,9 +207,11 @@ autorec_entry_destroy(dvr_autorec_entry_t *dae)
LIST_REMOVE(dae, dae_channel_tag_link);
if(dae->dae_brand)
dae->dae_brand->putref((epg_object_t*)dae->dae_brand);
dae->dae_brand->putref(dae->dae_brand);
if(dae->dae_season)
dae->dae_season->putref((epg_object_t*)dae->dae_season);
dae->dae_season->putref(dae->dae_season);
if(dae->dae_serieslink)
dae->dae_serieslink->putref(dae->dae_serieslink);
TAILQ_REMOVE(&autorec_entries, dae, dae_link);
@ -417,7 +427,8 @@ autorec_record_update(void *opaque, const char *id, htsmsg_t *values,
if (dae->dae_serieslink)
dae->dae_serieslink->getref(dae->dae_serieslink);
}
dvr_autorec_changed(dae);
if (!dvr_autorec_in_init)
dvr_autorec_changed(dae, 1);
return autorec_record_build(dae);
}
@ -460,7 +471,18 @@ dvr_autorec_init(void)
{
TAILQ_INIT(&autorec_entries);
autorec_dt = dtable_create(&autorec_dtc, "autorec", NULL);
dvr_autorec_in_init = 1;
dtable_load(autorec_dt);
dvr_autorec_in_init = 0;
}
void
dvr_autorec_update(void)
{
dvr_autorec_entry_t *dae;
TAILQ_FOREACH(dae, &autorec_entries, dae_link) {
dvr_autorec_changed(dae, 0);
}
}
static void
@ -520,7 +542,7 @@ _dvr_autorec_add(const char *config_name,
htsmsg_add_u32(m, "reload", 1);
notify_by_msg("autorec", m);
dvr_autorec_changed(dae);
dvr_autorec_changed(dae, 1);
}
void
@ -559,14 +581,10 @@ void
dvr_autorec_check_event(epg_broadcast_t *e)
{
dvr_autorec_entry_t *dae;
dvr_entry_t *existingde;
TAILQ_FOREACH(dae, &autorec_entries, dae_link)
if(autorec_cmp(dae, e)) {
existingde = dvr_entry_find_by_event_fuzzy(e);
if (existingde == NULL)
dvr_entry_create_by_autorec(e, dae);
}
if(autorec_cmp(dae, e))
dvr_entry_create_by_autorec(e, dae);
// Note: no longer updating event here as it will be done from EPG
// anyway
}
@ -593,12 +611,13 @@ void dvr_autorec_check_serieslink(epg_serieslink_t *s)
*
*/
static void
dvr_autorec_changed(dvr_autorec_entry_t *dae)
dvr_autorec_changed(dvr_autorec_entry_t *dae, int purge)
{
channel_t *ch;
epg_broadcast_t *e;
dvr_autorec_purge_spawns(dae);
if (purge)
dvr_autorec_purge_spawns(dae);
RB_FOREACH(ch, &channel_name_tree, ch_name_link) {
RB_FOREACH(e, &ch->ch_epg_schedule, sched_link) {

View file

@ -37,8 +37,6 @@ int dvr_iov_max;
struct dvr_config_list dvrconfigs;
struct dvr_entry_list dvrentries;
static void dvr_entry_save(dvr_entry_t *de);
static void dvr_timer_expire(void *aux);
static void dvr_timer_start_recording(void *aux);
@ -258,19 +256,6 @@ static dvr_entry_t *_dvr_entry_create (
if(de->de_start == start && de->de_sched_state != DVR_COMPLETED)
return NULL;
/* Reject duplicate episodes (unless earlier) */
if (e && cfg->dvr_dup_detect_episode) {
de = dvr_entry_find_by_episode(e);
if (de) {
if (de->de_start > start) {
dvr_event_replaced(de->de_bcast, e);
return de;
} else {
return NULL;
}
}
}
de = calloc(1, sizeof(dvr_entry_t));
de->de_id = ++de_tally;
@ -586,7 +571,7 @@ dvr_db_load(void)
/**
*
*/
static void
void
dvr_entry_save(dvr_entry_t *de)
{
htsmsg_t *m = htsmsg_create_map();
@ -1050,6 +1035,7 @@ dvr_init(void)
dvr_db_load();
dvr_autorec_init();
dvr_autorec_update();
}
/**

View file

@ -205,6 +205,11 @@ pvr_generate_filename(dvr_entry_t *de, const streaming_start_t *ss)
snprintf(path, sizeof(path), "%s", cfg->dvr_storage);
/* Remove trailing slash */
if (path[strlen(path)-1] == '/')
path[strlen(path)-1] = '\0';
/* Append per-day directory */
if(cfg->dvr_flags & DVR_DIR_PER_DAY) {
@ -345,7 +350,7 @@ dvr_rec_start(dvr_entry_t *de, const streaming_start_t *ss)
return;
}
if(cfg->dvr_flags & DVR_TAG_FILES) {
if(cfg->dvr_flags & DVR_TAG_FILES && de->de_bcast) {
if(muxer_write_meta(de->de_mux, de->de_bcast)) {
dvr_rec_fatal_error(de, "Unable to write meta data");
return;
@ -442,8 +447,8 @@ dvr_thread(void *aux)
if(dispatch_clock > de->de_start - (60 * de->de_start_extra)) {
dvr_rec_set_state(de, DVR_RS_RUNNING, 0);
if(!muxer_write_pkt(de->de_mux, sm->sm_data))
sm->sm_data = NULL;
muxer_write_pkt(de->de_mux, sm->sm_data);
sm->sm_data = NULL;
}
break;
@ -528,6 +533,10 @@ dvr_thread(void *aux)
pthread_mutex_lock(&sq->sq_mutex);
}
pthread_mutex_unlock(&sq->sq_mutex);
if(de->de_mux)
dvr_thread_epilog(de);
return NULL;
}

View file

@ -801,6 +801,9 @@ mk_write_cues(mk_mux_t *mkm)
mk_mux_t *mk_mux_create(void)
{
mk_mux_t *mkm = calloc(1, sizeof(struct mk_mux));
mkm->fd = -1;
return mkm;
}
@ -899,8 +902,7 @@ mk_mux_write_pkt(mk_mux_t *mkm, struct th_pkt *pkt)
mk_write_frame_i(mkm, t, pkt);
}
if(!mkm->error)
pkt_ref_dec(pkt);
pkt_ref_dec(pkt);
return mkm->error;
}

View file

@ -746,13 +746,13 @@ static htsmsg_t *epg_episode_num_serialize ( epg_episode_num_t *num )
if (num->e_cnt)
htsmsg_add_u32(m, "e_cnt", num->e_cnt);
if (num->s_num)
htsmsg_add_u32(m, "s_num", num->e_num);
htsmsg_add_u32(m, "s_num", num->s_num);
if (num->s_cnt)
htsmsg_add_u32(m, "s_cnt", num->e_cnt);
htsmsg_add_u32(m, "s_cnt", num->s_cnt);
if (num->p_num)
htsmsg_add_u32(m, "p_num", num->e_num);
htsmsg_add_u32(m, "p_num", num->p_num);
if (num->p_cnt)
htsmsg_add_u32(m, "p_cnt", num->e_cnt);
htsmsg_add_u32(m, "p_cnt", num->p_cnt);
if (num->text)
htsmsg_add_str(m, "text", num->text);
return m;
@ -990,6 +990,7 @@ int epg_episode_set_genre
g2 = LIST_NEXT(g1, link);
if (!epg_genre_list_contains(genre, g1, 0)) {
LIST_REMOVE(g1, link);
free(g1);
save = 1;
}
g1 = g2;
@ -1354,6 +1355,8 @@ static void _epg_channel_rem_broadcast
{
if (new) dvr_event_replaced(ebc, new);
RB_REMOVE(&ch->ch_epg_schedule, ebc, sched_link);
if (ch->ch_epg_now == ebc) ch->ch_epg_now = NULL;
if (ch->ch_epg_next == ebc) ch->ch_epg_next = NULL;
_epg_object_putref(ebc);
}
@ -1468,7 +1471,6 @@ static epg_broadcast_t *_epg_channel_add_broadcast
/* Remove overlapping (before) */
while ( (ebc = RB_PREV(ret, sched_link)) != NULL ) {
if ( ebc->stop <= ret->start ) break;
if ( ch->ch_epg_now == ebc ) ch->ch_epg_now = NULL;
_epg_channel_rem_broadcast(ch, ebc, ret);
}
@ -1838,10 +1840,15 @@ epg_broadcast_t *epg_broadcast_deserialize
if (!htsmsg_get_u32(m, "is_repeat", &u32))
*save |= epg_broadcast_set_is_repeat(ebc, u32, NULL);
if ((ls = lang_str_deserialize(m, "summary")))
if ((ls = lang_str_deserialize(m, "summary"))) {
*save |= epg_broadcast_set_summary2(ebc, ls, NULL);
if ((ls = lang_str_deserialize(m, "description")))
lang_str_destroy(ls);
}
if ((ls = lang_str_deserialize(m, "description"))) {
*save |= epg_broadcast_set_description2(ebc, ls, NULL);
lang_str_destroy(ls);
}
/* Series link */
if ((str = htsmsg_get_str(m, "serieslink")))

View file

@ -287,7 +287,7 @@ char *epggrab_module_grab_spawn ( void *m )
/* Grab */
outlen = spawn_and_store_stdout(mod->path, NULL, &outbuf);
if ( outlen < 1 ) {
tvhlog(LOG_ERR, "pyepg", "no output detected");
tvhlog(LOG_ERR, mod->id, "no output detected");
return NULL;
}
@ -300,13 +300,14 @@ htsmsg_t *epggrab_module_trans_xml ( void *m, char *c )
{
htsmsg_t *ret;
char errbuf[100];
epggrab_module_t *mod = m;
if (!c) return NULL;
/* Extract */
ret = htsmsg_xml_deserialize(c, errbuf, sizeof(errbuf));
if (!ret)
tvhlog(LOG_ERR, "pyepg", "htsmsg_xml_deserialize error %s", errbuf);
tvhlog(LOG_ERR, mod->id, "htsmsg_xml_deserialize error %s", errbuf);
return ret;
}

View file

@ -26,6 +26,7 @@
#include "epg.h"
#include "epggrab.h"
#include "epggrab/private.h"
#include "dvb/dvb_charset.h"
/* ************************************************************************
* Status handling
@ -149,7 +150,7 @@ typedef struct eit_event
lang_str_t *summary;
lang_str_t *desc;
char *default_charset;
const char *default_charset;
htsmsg_t *extra;
@ -200,7 +201,7 @@ static dvb_string_conv_t _eit_freesat_conv[2] = {
static int _eit_get_string_with_len
( epggrab_module_t *m,
char *dst, size_t dstlen,
const uint8_t *src, size_t srclen, char *charset )
const uint8_t *src, size_t srclen, const char *charset )
{
dvb_string_conv_t *cptr = NULL;
@ -534,7 +535,15 @@ static int _eit_process_event
/* Process tags */
memset(&ev, 0, sizeof(ev));
ev.default_charset = svc->s_dvb_default_charset;
ev.default_charset = svc->s_dvb_charset;
/* Override */
if (!ev.default_charset) {
ev.default_charset
= dvb_charset_find(svc->s_dvb_mux_instance->tdmi_transport_stream_id,
svc->s_dvb_service_id);
}
while (dllen > 2) {
int r;
dtag = ptr[0];

View file

@ -233,6 +233,8 @@ static char *_opentv_parse_string
int ok = 0;
char *ret, *tmp;
if (len <= 0) return NULL;
// Note: unlikely decoded string will be longer (though its possible)
ret = tmp = malloc(2*len);
*ret = 0;
@ -264,15 +266,17 @@ static int _opentv_parse_event_record
if (rlen+2 <= len) {
switch (rtag) {
case 0xb5: // title
ev->start = (((int)buf[2] << 9) | (buf[3] << 1))
+ mjd;
ev->stop = (((int)buf[4] << 9) | (buf[5] << 1))
+ ev->start;
ev->cat = buf[6];
if (prov->genre)
ev->cat = prov->genre->map[ev->cat];
if (!ev->title)
ev->title = _opentv_parse_string(prov, buf+9, rlen-7);
if (rlen >= 7) {
ev->start = (((int)buf[2] << 9) | (buf[3] << 1))
+ mjd;
ev->stop = (((int)buf[4] << 9) | (buf[5] << 1))
+ ev->start;
ev->cat = buf[6];
if (prov->genre)
ev->cat = prov->genre->map[ev->cat];
if (!ev->title)
ev->title = _opentv_parse_string(prov, buf+9, rlen-7);
}
break;
case 0xb9: // summary
if (!ev->summary)

View file

@ -59,28 +59,46 @@ static epggrab_channel_t *_xmltv_channel_find
/**
*
*/
static time_t _xmltv_str2time(const char *str)
static time_t _xmltv_str2time(const char *in)
{
struct tm tm;
int tz, r;
int tz = 0, r;
int sp = 0;
char str[32];
memset(&tm, 0, sizeof(tm));
strcpy(str, in);
r = sscanf(str, "%04d%02d%02d%02d%02d%02d %d",
/* split tz */
while (str[sp] && str[sp] != ' ')
sp++;
/* parse tz */
// TODO: handle string TZ?
if (str[sp]) {
sscanf(str+sp+1, "%d", &tz);
tz = (tz % 100) + (tz / 100) * 3600; // Convert from HHMM to seconds
str[sp] = 0;
sp = 1;
} else {
sp = 0;
}
/* parse time */
r = sscanf(str, "%04d%02d%02d%02d%02d%02d",
&tm.tm_year, &tm.tm_mon, &tm.tm_mday,
&tm.tm_hour, &tm.tm_min, &tm.tm_sec,
&tz);
&tm.tm_hour, &tm.tm_min, &tm.tm_sec);
/* adjust */
tm.tm_mon -= 1;
tm.tm_year -= 1900;
tm.tm_isdst = -1;
tz = (tz % 100) + (tz / 100) * 60; // Convert from HHMM to minutes
if(r == 6) {
return mktime(&tm);
} else if(r == 7) {
return timegm(&tm) - tz * 60;
if (r >= 5) {
if(sp)
return timegm(&tm) - tz;
else
return mktime(&tm);
} else {
return 0;
}
@ -190,7 +208,10 @@ static void parse_xmltv_dd_progid
snprintf(buf, sizeof(buf)-1, "ddprogid://%s/%s", mod->id, s);
/* SH - series without episode id so ignore */
if (strncmp("SH", s, 2)) *uri = strdup(buf);
if (strncmp("SH", s, 2))
*uri = strdup(buf);
else
*suri = strdup(buf);
/* Episode */
if (!strncmp("EP", s, 2)) {
@ -613,7 +634,7 @@ static void _xmltv_load_grabbers ( void )
size_t i, p, n;
char *outbuf;
char name[1000];
char *tmp, *path;
char *tmp, *tmp2 = NULL, *path;
/* Load data */
outlen = spawn_and_store_stdout(XMLTV_FIND, NULL, &outbuf);
@ -647,7 +668,7 @@ static void _xmltv_load_grabbers ( void )
NULL
};
path = strdup(tmp);
tmp = strtok(path, ":");
tmp = strtok_r(path, ":", &tmp2);
while (tmp) {
DIR *dir;
struct dirent *de;
@ -656,7 +677,8 @@ static void _xmltv_load_grabbers ( void )
while ((de = readdir(dir))) {
if (strstr(de->d_name, XMLTV_GRAB) != de->d_name) continue;
snprintf(bin, sizeof(bin), "%s/%s", tmp, de->d_name);
if (lstat(bin, &st)) continue;
if (epggrab_module_find_by_id(bin)) continue;
if (stat(bin, &st)) continue;
if (!(st.st_mode & S_IEXEC)) continue;
if (!S_ISREG(st.st_mode)) continue;
if ((outlen = spawn_and_store_stdout(bin, argv, &outbuf)) > 0) {
@ -667,9 +689,9 @@ static void _xmltv_load_grabbers ( void )
free(outbuf);
}
}
closedir(dir);
}
closedir(dir);
tmp = strtok(NULL, ":");
tmp = strtok_r(NULL, ":", &tmp2);
}
free(path);
}

View file

@ -136,6 +136,7 @@ void epggrab_ota_load ( void )
if ((l = htsmsg_get_list_by_field(f)))
_epggrab_ota_load_one((epggrab_module_ota_t*)mod, l);
}
htsmsg_destroy(m);
}
}
@ -171,6 +172,7 @@ void epggrab_ota_save ( void )
}
hts_settings_save(m, "epggrab/otamux");
htsmsg_destroy(m);
}
/* **************************************************************************

View file

@ -214,12 +214,13 @@ fb_dir *fb_opendir ( const char *path )
/* Bundle */
#if ENABLE_BUNDLE
char *tmp1 = strdup(path);
char *tmp2 = strtok(tmp1, "/");
char *tmp1, *tmp2, *tmp3 = NULL;
tmp1 = strdup(path);
tmp2 = strtok_r(tmp1, "/", &tmp3);
filebundle_entry_t *fb = filebundle_root;
while (fb && tmp2) {
if (fb->type == FB_DIR && !strcmp(fb->name, tmp2)) {
tmp2 = strtok(NULL, "/");
tmp2 = strtok_r(NULL, "/", &tmp3);
if (tmp2) fb = fb->d.child;
} else {
fb = fb->next;

View file

@ -467,7 +467,8 @@ htsp_build_dvrentry(dvr_entry_t *de, const char *method)
*/
static htsmsg_t *
htsp_build_event
(epg_broadcast_t *e, const char *method, const char *lang, time_t update )
(epg_broadcast_t *e, const char *method, const char *lang, time_t update,
htsp_connection_t *htsp )
{
htsmsg_t *out;
epg_broadcast_t *n;
@ -501,11 +502,11 @@ htsp_build_event
htsmsg_add_s64(out, "stop", e->stop);
if ((str = epg_broadcast_get_title(e, lang)))
htsmsg_add_str(out, "title", str);
if ((str = epg_broadcast_get_description(e, lang)))
if ((str = epg_broadcast_get_description(e, lang))) {
htsmsg_add_str(out, "description", str);
if ((str = epg_broadcast_get_description(e, lang)))
if ((str = epg_broadcast_get_summary(e, lang)))
htsmsg_add_str(out, "summary", str);
else if((str = epg_broadcast_get_summary(e, lang)))
} else if((str = epg_broadcast_get_summary(e, lang)))
htsmsg_add_str(out, "description", str);
if (e->serieslink)
htsmsg_add_u32(out, "serieslinkId", e->serieslink->id);
@ -516,8 +517,11 @@ htsp_build_event
htsmsg_add_u32(out, "brandId", ee->brand->id);
if (ee->season)
htsmsg_add_u32(out, "seasonId", ee->season->id);
if((g = LIST_FIRST(&ee->genre)))
htsmsg_add_u32(out, "contentType", g->code);
if((g = LIST_FIRST(&ee->genre))) {
uint32_t code = g->code;
if (htsp->htsp_version < 6) code = (code >> 4) & 0xF;
htsmsg_add_u32(out, "contentType", code);
}
if (ee->age_rating)
htsmsg_add_u32(out, "ageRating", ee->age_rating);
if (ee->star_rating)
@ -650,35 +654,6 @@ htsp_method_getSysTime(htsp_connection_t *htsp, htsmsg_t *in)
return out;
}
/**
* Request a ticket for a http url pointing to a channel or dvr
*/
static htsmsg_t *
htsp_method_getTicket(htsp_connection_t *htsp, htsmsg_t *in)
{
htsmsg_t *out;
uint32_t id;
char path[255];
const char *ticket = NULL;
if(!htsmsg_get_u32(in, "channelId", &id)) {
snprintf(path, sizeof(path), "/stream/channelid/%d", id);
ticket = access_ticket_create(path);
} else if(!htsmsg_get_u32(in, "dvrId", &id)) {
snprintf(path, sizeof(path), "/dvrfile/%d", id);
ticket = access_ticket_create(path);
} else {
return htsp_error("Missing argument 'channelId' or 'dvrId'");
}
out = htsmsg_create_map();
htsmsg_add_str(out, "path", path);
htsmsg_add_str(out, "ticket", ticket);
return out;
}
/**
* Switch the HTSP connection into async mode
*/
@ -735,7 +710,7 @@ htsp_method_async(htsp_connection_t *htsp, htsmsg_t *in)
RB_FOREACH(ch, &channel_name_tree, ch_name_link)
RB_FOREACH(ebc, &ch->ch_epg_schedule, sched_link) {
if (epgMaxTime && ebc->start > epgMaxTime) break;
htsmsg_t *e = htsp_build_event(ebc, "eventAdd", lang, lastUpdate);
htsmsg_t *e = htsp_build_event(ebc, "eventAdd", lang, lastUpdate, htsp);
if (e) htsp_send_message(htsp, e, NULL);
}
}
@ -768,7 +743,7 @@ htsp_method_getEvent(htsp_connection_t *htsp, htsmsg_t *in)
if((e = epg_broadcast_find_by_id(eventId, NULL)) == NULL)
return htsp_error("Event does not exist");
return htsp_build_event(e, NULL, lang, 0);
return htsp_build_event(e, NULL, lang, 0, htsp);
}
/**
@ -807,7 +782,7 @@ htsp_method_getEvents(htsp_connection_t *htsp, htsmsg_t *in)
events = htsmsg_create_list();
while (e) {
if (maxTime && e->start > maxTime) break;
htsmsg_add_msg(events, NULL, htsp_build_event(e, NULL, lang, 0));
htsmsg_add_msg(events, NULL, htsp_build_event(e, NULL, lang, 0, htsp));
if (numFollowing == 1) break;
if (numFollowing) numFollowing--;
e = epg_broadcast_get_next(e);
@ -820,7 +795,7 @@ htsp_method_getEvents(htsp_connection_t *htsp, htsmsg_t *in)
int num = numFollowing;
RB_FOREACH(e, &ch->ch_epg_schedule, sched_link) {
if (maxTime && e->start > maxTime) break;
htsmsg_add_msg(events, NULL, htsp_build_event(e, NULL, lang, 0));
htsmsg_add_msg(events, NULL, htsp_build_event(e, NULL, lang, 0, htsp));
if (num == 1) break;
if (num) num--;
}
@ -862,6 +837,7 @@ htsp_method_epgQuery(htsp_connection_t *htsp, htsmsg_t *in)
if (!(ct = channel_tag_find_by_identifier(u32)))
return htsp_error("Channel tag does not exist");
if (!htsmsg_get_u32(in, "contentType", &u32)) {
if(htsp->htsp_version < 6) u32 <<= 4;
genre.code = u32;
eg = &genre;
}
@ -878,7 +854,7 @@ htsp_method_epgQuery(htsp_connection_t *htsp, htsmsg_t *in)
for(i = 0; i < eqr.eqr_entries; ++i) {
if (full)
htsmsg_add_msg(array, NULL,
htsp_build_event(eqr.eqr_array[i], NULL, lang, 0));
htsp_build_event(eqr.eqr_array[i], NULL, lang, 0, htsp));
else
htsmsg_add_u32(array, NULL, eqr.eqr_array[i]->id);
}
@ -1088,6 +1064,35 @@ htsp_method_deleteDvrEntry(htsp_connection_t *htsp, htsmsg_t *in)
return out;
}
/**
* Request a ticket for a http url pointing to a channel or dvr
*/
static htsmsg_t *
htsp_method_getTicket(htsp_connection_t *htsp, htsmsg_t *in)
{
htsmsg_t *out;
uint32_t id;
char path[255];
const char *ticket = NULL;
if(!htsmsg_get_u32(in, "channelId", &id)) {
snprintf(path, sizeof(path), "/stream/channelid/%d", id);
ticket = access_ticket_create(path);
} else if(!htsmsg_get_u32(in, "dvrId", &id)) {
snprintf(path, sizeof(path), "/dvrfile/%d", id);
ticket = access_ticket_create(path);
} else {
return htsp_error("Missing argument 'channelId' or 'dvrId'");
}
out = htsmsg_create_map();
htsmsg_add_str(out, "path", path);
htsmsg_add_str(out, "ticket", ticket);
return out;
}
/**
* Request subscription for a channel
*/
@ -1200,7 +1205,6 @@ struct {
{ "authenticate", htsp_method_authenticate, ACCESS_ANONYMOUS},
{ "getDiskSpace", htsp_method_getDiskSpace, ACCESS_STREAMING},
{ "getSysTime", htsp_method_getSysTime, ACCESS_STREAMING},
{ "getTicket", htsp_method_getTicket, ACCESS_STREAMING},
{ "enableAsyncMetadata", htsp_method_async, ACCESS_STREAMING},
{ "getEvent", htsp_method_getEvent, ACCESS_STREAMING},
{ "getEvents", htsp_method_getEvents, ACCESS_STREAMING},
@ -1210,6 +1214,7 @@ struct {
{ "updateDvrEntry", htsp_method_updateDvrEntry, ACCESS_RECORDER},
{ "cancelDvrEntry", htsp_method_cancelDvrEntry, ACCESS_RECORDER},
{ "deleteDvrEntry", htsp_method_deleteDvrEntry, ACCESS_RECORDER},
{ "getTicket", htsp_method_getTicket, ACCESS_STREAMING},
{ "subscribe", htsp_method_subscribe, ACCESS_STREAMING},
{ "unsubscribe", htsp_method_unsubscribe, ACCESS_STREAMING},
{ "subscriptionChangeWeight", htsp_method_change_weight, ACCESS_STREAMING},
@ -1422,24 +1427,30 @@ htsp_write_scheduler(void *aux)
r = htsmsg_binary_serialize(hm->hm_msg, &dptr, &dlen, INT32_MAX);
#if 0
if(hm->hm_pktref) {
usleep(hm->hm_payloadsize * 3);
}
#endif
htsp_msg_destroy(hm);
/* ignore return value */
r = write(htsp->htsp_fd, dptr, dlen);
if(r != dlen)
tvhlog(LOG_INFO, "htsp", "%s: Write error -- %s",
htsp->htsp_logname, strerror(errno));
free(dptr);
void *freeme = dptr;
while(dlen > 0) {
r = write(htsp->htsp_fd, dptr, dlen);
if(r < 1) {
tvhlog(LOG_INFO, "htsp", "%s: Write error -- %s",
htsp->htsp_logname, strerror(errno));
break;
}
dptr += r;
dlen -= r;
}
free(freeme);
pthread_mutex_lock(&htsp->htsp_out_mutex);
if(r != dlen)
if(dlen)
break;
}
// Shutdown socket to make receive thread terminate entire HTSP connection
shutdown(htsp->htsp_fd, SHUT_RDWR);
pthread_mutex_unlock(&htsp->htsp_out_mutex);
return NULL;
}
@ -1500,17 +1511,28 @@ htsp_serve(int fd, void *opaque, struct sockaddr_in *source,
pthread_mutex_unlock(&global_lock);
free(htsp.htsp_logname);
free(htsp.htsp_peername);
free(htsp.htsp_username);
free(htsp.htsp_clientname);
pthread_mutex_lock(&htsp.htsp_out_mutex);
htsp.htsp_writer_run = 0;
pthread_cond_signal(&htsp.htsp_out_cond);
pthread_mutex_unlock(&htsp.htsp_out_mutex);
pthread_join(htsp.htsp_writer_thread, NULL);
free(htsp.htsp_logname);
free(htsp.htsp_peername);
free(htsp.htsp_username);
free(htsp.htsp_clientname);
htsp_msg_q_t *hmq;
TAILQ_FOREACH(hmq, &htsp.htsp_active_output_queues, hmq_link) {
htsp_msg_t *hm;
while((hm = TAILQ_FIRST(&hmq->hmq_q)) != NULL) {
TAILQ_REMOVE(&hmq->hmq_q, hm, hm_link);
htsp_msg_destroy(hm);
}
}
close(fd);
}
@ -1673,7 +1695,7 @@ htsp_event_add(epg_broadcast_t *ebc)
htsmsg_t *m;
LIST_FOREACH(htsp, &htsp_async_connections, htsp_async_link) {
if (!(htsp->htsp_async_mode & HTSP_ASYNC_EPG)) continue;
m = htsp_build_event(ebc, "eventAdd", htsp->htsp_language, 0);
m = htsp_build_event(ebc, "eventAdd", htsp->htsp_language, 0, htsp);
htsp_send_message(htsp, m, NULL);
}
}
@ -1688,7 +1710,7 @@ htsp_event_update(epg_broadcast_t *ebc)
htsmsg_t *m;
LIST_FOREACH(htsp, &htsp_async_connections, htsp_async_link) {
if (!(htsp->htsp_async_mode & HTSP_ASYNC_EPG)) continue;
m = htsp_build_event(ebc, "eventUpdate", htsp->htsp_language, 0);
m = htsp_build_event(ebc, "eventUpdate", htsp->htsp_language, 0, htsp);
htsp_send_message(htsp, m, NULL);
}
}
@ -1700,7 +1722,7 @@ void
htsp_event_delete(epg_broadcast_t *ebc)
{
htsmsg_t *m = htsmsg_create_map();
htsmsg_add_str(m, "method", "eventDeleted");
htsmsg_add_str(m, "method", "eventDelete");
htsmsg_add_u32(m, "eventId", ebc->id);
htsp_async_send(m, HTSP_ASYNC_EPG);
}

View file

@ -268,9 +268,11 @@ main(int argc, char **argv)
int crash = 0;
webui_port = 9981;
htsp_port = 9982;
gid_t gid;
uid_t uid;
/* Get current directory */
tvheadend_cwd = dirname(dirname(strdup(argv[0])));
tvheadend_cwd = dirname(dirname(tvh_strdupa(argv[0])));
/* Set locale */
setlocale(LC_ALL, "");
@ -346,34 +348,52 @@ main(int argc, char **argv)
signal(SIGPIPE, handle_sigpipe);
log_stderr = 1;
log_decorate = isatty(2);
if(forkaway) {
grp = getgrnam(groupnam ?: "video");
pw = usernam ? getpwnam(usernam) : NULL;
if(daemon(0, 0)) {
exit(2);
}
pidfile = fopen(pidpath, "w+");
if(pidfile != NULL) {
fprintf(pidfile, "%d\n", getpid());
fclose(pidfile);
}
if(grp != NULL) {
setgid(grp->gr_gid);
gid = grp->gr_gid;
} else {
setgid(1);
gid = 1;
}
if (pw != NULL) {
gid_t glist[10];
int gnum = get_user_groups(pw, glist, 10);
setgroups(gnum, glist);
setuid(pw->pw_uid);
if (getuid() != pw->pw_uid) {
gid_t glist[10];
int gnum;
gnum = get_user_groups(pw, glist, 10);
if (setgroups(gnum, glist)) {
tvhlog(LOG_ALERT, "START", "setgroups() failed, do you have permission?");
return 1;
}
}
uid = pw->pw_uid;
homedir = pw->pw_dir;
setenv("HOME", homedir, 1);
} else {
setuid(1);
uid = 1;
}
if ((getgid() != gid) && setgid(gid)) {
tvhlog(LOG_ALERT, "START", "setgid() failed, do you have permission?");
return 1;
}
if ((getuid() != uid) && setuid(uid)) {
tvhlog(LOG_ALERT, "START", "setuid() failed, do you have permission?");
return 1;
}
if(daemon(0, 0)) {
exit(2);
}
if(pidfile != NULL) {
fprintf(pidfile, "%d\n", getpid());
fclose(pidfile);
}
umask(0);

View file

@ -295,12 +295,12 @@ muxer_write_meta(muxer_t *m, struct epg_broadcast *eb)
* sanity wrapper arround m_write_pkt()
*/
int
muxer_write_pkt(muxer_t *m, struct th_pkt *pkt)
muxer_write_pkt(muxer_t *m, void *data)
{
if(!m || !pkt)
if(!m || !data)
return -1;
return m->m_write_pkt(m, pkt);
return m->m_write_pkt(m, data);
}

View file

@ -45,7 +45,7 @@ typedef struct muxer {
int (*m_close) (struct muxer *); // Close the muxer
void (*m_destroy) (struct muxer *); // Free the memory
int (*m_write_meta) (struct muxer *, struct epg_broadcast *); // Append epg data
int (*m_write_pkt) (struct muxer *, struct th_pkt *); // Append a media packet
int (*m_write_pkt) (struct muxer *, void *); // Append a media packet
int m_errors; // Number of errors
muxer_container_type_t m_container; // The type of the container
@ -68,7 +68,7 @@ int muxer_init (muxer_t *m, const struct streaming_start *ss, con
int muxer_close (muxer_t *m);
int muxer_destroy (muxer_t *m);
int muxer_write_meta (muxer_t *m, struct epg_broadcast *eb);
int muxer_write_pkt (muxer_t *m, struct th_pkt *pkt);
int muxer_write_pkt (muxer_t *m, void *data);
const char* muxer_mime (muxer_t *m, const struct streaming_start *ss);
const char* muxer_suffix (muxer_t *m, const struct streaming_start *ss);

View file

@ -26,7 +26,6 @@
#include "psi.h"
#include "muxer_pass.h"
#define TS_BUFFER_COUNT 100
#define TS_INJECTION_RATE 1000
/*
@ -49,7 +48,6 @@ typedef struct pass_muxer {
char *pm_filename;
/* TS muxing */
uint8_t *pm_buf;
uint8_t *pm_pat;
uint8_t *pm_pmt;
uint16_t pm_pmt_pid;
@ -194,7 +192,7 @@ pass_muxer_write(muxer_t *m, const void *ts, size_t len)
* Write TS packets to the file descriptor
*/
static void
pass_muxer_write_ts(muxer_t *m, struct th_pkt *pkt)
pass_muxer_write_ts(muxer_t *m, pktbuf_t *pb)
{
pass_muxer_t *pm = (pass_muxer_t*)m;
int rem;
@ -209,13 +207,9 @@ pass_muxer_write_ts(muxer_t *m, struct th_pkt *pkt)
pm->pm_ic++;
}
// flush buffer
rem = pm->pm_pc % TS_BUFFER_COUNT;
if(pm->pm_pc && !rem)
pass_muxer_write(m, pm->pm_buf, TS_BUFFER_COUNT * 188);
pass_muxer_write(m, pb->pb_data, pb->pb_size);
memcpy(pm->pm_buf + rem * 188, pkt, 188);
pm->pm_pc++;
pm->pm_pc += (pb->pb_size / 188);
}
@ -223,21 +217,21 @@ pass_muxer_write_ts(muxer_t *m, struct th_pkt *pkt)
* Write a packet directly to the file descriptor
*/
static int
pass_muxer_write_pkt(muxer_t *m, struct th_pkt *pkt)
pass_muxer_write_pkt(muxer_t *m, void *data)
{
pktbuf_t *pb = (pktbuf_t*)data;
pass_muxer_t *pm = (pass_muxer_t*)m;
switch(pm->m_container) {
case MC_MPEGTS:
pass_muxer_write_ts(m, pkt);
pass_muxer_write_ts(m, pb);
break;
default:
//NOP
break;
}
if(!pm->pm_error)
free(pkt);
pktbuf_ref_dec(pb);
return pm->pm_error;
}
@ -290,9 +284,6 @@ pass_muxer_destroy(muxer_t *m)
if(pm->pm_pat)
free(pm->pm_pat);
if(pm->pm_buf)
free(pm->pm_buf);
free(pm);
}
@ -325,9 +316,10 @@ pass_muxer_create(service_t *s, muxer_container_type_t mc)
pm->pm_pmt_pid = s->s_pmt_pid;
pm->pm_pat = malloc(188);
pm->pm_pmt = malloc(188);
pm->pm_buf = malloc(188 * TS_BUFFER_COUNT);
}
pm->pm_fd = -1;
return (muxer_t *)pm;
}

View file

@ -117,8 +117,9 @@ tvh_muxer_open_file(muxer_t *m, const char *filename)
* Write a packet to the muxer
*/
static int
tvh_muxer_write_pkt(muxer_t *m, struct th_pkt *pkt)
tvh_muxer_write_pkt(muxer_t *m, void *data)
{
th_pkt_t *pkt = (th_pkt_t*)data;
tvh_muxer_t *tm = (tvh_muxer_t*)m;
if(mk_mux_write_pkt(tm->tm_ref, pkt)) {

View file

@ -289,7 +289,10 @@ static void _muxes_load_file
str++;
}
}
if (!reg) return;
if (!reg) {
fb_close(fp);
return;
}
/* Network */
str = buf;
@ -338,19 +341,22 @@ static void _muxes_load_file
*
* Note: should we follow symlinks?
*/
static void _muxes_load_dir ( const char *path, const char *type )
static void _muxes_load_dir
( const char *path, const char *type, int lvl )
{
char p[256];
fb_dir *dir;
fb_dirent *de;
if (lvl >= 3) return;
if (!(dir = fb_opendir(path))) return;
lvl++;
while ((de = fb_readdir(dir))) {
if (*de->name == '.') continue;
if (de->type == FB_DIR) {
snprintf(p, sizeof(p), "%s/%s", path, de->name);
_muxes_load_dir(p, de->name);
_muxes_load_dir(p, de->name, lvl+1);
} else if (type) {
_muxes_load_file(type, dir, de->name);
}
@ -371,5 +377,5 @@ void muxes_init ( void )
#else
path = "/usr/share/dvb";
#endif
_muxes_load_dir(path, NULL);
_muxes_load_dir(path, NULL, 0);
}

View file

@ -355,7 +355,7 @@ h264_decode_slice_header(elementary_stream_t *st, bitstream_t *bs, int *pkttype,
int *duration, int *isfield)
{
h264_private_t *p;
int slice_type, pps_id, sps_id;
unsigned int slice_type, pps_id, sps_id;
if((p = st->es_priv) == NULL)
return -1;

View file

@ -110,18 +110,21 @@ stream_clean(elementary_stream_t *st)
st->es_global_data_len = 0;
}
/**
*
*/
void
service_stream_destroy(service_t *t, elementary_stream_t *st)
service_stream_destroy(service_t *t, elementary_stream_t *es)
{
if(t->s_status == SERVICE_RUNNING)
stream_clean(st);
TAILQ_REMOVE(&t->s_components, st, es_link);
free(st->es_nicename);
free(st);
stream_clean(es);
avgstat_flush(&es->es_rate);
avgstat_flush(&es->es_cc_errors);
TAILQ_REMOVE(&t->s_components, es, es_link);
free(es->es_nicename);
free(es);
}
/**
@ -364,6 +367,8 @@ service_find(channel_t *ch, unsigned int weight, const char *loginfo,
/* First, try all services without stealing */
for(i = off; i < cnt; i++) {
t = vec[i];
if(t->s_status == SERVICE_RUNNING)
return t;
if(t->s_quality_index(t) < 10) {
if(loginfo != NULL) {
tvhlog(LOG_NOTICE, "Service",
@ -375,9 +380,6 @@ service_find(channel_t *ch, unsigned int weight, const char *loginfo,
}
tvhlog(LOG_DEBUG, "Service", "%s: Probing adapter \"%s\" without stealing for service \"%s\"",
loginfo, service_adapter_nicename(t), service_nicename(t));
if(t->s_status == SERVICE_RUNNING)
return t;
if((r = service_start(t, 0, 0)) == 0)
return t;
if(loginfo != NULL)
@ -486,17 +488,19 @@ service_destroy(service_t *t)
free(t->s_identifier);
free(t->s_svcname);
free(t->s_provider);
free(t->s_dvb_default_charset);
free(t->s_dvb_charset);
while((st = TAILQ_FIRST(&t->s_components)) != NULL) {
TAILQ_REMOVE(&t->s_components, st, es_link);
free(st->es_nicename);
free(st);
}
while((st = TAILQ_FIRST(&t->s_components)) != NULL)
service_stream_destroy(t, st);
free(t->s_pat_section);
free(t->s_pmt_section);
sbuf_free(&t->s_tsbuf);
avgstat_flush(&t->s_cc_errors);
avgstat_flush(&t->s_rate);
service_unref(t);
if(ch != NULL) {
@ -525,10 +529,12 @@ service_create(const char *identifier, int type, int source_type)
t->s_refcount = 1;
t->s_enabled = 1;
t->s_pcr_last = PTS_UNSET;
t->s_dvb_default_charset = NULL;
t->s_dvb_charset = NULL;
t->s_dvb_eit_enable = 1;
TAILQ_INIT(&t->s_components);
sbuf_init(&t->s_tsbuf);
streaming_pad_init(&t->s_streaming_pad);
LIST_INSERT_HEAD(&servicehash[hash], t, s_hash_link);
@ -703,15 +709,15 @@ service_map_channel(service_t *t, channel_t *ch, int save)
*
*/
void
service_set_dvb_default_charset(service_t *t, const char *dvb_default_charset)
service_set_dvb_charset(service_t *t, const char *dvb_charset)
{
lock_assert(&global_lock);
if(t->s_dvb_default_charset != NULL && !strcmp(t->s_dvb_default_charset, dvb_default_charset))
if(t->s_dvb_charset != NULL && !strcmp(t->s_dvb_charset, dvb_charset))
return;
free(t->s_dvb_default_charset);
t->s_dvb_default_charset = strdup(dvb_default_charset);
free(t->s_dvb_charset);
t->s_dvb_charset = strdup(dvb_charset);
t->s_config_save(t);
}
@ -1164,7 +1170,7 @@ service_is_primary_epg(service_t *svc)
LIST_FOREACH(t, &svc->s_ch->ch_services, s_ch_link) {
if (!t->s_dvb_mux_instance) continue;
if (!t->s_enabled || !t->s_dvb_eit_enable) continue;
if (!ret || dvb_extra_prio(t->s_dvb_mux_instance->tdmi_adapter) > dvb_extra_prio(ret->s_dvb_mux_instance->tdmi_adapter))
if (!ret || service_get_prio(t) < service_get_prio(ret))
ret = t;
}
return !ret ? 0 : (ret->s_dvb_service_id == svc->s_dvb_service_id);

View file

@ -447,6 +447,13 @@ typedef struct service {
elementary_stream_t *s_video;
elementary_stream_t *s_audio;
/**
* When a subscription request SMT_MPEGTS, chunk them togeather
* in order to recude load.
*/
sbuf_t s_tsbuf;
/**
* Average continuity errors
*/
@ -492,7 +499,7 @@ typedef struct service {
* DVB default charset
* used to overide the default ISO6937 per service
*/
char *s_dvb_default_charset;
char *s_dvb_charset;
/**
* Set if EIT grab is enabled for DVB service (the default).
@ -584,7 +591,7 @@ int tss2errcode(int tss);
uint16_t service_get_encryption(service_t *t);
void service_set_dvb_default_charset(service_t *t, const char *dvb_default_charset);
void service_set_dvb_charset(service_t *t, const char *dvb_charset);
void service_set_dvb_eit_enable(service_t *t, int dvb_eit_enable);

View file

@ -200,11 +200,13 @@ hts_settings_load_one(const char *filename)
mem = malloc(fb_size(fp)+1);
n = fb_read(fp, mem, fb_size(fp));
if (n >= 0) mem[n] = 0;
fb_close(fp);
/* Decode */
if(n == fb_size(fp))
r = htsmsg_json_deserialize(mem);
/* Close */
fb_close(fp);
free(mem);
return r;
@ -290,12 +292,18 @@ hts_settings_remove(const char *pathfmt, ...)
{
char fullpath[256];
va_list ap;
struct stat st;
va_start(ap, pathfmt);
hts_settings_buildpath(fullpath, sizeof(fullpath),
pathfmt, ap, settingspath);
va_end(ap);
unlink(fullpath);
if (stat(fullpath, &st) == 0) {
if (S_ISDIR(st.st_mode))
rmdir(fullpath);
else
unlink(fullpath);
}
}
/**

View file

@ -53,13 +53,13 @@ find_exec ( const char *name, char *out, size_t len )
{
int ret = 0;
char bin[512];
char *path, *tmp;
char *path, *tmp, *tmp2 = NULL;
DIR *dir;
struct dirent *de;
struct stat st;
if (!(path = getenv("PATH"))) return 0;
path = strdup(path);
tmp = strtok(path, ":");
tmp = strtok_r(path, ":", &tmp2);
while (tmp && !ret) {
if ((dir = opendir(tmp))) {
while ((de = readdir(dir))) {
@ -73,7 +73,7 @@ find_exec ( const char *name, char *out, size_t len )
}
closedir(dir);
}
tmp = strtok(NULL, ":");
tmp = strtok_r(NULL, ":", &tmp2);
}
free(path);
return ret;

View file

@ -197,8 +197,8 @@ streaming_msg_clone(streaming_message_t *src)
break;
case SMT_MPEGTS:
dst->sm_data = malloc(188);
memcpy(dst->sm_data, src->sm_data, 188);
pktbuf_ref_inc(src->sm_data);
dst->sm_data = src->sm_data;
break;
default:
@ -256,10 +256,14 @@ streaming_msg_free(streaming_message_t *sm)
break;
case SMT_SIGNAL_STATUS:
case SMT_MPEGTS:
free(sm->sm_data);
break;
case SMT_MPEGTS:
if(sm->sm_data)
pktbuf_ref_dec(sm->sm_data);
break;
default:
abort();
}

View file

@ -75,9 +75,14 @@ subscription_link_service(th_subscription_t *s, service_t *t)
pthread_mutex_lock(&t->s_stream_mutex);
if(TAILQ_FIRST(&t->s_components) != NULL)
if(TAILQ_FIRST(&t->s_components) != NULL) {
if(s->ths_start_message != NULL)
streaming_msg_free(s->ths_start_message);
s->ths_start_message =
streaming_msg_create_data(SMT_START, service_build_stream_start(t));
}
// Link to service output
streaming_target_connect(&t->s_streaming_pad, &s->ths_input);

View file

@ -40,6 +40,8 @@
#include "parsers.h"
#include "streaming.h"
#define TS_REMUX_BUFSIZE (188 * 100)
static void ts_remux(service_t *t, const uint8_t *tsb);
/**
@ -281,15 +283,26 @@ ts_recv_packet2(service_t *t, const uint8_t *tsb)
static void
ts_remux(service_t *t, const uint8_t *src)
{
uint8_t tsb[188];
memcpy(tsb, src, 188);
streaming_message_t sm;
pktbuf_t *pb;
sbuf_t *sb = &t->s_tsbuf;
sbuf_append(sb, src, 188);
if(sb->sb_ptr < TS_REMUX_BUFSIZE)
return;
pb = pktbuf_alloc(sb->sb_data, sb->sb_ptr);
sm.sm_type = SMT_MPEGTS;
sm.sm_data = tsb;
sm.sm_data = pb;
streaming_pad_deliver(&t->s_streaming_pad, &sm);
pktbuf_ref_dec(pb);
service_set_streaming_status_flags(t, TSS_PACKETS);
sbuf_reset(sb);
}
/*

View file

@ -1,4 +0,0 @@
#include "buildversion.h"
#include "config.h"
const char *tvheadend_version = BUILD_VERSION;

View file

@ -190,8 +190,8 @@ page_about(http_connection_t *hc, const char *remain, void *opaque)
"</div><br>"
"&copy; 2006 - 2012 Andreas \303\226man, et al.<br><br>"
"<img src=\"docresources/tvheadendlogo.png\"><br>"
"<a href=\"http://www.lonelycoder.com/hts\">"
"http://www.lonelycoder.com/hts</a><br><br>"
"<a href=\"http://www.lonelycoder.com/tvheadend\">"
"http://www.lonelycoder.com/tvheadend</a><br><br>"
"Based on software from "
"<a target=\"_blank\" href=\"http://www.extjs.com/\">ExtJS</a>. "
"Icons from "
@ -199,6 +199,13 @@ page_about(http_connection_t *hc, const char *remain, void *opaque)
"FamFamFam</a>"
"<br><br>"
"Build: %s"
"<p>"
"If you'd like to support the project, please consider a donation."
"<br/>"
"All proceeds are used to support server infrastructure and buy test "
"equipment."
"<br/>"
"<a href='https://www.paypal.com/cgi-bin/webscr?cmd=_donations&#38;business=andreas%%40lonelycoder%%2ecom&#38;item_name=Donation%%20to%%20the%%20Tvheadend%%20project&#38;currency_code=USD'><img src='https://www.paypal.com/en_US/i/btn/btn_donate_LG.gif' alt='' /></a>"
"</center>",
tvheadend_version,
tvheadend_version);
@ -343,7 +350,7 @@ extjs_channels_update(htsmsg_t *in)
if((s = htsmsg_get_str(c, "epggrabsrc")) != NULL) {
char *tmp = strdup(s);
char *sptr = NULL;
char *sptr = NULL, *sptr2 = NULL;
char *modecid = strtok_r(tmp, ",", &sptr);
char *modid, *ecid;
epggrab_module_t *mod;
@ -368,8 +375,8 @@ extjs_channels_update(htsmsg_t *in)
/* Add new */
while (modecid) {
modid = strtok(modecid, "|");
ecid = strtok(NULL, "|");
modid = strtok_r(modecid, "|", &sptr2);
ecid = strtok_r(NULL, "|", &sptr2);
modecid = strtok_r(NULL, ",", &sptr);
if (!(mod = epggrab_module_find_by_id(modid)))
@ -610,6 +617,7 @@ extjs_epggrab(http_connection_t *hc, const char *remain, void *opaque)
if ( str ) save |= epggrab_enable_module_by_id(str, u32);
}
}
htsmsg_destroy(array);
}
}
if (save) epggrab_save();
@ -1408,7 +1416,7 @@ service_update(htsmsg_t *in)
uint32_t u32;
const char *id;
const char *chname;
const char *dvb_default_charset;
const char *dvb_charset;
TAILQ_FOREACH(f, &in->hm_fields, hmf_link) {
if((c = htsmsg_get_map_by_field(f)) == NULL ||
@ -1424,8 +1432,8 @@ service_update(htsmsg_t *in)
if((chname = htsmsg_get_str(c, "channelname")) != NULL)
service_map_channel(t, channel_find_by_name(chname, 1, 0), 1);
if((dvb_default_charset = htsmsg_get_str(c, "dvb_default_charset")) != NULL)
service_set_dvb_default_charset(t, dvb_default_charset);
if((dvb_charset = htsmsg_get_str(c, "dvb_charset")) != NULL)
service_set_dvb_charset(t, dvb_charset);
if(!htsmsg_get_u32(c, "dvb_eit_enable", &u32))
service_set_dvb_eit_enable(t, u32);
@ -1510,8 +1518,8 @@ extjs_servicedetails(http_connection_t *hc,
htsmsg_add_msg(out, "streams", streams);
if(t->s_dvb_default_charset != NULL)
htsmsg_add_str(out, "dvb_default_charset", t->s_dvb_default_charset);
if(t->s_dvb_charset != NULL)
htsmsg_add_str(out, "dvb_charset", t->s_dvb_charset);
htsmsg_add_u32(out, "dvb_eit_enable", t->s_dvb_eit_enable);
@ -1742,7 +1750,7 @@ extjs_service_update(htsmsg_t *in)
uint32_t u32;
const char *id;
const char *chname;
const char *dvb_default_charset;
const char *dvb_charset;
TAILQ_FOREACH(f, &in->hm_fields, hmf_link) {
if((c = htsmsg_get_map_by_field(f)) == NULL ||
@ -1758,8 +1766,8 @@ extjs_service_update(htsmsg_t *in)
if((chname = htsmsg_get_str(c, "channelname")) != NULL)
service_map_channel(t, channel_find_by_name(chname, 1, 0), 1);
if((dvb_default_charset = htsmsg_get_str(c, "dvb_default_charset")) != NULL)
service_set_dvb_default_charset(t, dvb_default_charset);
if((dvb_charset = htsmsg_get_str(c, "dvb_charset")) != NULL)
service_set_dvb_charset(t, dvb_charset);
if(!htsmsg_get_u32(c, "dvb_eit_enable", &u32))
service_set_dvb_eit_enable(t, u32);

View file

@ -424,23 +424,23 @@ page_status(http_connection_t *hc,
htsbuf_qprintf(hq,
"<recording>"
"<start>"
"<date>%02d/%02d/%02d</date>"
"<date>%d/%02d/%02d</date>"
"<time>%02d:%02d</time>"
"<unixtime>%"PRItime_t"</unixtime>"
"<extra_start>%"PRItime_t"</extra_start>"
"</start>"
"<stop>"
"<date>%02d/%02d/%02d</date>"
"<date>%d/%02d/%02d</date>"
"<time>%02d:%02d</time>"
"<unixtime>%"PRItime_t"</unixtime>"
"<extra_stop>%"PRItime_t"</extra_stop>"
"</stop>"
"<title>%s</title>",
a.tm_year + 1900, a.tm_mon, a.tm_mday,
a.tm_year + 1900, a.tm_mon + 1, a.tm_mday,
a.tm_hour, a.tm_min,
de->de_start,
de->de_start_extra,
b.tm_year+1900, b.tm_mon, b.tm_mday,
b.tm_year+1900, b.tm_mon + 1, b.tm_mday,
b.tm_hour, b.tm_min,
de->de_stop,
de->de_stop_extra,

View file

@ -314,7 +314,7 @@ tvheadend.chconf = function() {
tooltop : 'Add a new channel',
iconCls : 'add',
text : 'Add channel',
handler : addRecord,
handler : addRecord
});
var delBtn = new Ext.Toolbar.Button({

View file

@ -382,7 +382,7 @@ tvheadend.dvb_services = function(adapterId) {
});
var eitColumn = new Ext.grid.CheckColumn({
header : "EIT",
header : "EPG",
dataIndex : 'dvb_eit_enable',
width : 45
});
@ -444,18 +444,18 @@ tvheadend.dvb_services = function(adapterId) {
})
},
{
header : "DVB default charset",
dataIndex : 'dvb_default_charset',
header : "DVB charset",
dataIndex : 'dvb_charset',
width : 200,
renderer : function(value, metadata, record, row, col, store) {
return value ? value
: '<span class="tvh-grid-unset">ISO6937</span>';
: '<span class="tvh-grid-unset">auto</span>';
},
editor : new fm.ComboBox({
mode : 'local',
store : new Ext.data.SimpleStore({
fields : [ 'key', 'value' ],
data : [ [ 'ISO6937', 'default' ], [ 'ISO6937', 'ISO6937' ],
data : [ [ null, 'auto' ], [ 'ISO6937', 'ISO6937' ],
[ 'ISO8859-1', 'ISO8859-1' ], [ 'ISO8859-2', 'ISO8859-2' ],
[ 'ISO8859-3', 'ISO8859-3' ], [ 'ISO8859-4', 'ISO8859-4' ],
[ 'ISO8859-5', 'ISO8859-5' ], [ 'ISO8859-6', 'ISO8859-6' ],
@ -510,7 +510,7 @@ tvheadend.dvb_services = function(adapterId) {
root : 'entries',
fields : Ext.data.Record.create([ 'id', 'enabled', 'type', 'sid', 'pmt',
'pcr', 'svcname', 'network', 'provider', 'mux', 'channelname',
'dvb_default_charset', 'dvb_eit_enable' ]),
'dvb_charset', 'dvb_eit_enable' ]),
url : "dvb/services/" + adapterId,
autoLoad : true,
id : 'id',
@ -1114,6 +1114,10 @@ tvheadend.dvb_adapter_general = function(adapterData, satConfStore) {
fieldLabel : 'Skip service availability check when mapping',
name : 'skip_checksubscr'
}),
new Ext.form.Checkbox({
fieldLabel : 'Use SID as channel number during mapping',
name : 'sidtochan'
}),
new Ext.form.Checkbox({
fieldLabel : 'Monitor signal quality',
name : 'qmon'
@ -1132,7 +1136,7 @@ tvheadend.dvb_adapter_general = function(adapterData, satConfStore) {
+ 'of diskspace. You have been warned');
}
}), {
fieldLabel : 'NIT-o Network ID',
fieldLabel : 'Original Network ID',
name : 'nitoid',
width : 50
}, {
@ -1158,11 +1162,6 @@ tvheadend.dvb_adapter_general = function(adapterData, satConfStore) {
name : 'poweroff'
});
items.push(v);
v = new Ext.form.Checkbox({
fieldLabel : 'Use SID as channel number during mapping',
name : 'sidtochan'
}),
items.push(v);
}
var confform = new Ext.FormPanel({
@ -1229,6 +1228,8 @@ tvheadend.dvb_adapter_general = function(adapterData, satConfStore) {
var panel = new Ext.Panel({
title : 'General',
layout : 'column',
autoScroll : true,
autoHeight: true,
items : [ toolpanel, confform, infoPanel ]
});

View file

@ -18,7 +18,7 @@ tvheadend.dvrprio = new Ext.data.SimpleStore({
tvheadend.containers = new Ext.data.SimpleStore({
fields : [ 'identifier', 'name' ],
id : 0,
data : [ [ 'matroska', 'Matroska' ], [ 'pass', 'Pass-through' ] ]
data : [ [ 'matroska', 'Matroska' ], [ 'pass', 'TS (Pass-through)' ] ]
});
/**
@ -748,9 +748,6 @@ tvheadend.dvrsettings = function() {
}), new Ext.form.Checkbox({
fieldLabel : 'Include channel name in filename',
name : 'channelInTitle'
}), new Ext.form.Checkbox({
fieldLabel : 'Remove all unsafe characters from filename',
name : 'cleanTitle'
}), new Ext.form.Checkbox({
fieldLabel : 'Include date in filename',
name : 'dateInTitle'
@ -760,6 +757,9 @@ tvheadend.dvrsettings = function() {
}), new Ext.form.Checkbox({
fieldLabel : 'Include episode in filename',
name : 'episodeInTitle'
}), new Ext.form.Checkbox({
fieldLabel : 'Remove all unsafe characters from filename',
name : 'cleanTitle'
}), new Ext.form.Checkbox({
fieldLabel : 'Replace whitespace in title with \'-\'',
name : 'whitespaceInTitle'

View file

@ -185,15 +185,25 @@ tvheadend.epggrab = function() {
});
/*
* Simple fieldet
* Simple fields
*/
var simplePanel = new Ext.form.FieldSet({
title : 'Basic Config',
width : 800,
title : 'General Config',
width : 700,
autoHeight : true,
collapsible : true,
items : [ interval, internalModule, intervalValue, intervalUnit,
channelRename, channelRenumber, channelReicon ]
items : [ channelRename, channelRenumber, channelReicon ]
});
/*
* Internal grabber
*/
var internalPanel = new Ext.form.FieldSet({
title : 'Internal Grabber',
width : 700,
autoHeight : true,
collapsible : true,
items : [ interval, internalModule, intervalValue, intervalUnit ]
});
/* ****************************************************************
@ -243,7 +253,7 @@ tvheadend.epggrab = function() {
var externalPanel = new Ext.form.FieldSet({
title : 'External Interfaces',
width : 800,
width : 700,
autoHeight : true,
collapsible : true,
collapsed : true,
@ -287,8 +297,8 @@ tvheadend.epggrab = function() {
});
var otaPanel = new Ext.form.FieldSet({
title : 'OTA Interfaces',
width : 800,
title : 'Over-the-air Grabbers',
width : 700,
autoHeight : true,
collapsible : true,
collapsed : true,
@ -325,7 +335,7 @@ tvheadend.epggrab = function() {
layout : 'form',
defaultType : 'textfield',
autoHeight : true,
items : [ simplePanel, externalPanel, otaPanel ],
items : [ simplePanel, internalPanel, otaPanel, externalPanel ],
tbar : [ saveButton, '->', helpButton ]
});
@ -360,6 +370,7 @@ tvheadend.epggrab = function() {
/* Hack to get display working */
delay = new Ext.util.DelayedTask(function() {
simplePanel.doLayout(false);
internalPanel.doLayout(false);
externalPanel.doLayout(false);
otaPanel.doLayout(false);
});

View file

@ -1,19 +1,19 @@
tvheadend.servicetypeStore = new Ext.data.JsonStore({
root : 'entries',
id : 'val',
url : '/iptv/services',
baseParams : {
op : 'servicetypeList'
},
fields : [ 'val', 'str' ],
autoLoad : true
});
/**
* IPTV service grid
*/
tvheadend.iptv = function(adapterId) {
var servicetypeStore = new Ext.data.JsonStore({
root : 'entries',
id : 'val',
url : '/iptv/services',
baseParams : {
op : 'servicetypeList'
},
fields : [ 'val', 'str' ],
autoLoad : false
});
var fm = Ext.form;
var enabledColumn = new Ext.grid.CheckColumn({
@ -113,10 +113,10 @@ tvheadend.iptv = function(adapterId) {
editable : false,
mode : 'local',
triggerAction : 'all',
store : tvheadend.servicetypeStore
store : servicetypeStore
}),
renderer : function(value, metadata, record, row, col, store) {
var val = value ? tvheadend.servicetypeStore.getById(value) : null;
var val = value ? servicetypeStore.getById(value) : null;
return val ? val.get('str')
: '<span class="tvh-grid-unset">Unset</span>';
}
@ -291,7 +291,13 @@ tvheadend.iptv = function(adapterId) {
iconCls : 'add',
text : 'Add service',
handler : addRecord
}, '-', delButton, '-', saveBtn, rejectBtn ]
}, '-', delButton, '-', saveBtn, rejectBtn, '->',
{
text : 'Help',
handler : function() {
new tvheadend.help('IPTV', 'config_iptv.html');
}
} ]
});
store.on('update', function(s, r, o) {

View file

@ -24,6 +24,8 @@ tvheadend.comet.on('tvAdapter', function(m) {
});
tvheadend.tvadapters = function() {
tvheadend.tvAdapterStore.load();
var adapterSelection = new Ext.form.ComboBox({
loadingText : 'Loading...',
width : 300,

View file

@ -299,6 +299,7 @@ tvheadend.app = function() {
boxMaxHeight : 45,
boxMinHeight : 45,
border: false,
hidden: true,
html: '<div id="header"><h1>Tvheadend Web-Panel</h1></div>'
});

View file

@ -144,6 +144,7 @@ http_stream_run(http_connection_t *hc, streaming_queue_t *sq,
{
streaming_message_t *sm;
int run = 1;
int started = 0;
muxer_t *mux = NULL;
int timeouts = 0;
struct timespec ts;
@ -180,10 +181,10 @@ http_stream_run(http_connection_t *hc, streaming_queue_t *sq,
//Check socket status
getsockopt(hc->hc_fd, SOL_SOCKET, SO_ERROR, (char *)&err, &errlen);
if(err) {
tvhlog(LOG_DEBUG, "webui", "Client hung up, exit streaming");
tvhlog(LOG_DEBUG, "webui", "Stop streaming %s, client hung up", hc->hc_url_orig);
run = 0;
}else if(timeouts >= 20) {
tvhlog(LOG_WARNING, "webui", "Timeout waiting for packets");
tvhlog(LOG_WARNING, "webui", "Stop streaming %s, timeout waiting for packets", hc->hc_url_orig);
run = 0;
}
}
@ -198,9 +199,8 @@ http_stream_run(http_connection_t *hc, streaming_queue_t *sq,
switch(sm->sm_type) {
case SMT_MPEGTS:
case SMT_PACKET:
if(!muxer_write_pkt(mux, sm->sm_data))
sm->sm_data = NULL;
muxer_write_pkt(mux, sm->sm_data);
sm->sm_data = NULL;
break;
case SMT_START:
@ -208,16 +208,19 @@ http_stream_run(http_connection_t *hc, streaming_queue_t *sq,
http_output_content(hc, muxer_mime(mux, sm->sm_data));
muxer_init(mux, sm->sm_data, name);
started = 1;
break;
case SMT_STOP:
muxer_close(mux);
tvhlog(LOG_WARNING, "webui", "Stop streaming %s, %s", hc->hc_url_orig,
streaming_code2txt(sm->sm_code));
run = 0;
break;
case SMT_SERVICE_STATUS:
if(getsockopt(hc->hc_fd, SOL_SOCKET, SO_ERROR, &err, &errlen)) {
tvhlog(LOG_DEBUG, "webui", "Client hung up, exit streaming");
tvhlog(LOG_DEBUG, "webui", "Stop streaming %s, client hung up", hc->hc_url_orig);
run = 0;
}
break;
@ -226,21 +229,29 @@ http_stream_run(http_connection_t *hc, streaming_queue_t *sq,
break;
case SMT_NOSTART:
tvhlog(LOG_DEBUG, "webui", "Couldn't start stream for %s", hc->hc_url_orig);
tvhlog(LOG_WARNING, "webui", "Couldn't start streaming %s, %s", hc->hc_url_orig,
streaming_code2txt(sm->sm_code));
run = 0;
break;
case SMT_EXIT:
muxer_close(mux);
tvhlog(LOG_WARNING, "webui", "Stop streaming %s, %s", hc->hc_url_orig,
streaming_code2txt(sm->sm_code));
run = 0;
break;
}
streaming_msg_free(sm);
if(mux->m_errors)
if(mux->m_errors) {
tvhlog(LOG_WARNING, "webui", "Stop streaming %s, muxer reported errors", hc->hc_url_orig);
run = 0;
}
}
if(started)
muxer_close(mux);
muxer_destroy(mux);
}

25
support/changelog Executable file
View file

@ -0,0 +1,25 @@
#!/bin/bash
#
# Create the Tvheadend changelog
#
# Arguments
CHANGELOG=$1
DIST=$2
VER=$3
# Defaults
[ -z "$DEBEMAIL" ] && DEBEMAIL="andreas@lonelycoder.com"
[ -z "$DEBFULLNAME" ] && DEBFULLNAME="Andreas Öman"
[ -z "$VER" ] && VER=$($(dirname $0)/version)
[ ! -z "$DIST" ] && VER=${VER}~${DIST}
[ -z "$DIST" ] && DIST=unstable
# Output
NOW=$(date -R)
echo >${CHANGELOG} "tvheadend (${VER}) ${DIST}; urgency=low"
echo >>${CHANGELOG}
echo >>${CHANGELOG} " * The full changelog can be found at "
echo >>${CHANGELOG} " http://www.lonelycoder.com/tvheadend/download"
echo >>${CHANGELOG}
echo >>${CHANGELOG} " -- ${DEBFULLNAME} <${DEBEMAIL}> ${NOW}"

View file

@ -7,20 +7,35 @@ URL=http://linuxtv.org/hg/dvb-apps/archive/tip.tar.bz2
TMP=/tmp/getmuxlist.$$
TVH=$(cd $(dirname $0)/..; pwd)/data/dvb-scan
function die
{
[ ! -z "$1" ] && echo $1 || echo
rm -rf $TMP
rm -rf $TVH
exit 1
}
# Get files
rm -rf $TMP
mkdir -p $TMP
cd $TMP
(wget -O - -q $URL | tar xj) || (curl $URL | tar xj)
cd dvb-apps*
echo -n "fetching scan files ... "
(wget -O - -q $URL | tar xj) 2> /dev/null ||\
(curl $URL | tar xj) 2> /dev/null
cd dvb-apps* 2> /dev/null || die "failed"
echo "done"
# Copy to TVH
echo -n "moving into tvh data/ directory ... "
rm -rf $TVH
mkdir -p $TVH
mv ./util/scan/* $TVH
echo "done"
# Cleanup
echo -n "cleaning up ... "
for f in $TVH/*; do
[ -f $f ] && rm -f $f
done
rm -rf $TMP
echo "done"

View file

@ -1,8 +0,0 @@
#!/bin/sh
revision=`cd "$1" && git describe --dirty --abbrev=5 2>/dev/null | sed -e 's/-/./g'`
if ! test $revision; then
test $revision || revision=`cd "$1" && git describe --abbrev=5 2>/dev/null | sed -e 's/-/./g'`
fi
echo $revision

60
support/launchpad-ppa Executable file
View file

@ -0,0 +1,60 @@
#!/bin/bash
#
# Upload packages to launchpad. Note: you must configure dput for tvh-X
# as target PPA, and you should also define DEBFULLNAME and DEBEMAIL
# environment variables
#
# CMD
CMD=$(basename $0)
echo $CMD
# Configuration
TVH_ROOT=$(cd $(dirname $0)/..; pwd)
[ -z "$TVH_DIST" ] && TVH_DIST="lucid natty oneiric precise quantal"
[ -z "$TVH_ARCH" ] && TVH_ARCH="i386 amd64"
# Options
[ ! -z "$1" ] && REL=$1 || REL=master
[ ! -z "$2" ] && PPA=$2 || PPA=unstable
# Setup
cd $TVH_ROOT || exit 1
git checkout $1 && git checkout . || exit 1
NOW=`date -R`
CHANGELOG=$TVH_ROOT/debian/changelog
VERFILE=$TVH_ROOT/src/version.c
# Create version file
VER=$($TVH_ROOT/support/version $VERFILE)
# Fetch scan files
./support/getmuxlist
# For each distro
for d in $TVH_DIST; do
V=${VER}~${d}
echo $V
# Create changelog
$TVH_ROOT/support/changelog "$CHANGELOG" "$d" "$VER"
# Build source package
dpkg-buildpackage -I.git* -S -sgpg -pgpg || exit 1
# Build
if [ "$CMD" == "pbuilder" ]; then
for a in $TVH_ARCH; do
pbuilder-dist $d $a ../tvheadend_${V}.dsc
done
# Upload
else
dput tvh-$PPA ../tvheadend_${V}_source.changes || exit 1
fi
done
# Cleanup
git checkout .

View file

@ -125,7 +125,7 @@ def add_entry ( ents, path = "", name = "", idx = -1, next = -1 ):
for k in ents:
# File
if not ents[k]:
if ents[k] is None:
output_file(d, k, idx+1, p)
p = idx = idx + 1
c = c + 1

View file

@ -1,5 +0,0 @@
#!/bin/bash
sh debian/createcopyright.sh >debian/copyright
dpkg-buildpackage -rfakeroot -b -us -uc
dh_clean

1
support/pbuilder Symbolic link
View file

@ -0,0 +1 @@
launchpad-ppa

53
support/tarball Executable file
View file

@ -0,0 +1,53 @@
#!/bin/bash
#
# Build tarball of the current directory
#
# Exit
function die
{
echo "ERROR: $*"
exit 1
}
# Switch dir
SRCDIR=$(dirname $0)/..
cd $SRCDIR
# Arguments
REL=$1
if [ ! -z "$REL" ]; then
git checkout $REL || die "could not checkout $REL"
fi
# Clean
git checkout . || die "could not clean git tree"
# Version
VER=$(./support/version)
echo $VER | grep -q dirty && die "git tree is not clean"
VER1=$(echo $VER | sed 's/~.*//')
echo $VER1
# Temp directory
TMPDIR=/tmp/tvhtar-$$
mkdir -p $TMPDIR
trap "rm -rf $TMPDIR" EXIT
# Copy
DSTDIR=$TMPDIR/tvheadend-$VER1
mkdir $DSTDIR
git archive HEAD | tar -x -C $DSTDIR
# Remove stuff we don't need
rm -rf $DSTDIR/.gitignore
# Fix changelog (store version)
$DSTDIR/support/changelog $DSTDIR/debian/changelog "" $VER
# Build tarball
TARFILE=$(cd $SRCDIR/..; pwd)/tvheadend-$VER1.tar.gz
tar -C $TMPDIR -zcf $TARFILE tvheadend-$VER1
# Done
echo "Created $TARFILE"

34
support/version Executable file
View file

@ -0,0 +1,34 @@
#!/bin/bash
#
# Update Tvheadend version file (if required)
#
# Path to version file
FILE=$1
# Calculate version
if [ -d ".git" ]; then
VER=$(cd $(dirname $0); git describe --dirty --match "v*" 2> /dev/null | sed "s/^v//" | sed "s/-\([0-9]*\)-\(g[0-9a-f]*\)/.\1~\2/")
else
VER=$(head -1 $(dirname $0)/../debian/changelog | awk '{ print $2 }' | tr -d '()' | cut -d '-' -f 1)
fi
# Output
if [ -z "$FILE" ]; then
echo $VER
exit
fi
# Leave (probably ppa build)
if [ -z "$VER" -a -s "$FILE" ]; then
cat $FILE
exit
fi
# Update?
NEW_VER="const char *tvheadend_version = \"$VER\";"
OLD_VER=$(cat $FILE 2> /dev/null)
if [ "$NEW_VER" != "$OLD_VER" ]; then
echo $NEW_VER > $FILE
fi
echo $VER

View file

@ -1,11 +0,0 @@
#!/bin/sh
revision=`$1/support/getver.sh`
NEW_REVISION="#define BUILD_VERSION \"$revision\""
OLD_REVISION=`cat $2 2> /dev/null`
# Update version.h only on revision changes to avoid spurious rebuilds
if test "$NEW_REVISION" != "$OLD_REVISION"; then
echo "$NEW_REVISION" > "$2"
fi