Version 2.3.2

Merry Christmas to all VDR users!

It's been a very busy year for me, in which I was unable to
spend as much time on VDR as I would have liked to. But now things
are settled again and I managed to prepare a new developer version
with the most important fixes and improvements. Please feel free
to tell me if I missed something important - some things may well
have slipped under my radar ;-).

So here's my Christmas gift for you!

VDR developer version 2.3.2 is now available at

       ftp://ftp.tvdr.de/vdr/Developer/vdr-2.3.2.tar.bz2

A 'diff' against the previous version is available at

       ftp://ftp.tvdr.de/vdr/Developer/vdr-2.3.1-2.3.2.diff

MD5 checksums:

6dbb208ea3d59658a18912b49af175b3  vdr-2.3.2.tar.bz2
68a0ed9f01048026333939d30e0a6474  vdr-2.3.1-2.3.2.diff

WARNING:
========

This is a *developer* version. Even though *I* use it in my productive
environment, I strongly recommend that you only use it under controlled
conditions and for testing and debugging.

From the HISTORY file:
- Fixed a crash when deleting a recording (reported by Oliver Endriss).
- Fixed an overflow of PIDs in a receiver (thanks to Robert Hannebauer).
- Updated the Italian OSD texts (thanks to Diego Pierotto).
- Fixed initializing device specific parameters in cDvbTransponderParameters.
- The function SetCurrentChannel(const cChannel *Channel) is now deprecated and
  may be removed in a future version. Use SetCurrentChannel(int ChannelNumber)
  instead.
- The SVDRP command DELC now refuses to delete the very last channel in the list,
  to avoid ending up with an empty channel list.
- The cRwLock class now allows nested read locks within a write lock from the
  same thread. This fixes possible crashes when moving or deleting channels in
  the menu or through SVDRP (as well as other operations that try to acquire a
  read lock within a write lock).
- Fixed a crash when trying to delete a channel that is being used by a timer.
- Fixed setting the current item and counter values in the Recordings menu after
  deleting the last recording in a subfolder.
- Fixed a crash when deleting a recording that is currently being replayed.
- Fixed a crash when moving a recording to a folder on a different volume.
  The cRecordingsHandler now performs its actual operations in a separate thread,
  thus avoiding locking problems and reducing the time between subsequent
  operations.
- Added a note to the description of cFont::Size(), regarding possible differences
  between it and cFont::Height() (suggested to Thomas Reufer).
- Made the cPlayer member functions FramesPerSecond, GetIndex and GetReplayMode
  'const' (thanks to Thomas Reufer).
- Fixed resuming replay at a given position, which was off by one frame (thanks
  to Thomas Reufer).
- Improved handling frame numbers to have a smoother progress display during
  replay of recordings with B-frames (thanks to Thomas Reufer).
- Fixed replaying recordings to their very end, if they don't end with an I-frame
  (thanks to Thomas Reufer).
- Implemented a frame parser for H.265 (HEVC) recordings (thanks to Thomas Reufer).
- Added cFont::Width(void) to get the default character width and allow stretched
  font drawing in high level OSDs (thanks to Thomas Reufer).
- Fixed regenerating the index of audio recordings (thanks to Thomas Reufer).
- Fixed building VDR with systemd >= 230 (thanks to Ville Skyttä).
- Sorted sources.conf by continous azimuth (thanks to Lucian Muresan).
- Added 'S58.5E Kazsat 3' to sources.conf (thanks to Aitugan Sarbassov).
- Fixed truncated date/time strings in the skins on multi-byte UTF-8 systems
  (reported by Sergey Chernyavskiy).
- Updated the Estonian OSD texts (thanks to Arthur Konovalov).
- Added a 'const' version of cTimers::GetTimer() (thanks to Lars Hanisch).
- Fixed a typo in the description of cTimers::GetTimersRead() (thanks to Lars
  Hanisch).
- Fixed a possible buffer overflow in handling CA descriptors (suggested by
  Lars Hanisch).
- Avoiding some duplicate code and unnecessary work in nit.c (thanks to Ville
  Skyttä).
- Added support for the systemd watchdog (thanks to Marc Perrudin),
- Added a short sleep to cTSBuffer::Action() to avoid high CPU usage (thanks to
  Sergey Chernyavskiy).
This commit is contained in:
Klaus Schmidinger 2016-12-24 10:07:00 +01:00 committed by Dieter Hametner
parent a26aae3ce8
commit ec0ec6da01
41 changed files with 862 additions and 511 deletions

View File

@ -715,6 +715,7 @@ Oliver Endriss <o.endriss@gmx.de>
for suggesting to ignore channels with an RID that is not 0 when checking for obsolete
channels
for fixing a possible stack overflow in cListBase::Sort()
for reporting a crash when deleting a recording
Reinhard Walter Buchner <rw.buchner@freenet.de>
for adding some satellites to 'sources.conf'
@ -1844,6 +1845,7 @@ Lucian Muresan <lucianm@users.sourceforge.net>
for exporting some libsi functions
for suggesting to add functions to cDevice that allow derived output devices to
implement scaling the video to a given size and location
fpr sorting sources.conf by continous azimuth
Mattias Grönlund <Mattias@Gronlund.net>
for pointing out a missing cleanup at program exit in case there is a problem
@ -2062,6 +2064,8 @@ Ville Skytt
for reporting a possible NULL pointer dereference in cCiSession::SendData()
for reporting a superfluous assignment in cPipe::Open()
for avoiding unnecessary pkg-config warnings in plugin Makefiles
for fixing building VDR with systemd >= 230
for avoiding some duplicate code and unnecessary work in nit.c
Steffen Beyer <cpunk@reactor.de>
for fixing setting the colored button help after deleting a recording in case the next
@ -2924,6 +2928,10 @@ Lars Hanisch <dvb@flensrocker.de>
for making VDR read command line options from *.conf files in /etc/vdr/conf.d
for adding a missing backslash to the help text of the SVDRP command MOVR
for fixing a memory leak in case of broken Extended Event Descriptors
for adding a 'const' version of cTimers::GetTimer()
for fixing a typo in the description of cTimers::GetTimersRead()
for suggesting to use dynamic buffering in handling CA descriptors to avoid a
possible buffer overflow
Alex Lasnier <alex@fepg.org>
for adding tuning support for ATSC devices
@ -3225,6 +3233,7 @@ Malte Forkel <malte.forkel@berlin.de>
Marc Perrudin <vdr@ekass.net>
for translating OSD texts to the French language
for adding support for the systemd watchdog
Bernard Jaulin <bernard.jaulin@gmail.com>
for translating OSD texts to the French language
@ -3322,6 +3331,18 @@ Thomas Reufer <thomas@reufer.ch>
ViewPort and DrawPort
for suggesting to reduce the priority of the "video directory scanner" thread
for making the 'newplugin' script create the 'po' subdirectory for translations
for suggesting to add a note to the description of cFont::Size(), regarding possible
differences between it and cFont::Height()
for making the cPlayer member functions FramesPerSecond, GetIndex and GetReplayMode
'const'
for fixing resuming replay at a given position, which was off by one frame
for improving handling frame numbers to have a smoother progress display during
replay of recordings with B-frames
for fixing replaying recordings to their very end, if they don't end with an I-frame
for implementing a frame parser for H.265 (HEVC) recordings
for adding cFont::Width(void) to get the default character width and allow stretched
font drawing in high level OSDs
for fixing regenerating the index of audio recordings
Eike Sauer <EikeSauer@t-online.de>
for reporting a problem with channels that need more than 5 TS packets for detecting
@ -3428,3 +3449,13 @@ Janne P
Stefan Pöschel <basic.master@gmx.de>
for coding the AFFcleaner, parts of which were used to make the recorder skip empty
adaptation field TS packets
Robert Hannebauer <vdr@hannebauer.org>
for fixing an overflow of PIDs in a receiver
Aitugan Sarbassov <isarbassov@gmail.com>
for adding 'S58.5E Kazsat 3' to sources.conf
Sergey Chernyavskiy <glenvt18@gmail.com>
for reporting truncated date/time strings in the skins on multi-byte UTF-8
for adding a short sleep to cTSBuffer::Action() to avoid high CPU usage

54
HISTORY
View File

@ -8827,3 +8827,57 @@ Video Disk Recorder Revision History
live tv (suggested by Dietmar Spingler).
- Empty adaptation field TS packets are now skipped when recording (thanks to
Christopher Reimer, based on the "AFFcleaner" by Stefan Pöschel).
2016-12-24: Version 2.3.2
- Fixed a crash when deleting a recording (reported by Oliver Endriss).
- Fixed an overflow of PIDs in a receiver (thanks to Robert Hannebauer).
- Updated the Italian OSD texts (thanks to Diego Pierotto).
- Fixed initializing device specific parameters in cDvbTransponderParameters.
- The function SetCurrentChannel(const cChannel *Channel) is now deprecated and
may be removed in a future version. Use SetCurrentChannel(int ChannelNumber)
instead.
- The SVDRP command DELC now refuses to delete the very last channel in the list,
to avoid ending up with an empty channel list.
- The cRwLock class now allows nested read locks within a write lock from the
same thread. This fixes possible crashes when moving or deleting channels in
the menu or through SVDRP (as well as other operations that try to acquire a
read lock within a write lock).
- Fixed a crash when trying to delete a channel that is being used by a timer.
- Fixed setting the current item and counter values in the Recordings menu after
deleting the last recording in a subfolder.
- Fixed a crash when deleting a recording that is currently being replayed.
- Fixed a crash when moving a recording to a folder on a different volume.
The cRecordingsHandler now performs its actual operations in a separate thread,
thus avoiding locking problems and reducing the time between subsequent
operations.
- Added a note to the description of cFont::Size(), regarding possible differences
between it and cFont::Height() (suggested to Thomas Reufer).
- Made the cPlayer member functions FramesPerSecond, GetIndex and GetReplayMode
'const' (thanks to Thomas Reufer).
- Fixed resuming replay at a given position, which was off by one frame (thanks
to Thomas Reufer).
- Improved handling frame numbers to have a smoother progress display during
replay of recordings with B-frames (thanks to Thomas Reufer).
- Fixed replaying recordings to their very end, if they don't end with an I-frame
(thanks to Thomas Reufer).
- Implemented a frame parser for H.265 (HEVC) recordings (thanks to Thomas Reufer).
- Added cFont::Width(void) to get the default character width and allow stretched
font drawing in high level OSDs (thanks to Thomas Reufer).
- Fixed regenerating the index of audio recordings (thanks to Thomas Reufer).
- Fixed building VDR with systemd >= 230 (thanks to Ville Skyttä).
- Sorted sources.conf by continous azimuth (thanks to Lucian Muresan).
- Added 'S58.5E Kazsat 3' to sources.conf (thanks to Aitugan Sarbassov).
- Fixed truncated date/time strings in the skins on multi-byte UTF-8 systems
(reported by Sergey Chernyavskiy).
- Updated the Estonian OSD texts (thanks to Arthur Konovalov).
- Added a 'const' version of cTimers::GetTimer() (thanks to Lars Hanisch).
- Fixed a typo in the description of cTimers::GetTimersRead() (thanks to Lars
Hanisch).
- Fixed a possible buffer overflow in handling CA descriptors (suggested by
Lars Hanisch).
- Avoiding some duplicate code and unnecessary work in nit.c (thanks to Ville
Skyttä).
- Added support for the systemd watchdog (thanks to Marc Perrudin),
- Added a short sleep to cTSBuffer::Action() to avoid high CPU usage (thanks to
Sergey Chernyavskiy).

View File

@ -4,7 +4,7 @@
# See the main source file 'vdr.c' for copyright information and
# how to reach the author.
#
# $Id: Makefile 4.0 2015/02/09 12:28:24 kls Exp $
# $Id: Makefile 4.1 2016/12/22 13:18:32 kls Exp $
.DELETE_ON_ERROR:
@ -95,9 +95,9 @@ DEFINES += -DBIDI
LIBS += $(shell pkg-config --libs fribidi)
endif
ifdef SDNOTIFY
INCLUDES += $(shell pkg-config --cflags libsystemd-daemon)
INCLUDES += $(shell pkg-config --silence-errors --cflags libsystemd-daemon || pkg-config --cflags libsystemd)
DEFINES += -DSDNOTIFY
LIBS += $(shell pkg-config --libs libsystemd-daemon)
LIBS += $(shell pkg-config --silence-errors --libs libsystemd-daemon || pkg-config --libs libsystemd)
endif
LIRC_DEVICE ?= /var/run/lirc/lircd

View File

@ -130,3 +130,10 @@ VDR Plugin 'skincurses' Revision History
2015-02-19: Version 2.2.0
- Official release.
2016-12-22: Version 2.3.2
- Added cFont::Width(void) to get the default character width and allow stretched
font drawing in high level OSDs (dummy for skincurses).
- Fixed truncated date/time strings in the skins on multi-byte UTF-8 systems
(reported by Sergey Chernyavskiy).

View File

@ -3,7 +3,7 @@
*
* See the README file for copyright information and how to reach the author.
*
* $Id: skincurses.c 4.0 2015/02/17 13:13:17 kls Exp $
* $Id: skincurses.c 4.2 2016/12/22 14:09:09 kls Exp $
*/
#include <ncurses.h>
@ -12,7 +12,7 @@
#include <vdr/skins.h>
#include <vdr/videodir.h>
static const char *VERSION = "2.2.0";
static const char *VERSION = "2.3.2";
static const char *DESCRIPTION = trNOOP("A text only skin");
static const char *MAINMENUENTRY = NULL;
@ -20,6 +20,7 @@ static const char *MAINMENUENTRY = NULL;
class cCursesFont : public cFont {
public:
virtual int Width(void) const { return 1; }
virtual int Width(uint c) const { return 1; }
virtual int Width(const char *s) const { return s ? Utf8StrLen(s) : 0; }
virtual int Height(void) const { return 1; }
@ -407,8 +408,7 @@ void cSkinCursesDisplayMenu::SetEvent(const cEvent *Event)
return;
int y = 2;
cTextScroller ts;
char t[32];
snprintf(t, sizeof(t), "%s %s - %s", *Event->GetDateString(), *Event->GetTimeString(), *Event->GetEndTimeString());
cString t = cString::sprintf("%s %s - %s", *Event->GetDateString(), *Event->GetTimeString(), *Event->GetEndTimeString());
ts.Set(osd, 0, y, ScOsdWidth, ScOsdHeight - y - 2, t, &Font, clrYellow, clrBackground);
if (Event->Vps() && Event->Vps() != Event->StartTime()) {
cString buffer = cString::sprintf(" VPS: %s", *Event->GetVpsString());

67
ci.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: ci.c 4.2 2015/09/05 11:45:19 kls Exp $
* $Id: ci.c 4.3 2016/12/23 14:00:45 kls Exp $
*/
#include "ci.h"
@ -756,9 +756,9 @@ class cCiCaPmt {
friend class cCiConditionalAccessSupport;
private:
uint8_t cmdId;
int length;
int esInfoLengthPos;
uint8_t capmt[2048]; ///< XXX is there a specified maximum?
cDynamicBuffer caDescriptors;
cDynamicBuffer capmt;
int source;
int transponder;
int programNumber;
@ -768,7 +768,7 @@ public:
cCiCaPmt(uint8_t CmdId, int Source, int Transponder, int ProgramNumber, const int *CaSystemIds);
uint8_t CmdId(void) { return cmdId; }
void SetListManagement(uint8_t ListManagement);
uint8_t ListManagement(void) { return capmt[0]; }
uint8_t ListManagement(void) { return capmt.Get(0); }
void AddPid(int Pid, uint8_t StreamType);
};
@ -784,55 +784,46 @@ cCiCaPmt::cCiCaPmt(uint8_t CmdId, int Source, int Transponder, int ProgramNumber
caSystemIds[i] = CaSystemIds[i];
}
caSystemIds[i] = 0;
uint8_t caDescriptors[512];
int caDescriptorsLength = GetCaDescriptors(source, transponder, programNumber, caSystemIds, sizeof(caDescriptors), caDescriptors, 0);
length = 0;
capmt[length++] = CPLM_ONLY;
capmt[length++] = (ProgramNumber >> 8) & 0xFF;
capmt[length++] = ProgramNumber & 0xFF;
capmt[length++] = 0x01; // version_number, current_next_indicator - apparently vn doesn't matter, but cni must be 1
esInfoLengthPos = length;
capmt[length++] = 0x00; // program_info_length H (at program level)
capmt[length++] = 0x00; // program_info_length L
AddCaDescriptors(caDescriptorsLength, caDescriptors);
GetCaDescriptors(source, transponder, programNumber, caSystemIds, caDescriptors, 0);
capmt.Append(CPLM_ONLY);
capmt.Append((ProgramNumber >> 8) & 0xFF);
capmt.Append( ProgramNumber & 0xFF);
capmt.Append(0x01); // version_number, current_next_indicator - apparently vn doesn't matter, but cni must be 1
esInfoLengthPos = capmt.Length();
capmt.Append(0x00); // program_info_length H (at program level)
capmt.Append(0x00); // program_info_length L
AddCaDescriptors(caDescriptors.Length(), caDescriptors.Data());
}
void cCiCaPmt::SetListManagement(uint8_t ListManagement)
{
capmt[0] = ListManagement;
capmt.Set(0, ListManagement);
}
void cCiCaPmt::AddPid(int Pid, uint8_t StreamType)
{
if (Pid) {
uint8_t caDescriptors[512];
int caDescriptorsLength = GetCaDescriptors(source, transponder, programNumber, caSystemIds, sizeof(caDescriptors), caDescriptors, Pid);
//XXX buffer overflow check???
capmt[length++] = StreamType;
capmt[length++] = (Pid >> 8) & 0xFF;
capmt[length++] = Pid & 0xFF;
esInfoLengthPos = length;
capmt[length++] = 0x00; // ES_info_length H (at ES level)
capmt[length++] = 0x00; // ES_info_length L
AddCaDescriptors(caDescriptorsLength, caDescriptors);
GetCaDescriptors(source, transponder, programNumber, caSystemIds, caDescriptors, Pid);
capmt.Append(StreamType);
capmt.Append((Pid >> 8) & 0xFF);
capmt.Append( Pid & 0xFF);
esInfoLengthPos = capmt.Length();
capmt.Append(0x00); // ES_info_length H (at ES level)
capmt.Append(0x00); // ES_info_length L
AddCaDescriptors(caDescriptors.Length(), caDescriptors.Data());
}
}
void cCiCaPmt::AddCaDescriptors(int Length, const uint8_t *Data)
{
if (esInfoLengthPos) {
if (length + Length < int(sizeof(capmt))) {
if (Length || cmdId == CPCI_QUERY) {
capmt[length++] = cmdId;
memcpy(capmt + length, Data, Length);
length += Length;
int l = length - esInfoLengthPos - 2;
capmt[esInfoLengthPos] = (l >> 8) & 0xFF;
capmt[esInfoLengthPos + 1] = l & 0xFF;
}
if (Length || cmdId == CPCI_QUERY) {
capmt.Append(cmdId);
capmt.Append(Data, Length);
int l = capmt.Length() - esInfoLengthPos - 2;
capmt.Set(esInfoLengthPos, (l >> 8) & 0xFF);
capmt.Set(esInfoLengthPos + 1, l & 0xFF);
}
else
esyslog("ERROR: buffer overflow in CA descriptor");
esInfoLengthPos = 0;
}
else
@ -995,7 +986,7 @@ void cCiConditionalAccessSupport::SendPMT(cCiCaPmt *CaPmt)
{
if (CaPmt && state >= 2) {
dbgprotocol("Slot %d: ==> Ca Pmt (%d) %d %d\n", Tc()->CamSlot()->SlotNumber(), SessionId(), CaPmt->ListManagement(), CaPmt->CmdId());
SendData(AOT_CA_PMT, CaPmt->length, CaPmt->capmt);
SendData(AOT_CA_PMT, CaPmt->capmt.Length(), CaPmt->capmt.Data());
state = 4; // sent ca pmt
}
}

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: config.h 4.5 2015/09/11 08:07:34 kls Exp $
* $Id: config.h 4.6 2015/09/16 11:11:42 kls Exp $
*/
#ifndef __CONFIG_H
@ -22,13 +22,13 @@
// VDR's own version number:
#define VDRVERSION "2.3.1"
#define VDRVERSNUM 20301 // Version * 10000 + Major * 100 + Minor
#define VDRVERSION "2.3.2"
#define VDRVERSNUM 20302 // Version * 10000 + Major * 100 + Minor
// The plugin API's version number:
#define APIVERSION "2.3.1"
#define APIVERSNUM 20301 // Version * 10000 + Major * 100 + Minor
#define APIVERSION "2.3.2"
#define APIVERSNUM 20302 // Version * 10000 + Major * 100 + Minor
// When loading plugins, VDR searches them by their APIVERSION, which
// may be smaller than VDRVERSION in case there have been no changes to

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: device.c 4.2 2015/09/05 11:42:17 kls Exp $
* $Id: device.c 4.3 2016/12/23 14:43:44 kls Exp $
*/
#include "device.h"
@ -1768,6 +1768,7 @@ void cTSBuffer::Action(void)
break;
}
}
cCondWait::SleepMs(10); // avoids small chunks of data, which cause high CPU usage, esp. on ARM CPUs
}
}
}

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: device.h 4.1 2015/04/19 12:12:43 kls Exp $
* $Id: device.h 4.2 2016/12/06 14:12:39 kls Exp $
*/
#ifndef __DEVICE_H
@ -322,7 +322,11 @@ protected:
public:
static int CurrentChannel(void) { return primaryDevice ? currentChannel : 0; }
///< Returns the number of the current channel on the primary device.
#define DEPRECATED_SETCURRENTCHANNEL
#ifdef DEPRECATED_SETCURRENTCHANNEL
static void SetCurrentChannel(const cChannel *Channel) { currentChannel = Channel ? Channel->Number() : 0; }
#endif
static void SetCurrentChannel(int ChannelNumber) { currentChannel = ChannelNumber; }
///< Sets the number of the current channel on the primary device, without
///< actually switching to it. This can be used to correct the current
///< channel number while replaying.

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: dvbdevice.c 4.2 2015/04/18 16:19:28 kls Exp $
* $Id: dvbdevice.c 4.3 2016/11/07 13:55:58 kls Exp $
*/
#include "dvbdevice.h"
@ -201,21 +201,6 @@ int MapToDriver(int Value, const tDvbParameterMap *Map)
cDvbTransponderParameters::cDvbTransponderParameters(const char *Parameters)
{
polarization = 0;
inversion = INVERSION_AUTO;
bandwidth = 8000000;
coderateH = FEC_AUTO;
coderateL = FEC_AUTO;
modulation = QPSK;
system = DVB_SYSTEM_1;
transmission = TRANSMISSION_MODE_AUTO;
guard = GUARD_INTERVAL_AUTO;
hierarchy = HIERARCHY_AUTO;
rollOff = ROLLOFF_AUTO;
streamId = 0;
t2systemId = 0;
sisoMiso = 0;
pilot = PILOT_AUTO;
Parse(Parameters);
}
@ -266,6 +251,21 @@ const char *cDvbTransponderParameters::ParseParameter(const char *s, int &Value,
bool cDvbTransponderParameters::Parse(const char *s)
{
polarization = 0;
inversion = INVERSION_AUTO;
bandwidth = 8000000;
coderateH = FEC_AUTO;
coderateL = FEC_AUTO;
modulation = QPSK;
system = DVB_SYSTEM_1;
transmission = TRANSMISSION_MODE_AUTO;
guard = GUARD_INTERVAL_AUTO;
hierarchy = HIERARCHY_AUTO;
rollOff = ROLLOFF_AUTO;
streamId = 0;
t2systemId = 0;
sisoMiso = 0;
pilot = PILOT_AUTO;
while (s && *s) {
switch (toupper(*s)) {
case 'B': s = ParseParameter(s, bandwidth, BandwidthValues); break;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: dvbplayer.c 4.1 2015/08/06 13:09:19 kls Exp $
* $Id: dvbplayer.c 4.4 2016/12/22 11:34:31 kls Exp $
*/
#include "dvbplayer.h"
@ -17,13 +17,14 @@
// --- cPtsIndex -------------------------------------------------------------
#define PTSINDEX_ENTRIES 500
#define PTSINDEX_ENTRIES 1024
class cPtsIndex {
private:
struct tPtsIndex {
uint32_t pts; // no need for 33 bit - some devices don't even supply the msb
int index;
bool independent;
};
tPtsIndex pi[PTSINDEX_ENTRIES];
int w, r;
@ -33,8 +34,9 @@ public:
cPtsIndex(void);
void Clear(void);
bool IsEmpty(void);
void Put(uint32_t Pts, int Index);
void Put(uint32_t Pts, int Index, bool Independent);
int FindIndex(uint32_t Pts);
int FindFrameNumber(uint32_t Pts);
};
cPtsIndex::cPtsIndex(void)
@ -55,10 +57,11 @@ bool cPtsIndex::IsEmpty(void)
return w == r;
}
void cPtsIndex::Put(uint32_t Pts, int Index)
void cPtsIndex::Put(uint32_t Pts, int Index, bool Independent)
{
cMutexLock MutexLock(&mutex);
pi[w].pts = Pts;
pi[w].independent = Independent;
pi[w].index = Index;
w = (w + 1) % PTSINDEX_ENTRIES;
if (w == r)
@ -87,6 +90,36 @@ int cPtsIndex::FindIndex(uint32_t Pts)
return Index;
}
int cPtsIndex::FindFrameNumber(uint32_t Pts)
{
cMutexLock MutexLock(&mutex);
if (w == r)
return lastFound; // replay always starts at an I frame
bool Valid = false;
int d;
int FrameNumber = 0;
int UnplayedIFrame = 2; // GOPs may intersect, so we're looping until we found two unplayed I frames
for (int i = r; i != w && UnplayedIFrame; ) {
d = Pts - pi[i].pts;
if (d > 0x7FFFFFFF)
d = 0xFFFFFFFF - d; // handle rollover
if (d > 0) {
if (pi[i].independent) {
FrameNumber = pi[i].index; // an I frame's index represents its frame number
Valid = true;
}
else
FrameNumber++; // for every played non-I frame, increase frame number
}
else
if (pi[i].independent)
--UnplayedIFrame;
if (++i >= PTSINDEX_ENTRIES)
i = 0;
}
return Valid ? FrameNumber : FindIndex(Pts); // fall back during trick speeds
}
// --- cNonBlockingFileReader ------------------------------------------------
class cNonBlockingFileReader : public cThread {
@ -251,6 +284,7 @@ public:
virtual double FramesPerSecond(void) { return framesPerSecond; }
virtual void SetAudioTrack(eTrackType Type, const tTrackId *TrackId);
virtual bool GetIndex(int &Current, int &Total, bool SnapToIFrame = false);
virtual bool GetFrameNumber(int &Current, int &Total);
virtual bool GetReplayMode(bool &Play, bool &Forward, int &Speed);
};
@ -433,6 +467,8 @@ void cDvbPlayer::Action(void)
}
StateKey.Remove();
}
if (readIndex > 0) // will first be incremented in the loop!
--readIndex;
nonBlockingFileReader = new cNonBlockingFileReader;
int Length = 0;
@ -440,7 +476,7 @@ void cDvbPlayer::Action(void)
bool WaitingForData = false;
time_t StuckAtEof = 0;
uint32_t LastStc = 0;
int LastReadIFrame = -1;
int LastReadFrame = -1;
int SwitchToPlayFrame = 0;
bool CutIn = false;
bool AtLastMark = false;
@ -544,12 +580,9 @@ void cDvbPlayer::Action(void)
int r = nonBlockingFileReader->Result(&b);
if (r > 0) {
WaitingForData = false;
uint32_t Pts = 0;
if (readIndependent) {
Pts = isPesRecording ? PesGetPts(b) : TsGetPts(b, r);
LastReadIFrame = readIndex;
}
readFrame = new cFrame(b, -r, ftUnknown, readIndex, Pts); // hands over b to the ringBuffer
LastReadFrame = readIndex;
uint32_t Pts = isPesRecording ? (PesHasPts(b) ? PesGetPts(b) : -1) : TsGetPts(b, r);
readFrame = new cFrame(b, -r, ftUnknown, readIndex, Pts, readIndependent); // hands over b to the ringBuffer
}
else if (r < 0) {
if (errno == EAGAIN)
@ -604,7 +637,7 @@ void cDvbPlayer::Action(void)
pc = playFrame->Count();
if (p) {
if (playFrame->Index() >= 0 && playFrame->Pts() != 0)
ptsIndex.Put(playFrame->Pts(), playFrame->Index());
ptsIndex.Put(playFrame->Pts(), playFrame->Index(), playFrame->Independent());
if (firstPacket) {
if (isPesRecording) {
PlayPes(NULL, 0);
@ -667,7 +700,7 @@ void cDvbPlayer::Action(void)
LastStc = Stc;
int Index = ptsIndex.FindIndex(Stc);
if (playDir == pdForward && !SwitchToPlayFrame) {
if (Index >= LastReadIFrame)
if (Index >= LastReadFrame)
break; // automatically stop at end of recording
}
else if (Index <= 0 || SwitchToPlayFrame && Index >= SwitchToPlayFrame)
@ -878,7 +911,7 @@ void cDvbPlayer::Goto(int Index, bool Still)
if (playMode == pmPause)
DevicePlay();
DeviceStillPicture(b, r);
ptsIndex.Put(isPesRecording ? PesGetPts(b) : TsGetPts(b, r), Index);
ptsIndex.Put(isPesRecording ? PesGetPts(b) : TsGetPts(b, r), Index, true);
}
playMode = pmStill;
readIndex = Index;
@ -923,6 +956,17 @@ bool cDvbPlayer::GetIndex(int &Current, int &Total, bool SnapToIFrame)
return false;
}
bool cDvbPlayer::GetFrameNumber(int &Current, int &Total)
{
if (index) {
Current = ptsIndex.FindFrameNumber(DeviceGetSTC());
Total = index->Last();
return true;
}
Current = Total = -1;
return false;
}
bool cDvbPlayer::GetReplayMode(bool &Play, bool &Forward, int &Speed)
{
Play = (playMode == pmPlay || playMode == pmFast);
@ -1009,6 +1053,15 @@ bool cDvbPlayerControl::GetIndex(int &Current, int &Total, bool SnapToIFrame)
return false;
}
bool cDvbPlayerControl::GetFrameNumber(int &Current, int &Total)
{
if (player) {
player->GetFrameNumber(Current, Total);
return true;
}
return false;
}
bool cDvbPlayerControl::GetReplayMode(bool &Play, bool &Forward, int &Speed)
{
return player && player->GetReplayMode(Play, Forward, Speed);

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: dvbplayer.h 4.1 2015/08/02 13:01:44 kls Exp $
* $Id: dvbplayer.h 4.2 2016/12/22 10:36:50 kls Exp $
*/
#ifndef __DVBPLAYER_H
@ -50,6 +50,10 @@ public:
bool GetIndex(int &Current, int &Total, bool SnapToIFrame = false);
// Returns the current and total frame index, optionally snapped to the
// nearest I-frame.
bool GetFrameNumber(int &Current, int &Total);
// Returns the current and total frame number. In contrast to GetIndex(),
// this function respects the chronological order of frames, which is
// different from its index for streams containing B frames (e.g. H264)
bool GetReplayMode(bool &Play, bool &Forward, int &Speed);
// Returns the current replay mode (if applicable).
// 'Play' tells whether we are playing or pausing, 'Forward' tells whether

15
font.c
View File

@ -6,7 +6,7 @@
*
* BiDi support by Osama Alrawab <alrawab@hotmail.com> @2008 Tripoli-Libya.
*
* $Id: font.c 4.1 2015/04/19 11:13:45 kls Exp $
* $Id: font.c 4.2 2016/12/22 12:31:23 kls Exp $
*/
#include "font.h"
@ -100,6 +100,7 @@ class cFreetypeFont : public cFont {
private:
cString fontName;
int size;
int width;
int height;
int bottom;
FT_Library library; ///< Handle to library
@ -114,6 +115,7 @@ public:
virtual ~cFreetypeFont();
virtual const char *FontName(void) const { return fontName; }
virtual int Size(void) const { return size; }
virtual int Width(void) const { return width; }
virtual int Width(uint c) const;
virtual int Width(const char *s) const;
virtual int Height(void) const { return height; }
@ -125,6 +127,7 @@ cFreetypeFont::cFreetypeFont(const char *Name, int CharHeight, int CharWidth)
{
fontName = Name;
size = CharHeight;
width = CharWidth;
height = 0;
bottom = 0;
int error = FT_Init_FreeType(&library);
@ -384,10 +387,12 @@ void cFreetypeFont::DrawText(cPixmap *Pixmap, int x, int y, const char *s, tColo
class cDummyFont : public cFont {
private:
int height;
int width;
public:
cDummyFont(int CharHeight) { height = CharHeight; }
virtual int Width(uint c) const { return height; }
virtual int Width(const char *s) const { return height; }
cDummyFont(int CharHeight, int CharWidth) { height = CharHeight; width = CharWidth; }
virtual int Width(void) const { return width ? width : height; }
virtual int Width(uint c) const { return width ? width : height; }
virtual int Width(const char *s) const { return width ? width : height; }
virtual int Height(void) const { return height; }
virtual void DrawText(cBitmap *Bitmap, int x, int y, const char *s, tColor ColorFg, tColor ColorBg, int Width) const {}
virtual void DrawText(cPixmap *Pixmap, int x, int y, const char *s, tColor ColorFg, tColor ColorBg, int Width) const {};
@ -425,7 +430,7 @@ cFont *cFont::CreateFont(const char *Name, int CharHeight, int CharWidth)
cString fn = GetFontFileName(Name);
cFont *f = *fn ? new cFreetypeFont(fn, CharHeight, CharWidth) : NULL;
if (!f || !f->Height())
f = new cDummyFont(CharHeight);
f = new cDummyFont(CharHeight, CharWidth);
return f;
}

8
font.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: font.h 4.0 2014/01/07 12:11:55 kls Exp $
* $Id: font.h 4.2 2016/12/22 12:43:24 kls Exp $
*/
#ifndef __FONT_H
@ -43,7 +43,11 @@ public:
///< Returns the font name.
virtual int Size(void) const { return Height(); }
///< Returns the original size as requested when the font was created.
///< This may be different than the actual height.
///< This may be smaller than the actual height, for instance if the
///< font contains descenders.
virtual int Width(void) const = 0;
///< Returns the original character width as requested when the font was
///< created, or 0 if the default width is used.
virtual int Width(uint c) const = 0;
///< Returns the width of the given character in pixel.
virtual int Width(const char *s) const = 0;

149
menu.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: menu.c 4.12 2015/09/14 13:22:49 kls Exp $
* $Id: menu.c 4.19 2016/12/22 11:00:13 kls Exp $
*/
#include "menu.h"
@ -498,6 +498,7 @@ eOSState cMenuChannels::Delete(void)
int DeletedChannel = Channel->Number();
// Check if there is a timer using this channel:
if (Timers->UsesChannel(Channel)) {
channelsStateKey.Remove(false);
Skins.Message(mtError, tr("Channel is being used by a timer!"));
return osContinue;
}
@ -519,7 +520,7 @@ eOSState cMenuChannels::Delete(void)
if (!cDevice::PrimaryDevice()->Replaying() || cDevice::PrimaryDevice()->Transferring())
Channels->SwitchTo(CurrentChannel->Number());
else
cDevice::SetCurrentChannel(CurrentChannel);
cDevice::SetCurrentChannel(CurrentChannel->Number());
}
}
channelsStateKey.Remove(Deleted);
@ -546,7 +547,7 @@ void cMenuChannels::Move(int From, int To)
if (!cDevice::PrimaryDevice()->Replaying() || cDevice::PrimaryDevice()->Transferring())
Channels->SwitchTo(CurrentChannel->Number());
else
cDevice::SetCurrentChannel(CurrentChannel);
cDevice::SetCurrentChannel(CurrentChannel->Number());
}
}
channelsStateKey.Remove();
@ -2686,14 +2687,15 @@ eOSState cMenuRecordingEdit::ApplyChanges(void)
cRecordings *Recordings = cRecordings::GetRecordingsWrite(StateKey);
cRecording *Recording = Recordings->GetByName(recording->FileName());
if (!Recording) {
StateKey.Remove(false);
Skins.Message(mtWarning, tr("Recording vanished!"));
return osBack;
}
bool Modified = false;
if (priority != recording->Priority() || lifetime != recording->Lifetime()) {
if (!Recording->ChangePriorityLifetime(priority, lifetime)) {
Skins.Message(mtError, tr("Error while changing priority/lifetime!"));
StateKey.Remove(Modified);
Skins.Message(mtError, tr("Error while changing priority/lifetime!"));
return osContinue;
}
Modified = true;
@ -2706,8 +2708,8 @@ eOSState cMenuRecordingEdit::ApplyChanges(void)
NewName.CompactChars(FOLDERDELIMCHAR);
if (strcmp(NewName, Recording->Name())) {
if (!Recording->ChangeName(NewName)) {
Skins.Message(mtError, tr("Error while changing folder/name!"));
StateKey.Remove(Modified);
Skins.Message(mtError, tr("Error while changing folder/name!"));
return osContinue;
}
Modified = true;
@ -2953,10 +2955,9 @@ void cMenuRecordings::Set(bool Refresh)
const char *CurrentRecording = *fileName ? *fileName : cReplayControl::LastReplayed();
cRecordings *Recordings = cRecordings::GetRecordingsWrite(recordingsStateKey); // write access is necessary for sorting!
cMenuRecordingItem *LastItem = NULL;
if (Refresh) {
if (cMenuRecordingItem *ri = (cMenuRecordingItem *)Get(Current()))
CurrentRecording = ri->Recording()->FileName();
}
if (cMenuRecordingItem *ri = (cMenuRecordingItem *)Get(Current()))
CurrentRecording = ri->Recording()->FileName();
int current = Current();
Clear();
GetRecordingsSortMode(DirectoryName());
Recordings->Sort();
@ -2993,11 +2994,13 @@ void cMenuRecordings::Set(bool Refresh)
LastDir->IncrementCounter(Recording->IsNew());
}
}
if (Current() < 0)
SetCurrent(Get(current)); // last resort, in case the recording was deleted
SetMenuSortMode(RecordingsSortMode == rsmName ? msmName : msmTime);
recordingsStateKey.Remove(false); // sorting doesn't count as a real modification
if (Refresh)
Display();
}
if (Refresh)
Display();
}
void cMenuRecordings::SetPath(const char *Path)
@ -3087,38 +3090,32 @@ eOSState cMenuRecordings::Delete(void)
else
return osContinue;
}
cRecordings *Recordings = cRecordings::GetRecordingsWrite(recordingsStateKey);
Recordings->SetExplicitModify();
cRecording *Recording = Recordings->GetByName(ri->Recording()->FileName());
if (!Recording) {
Skins.Message(mtWarning, tr("Recording vanished!"));
recordingsStateKey.Remove();
return osContinue;
}
cString FileName = Recording->FileName();
if (RecordingsHandler.GetUsage(FileName)) {
if (Interface->Confirm(tr("Recording is being edited - really delete?"))) {
RecordingsHandler.Del(FileName);
Recording = Recordings->GetByName(FileName); // RecordingsHandler.Del() might have deleted it if it was the edited version
// we continue with the code below even if Recording is NULL,
// in order to have the menu updated etc.
}
else {
recordingsStateKey.Remove();
return osContinue;
}
}
cString FileName;
{
LOCK_RECORDINGS_READ;
if (const cRecording *Recording = Recordings->GetByName(ri->Recording()->FileName())) {
FileName = Recording->FileName();
if (RecordingsHandler.GetUsage(FileName)) {
if (!Interface->Confirm(tr("Recording is being edited - really delete?")))
return osContinue;
}
}
}
RecordingsHandler.Del(FileName); // must do this w/o holding a lock, because the cleanup section in cDirCopier::Action() might request one!
if (cReplayControl::NowReplaying() && strcmp(cReplayControl::NowReplaying(), FileName) == 0)
cControl::Shutdown();
cRecordings *Recordings = cRecordings::GetRecordingsWrite(recordingsStateKey);
Recordings->SetExplicitModify();
cRecording *Recording = Recordings->GetByName(FileName);
if (!Recording || Recording->Delete()) {
cReplayControl::ClearLastReplayed(FileName);
Recordings->DelByName(FileName);
cOsdMenu::Del(Current());
SetHelpKeys();
cVideoDiskUsage::ForceCheck();
Display();
Recordings->SetModified();
recordingsStateKey.Remove();
Display();
if (!Count())
return osBack;
return osUser2;
@ -3171,8 +3168,6 @@ eOSState cMenuRecordings::Sort(void)
eOSState cMenuRecordings::ProcessKey(eKeys Key)
{
if (!HasSubMenu())
Set(); // react on any changes to the recordings list
bool HadSubMenu = HasSubMenu();
eOSState state = cOsdMenu::ProcessKey(Key);
@ -3198,7 +3193,8 @@ eOSState cMenuRecordings::ProcessKey(eKeys Key)
return state; // closes all recording menus except for the top one
Set(); // this is the top level menu, so we refresh it...
Open(true); // ...and open any necessary submenus to show the new name
Display();
if (!HasSubMenu())
Display();
path = NULL;
fileName = NULL;
}
@ -3210,14 +3206,16 @@ eOSState cMenuRecordings::ProcessKey(eKeys Key)
ri->SetRecording(riSub->Recording());
}
}
if (Key == kYellow && HadSubMenu && !HasSubMenu()) {
// the last recording in a subdirectory was deleted, so let's go back up
cOsdMenu::Del(Current());
if (!Count())
return osBack;
Display();
}
if (!HasSubMenu()) {
if (HadSubMenu) {
if (Key == kYellow) {
// the last recording in a subdirectory was deleted, so let's go back up
cOsdMenu::Del(Current());
if (!Count())
return osBack;
}
}
Set(true);
if (Key != kNone)
SetHelpKeys();
}
@ -5437,6 +5435,7 @@ cReplayControl::cReplayControl(bool PauseLive)
lastPlay = lastForward = false;
lastSpeed = -2; // an invalid value
timeoutShow = 0;
lastProgressUpdate = 0;
timeSearchActive = false;
cRecording Recording(fileName);
cStatus::MsgReplaying(this, Recording.Name(), Recording.FileName(), true);
@ -5585,41 +5584,43 @@ void cReplayControl::ShowMode(void)
bool cReplayControl::ShowProgress(bool Initial)
{
int Current, Total;
if (GetIndex(Current, Total) && Total > 0) {
if (!visible) {
displayReplay = Skins.Current()->DisplayReplay(modeOnly);
displayReplay->SetMarks(&marks);
SetNeedsFastResponse(true);
visible = true;
}
if (Initial) {
if (*fileName) {
LOCK_RECORDINGS_READ;
if (const cRecording *Recording = Recordings->GetByName(fileName))
displayReplay->SetRecording(Recording);
if (Initial || time(NULL) - lastProgressUpdate >= 1) {
if (GetFrameNumber(Current, Total) && Total > 0) {
if (!visible) {
displayReplay = Skins.Current()->DisplayReplay(modeOnly);
displayReplay->SetMarks(&marks);
SetNeedsFastResponse(true);
visible = true;
}
lastCurrent = lastTotal = -1;
}
if (Current != lastCurrent || Total != lastTotal) {
if (Setup.ShowRemainingTime || Total != lastTotal) {
int Index = Total;
if (Setup.ShowRemainingTime)
Index = Current - Index;
displayReplay->SetTotal(IndexToHMSF(Index, false, FramesPerSecond()));
if (Initial) {
if (*fileName) {
LOCK_RECORDINGS_READ;
if (const cRecording *Recording = Recordings->GetByName(fileName))
displayReplay->SetRecording(Recording);
}
lastCurrent = lastTotal = -1;
}
if (Current != lastCurrent || Total != lastTotal) {
time(&lastProgressUpdate);
if (Setup.ShowRemainingTime || Total != lastTotal) {
int Index = Total;
if (Setup.ShowRemainingTime)
Index = Current - Index;
displayReplay->SetTotal(IndexToHMSF(Index, false, FramesPerSecond()));
if (!Initial)
displayReplay->Flush();
}
displayReplay->SetProgress(Current, Total);
if (!Initial)
displayReplay->Flush();
}
displayReplay->SetProgress(Current, Total);
if (!Initial)
displayReplay->SetCurrent(IndexToHMSF(Current, displayFrames, FramesPerSecond()));
displayReplay->Flush();
displayReplay->SetCurrent(IndexToHMSF(Current, displayFrames, FramesPerSecond()));
displayReplay->Flush();
lastCurrent = Current;
lastCurrent = Current;
}
lastTotal = Total;
ShowMode();
return true;
}
lastTotal = Total;
ShowMode();
return true;
}
return false;
}
@ -5860,6 +5861,8 @@ eOSState cReplayControl::ProcessKey(eKeys Key)
return osEnd;
if (Key == kNone && !marksModified)
marks.Update();
if (Key != kNone)
lastProgressUpdate = 0;
if (visible) {
if (timeoutShow && time(NULL) > timeoutShow) {
Hide();

3
menu.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: menu.h 4.4 2015/09/13 14:17:56 kls Exp $
* $Id: menu.h 4.5 2016/12/22 10:55:36 kls Exp $
*/
#ifndef __MENU_H
@ -300,6 +300,7 @@ private:
bool lastPlay, lastForward;
int lastSpeed;
time_t timeoutShow;
time_t lastProgressUpdate;
bool timeSearchActive, timeSearchHide;
int timeSearchTime, timeSearchPos;
void TimeSearchDisplay(void);

16
nit.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: nit.c 4.3 2015/07/26 09:24:36 kls Exp $
* $Id: nit.c 4.4 2016/12/23 14:16:59 kls Exp $
*/
#include "nit.h"
@ -114,7 +114,7 @@ void cNitFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length
static int RollOffs[] = { ROLLOFF_35, ROLLOFF_25, ROLLOFF_20, ROLLOFF_AUTO };
dtp.SetRollOff(sd->getModulationSystem() ? RollOffs[sd->getRollOff()] : ROLLOFF_AUTO);
int SymbolRate = BCD2INT(sd->getSymbolRate()) / 10;
dbgnit(" %s %d %c %d %d\n", *cSource::ToString(Source), Frequency, Polarizations[sd->getPolarization()], SymbolRate, cChannel::Transponder(Frequency, Polarizations[sd->getPolarization()]));
dbgnit(" %s %d %c %d %d\n", *cSource::ToString(Source), Frequency, dtp.Polarization(), SymbolRate, cChannel::Transponder(Frequency, dtp.Polarization()));
if (Setup.UpdateChannels >= 5) {
bool found = false;
bool forceTransponderUpdate = false;
@ -177,7 +177,7 @@ void cNitFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length
static int Modulations[] = { QPSK, QAM_16, QAM_32, QAM_64, QAM_128, QAM_256, QAM_AUTO };
dtp.SetModulation(Modulations[min(sd->getModulation(), 6)]);
int SymbolRate = BCD2INT(sd->getSymbolRate()) / 10;
dbgnit(" %s %d %d %d %d\n", *cSource::ToString(Source), Frequency, CodeRates[sd->getFecInner()], Modulations[min(sd->getModulation(), 6)], SymbolRate);
dbgnit(" %s %d %d %d %d\n", *cSource::ToString(Source), Frequency, dtp.CoderateH(), dtp.Modulation(), SymbolRate);
if (Setup.UpdateChannels >= 5) {
bool found = false;
bool forceTransponderUpdate = false;
@ -233,7 +233,7 @@ void cNitFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length
dtp.SetGuard(GuardIntervals[sd->getGuardInterval()]);
static int TransmissionModes[] = { TRANSMISSION_MODE_2K, TRANSMISSION_MODE_8K, TRANSMISSION_MODE_4K, TRANSMISSION_MODE_AUTO };
dtp.SetTransmission(TransmissionModes[sd->getTransmissionMode()]);
dbgnit(" %s %d %d %d %d %d %d %d %d\n", *cSource::ToString(Source), Frequency, Bandwidths[sd->getBandwidth()], Constellations[sd->getConstellation()], Hierarchies[sd->getHierarchy()], CodeRates[sd->getCodeRateHP()], CodeRates[sd->getCodeRateLP()], GuardIntervals[sd->getGuardInterval()], TransmissionModes[sd->getTransmissionMode()]);
dbgnit(" %s %d %d %d %d %d %d %d %d\n", *cSource::ToString(Source), Frequency, dtp.Bandwidth(), dtp.Modulation(), dtp.Hierarchy(), dtp.CoderateH(), dtp.CoderateL(), dtp.Guard(), dtp.Transmission());
if (Setup.UpdateChannels >= 5) {
bool found = false;
bool forceTransponderUpdate = false;
@ -310,9 +310,9 @@ void cNitFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length
SI::LogicalChannelDescriptor *lcd = (SI::LogicalChannelDescriptor *)d;
SI::LogicalChannelDescriptor::LogicalChannel LogicalChannel;
for (SI::Loop::Iterator it4; lcd->logicalChannelLoop.getNext(LogicalChannel, it4); ) {
int lcn = LogicalChannel.getLogicalChannelNumber();
int sid = LogicalChannel.getServiceId();
if (LogicalChannel.getVisibleServiceFlag()) {
int lcn = LogicalChannel.getLogicalChannelNumber();
int sid = LogicalChannel.getServiceId();
for (cChannel *Channel = Channels->First(); Channel; Channel = Channels->Next(Channel)) {
if (!Channel->GroupSep() && Channel->Sid() == sid && Channel->Nid() == ts.getOriginalNetworkId() && Channel->Tid() == ts.getTransportStreamId()) {
ChannelsModified |= Channel->SetLcn(lcn);
@ -328,9 +328,9 @@ void cNitFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length
SI::HdSimulcastLogicalChannelDescriptor *lcd = (SI::HdSimulcastLogicalChannelDescriptor *)d;
SI::HdSimulcastLogicalChannelDescriptor::HdSimulcastLogicalChannel HdSimulcastLogicalChannel;
for (SI::Loop::Iterator it4; lcd->hdSimulcastLogicalChannelLoop.getNext(HdSimulcastLogicalChannel, it4); ) {
int lcn = HdSimulcastLogicalChannel.getLogicalChannelNumber();
int sid = HdSimulcastLogicalChannel.getServiceId();
if (HdSimulcastLogicalChannel.getVisibleServiceFlag()) {
int lcn = HdSimulcastLogicalChannel.getLogicalChannelNumber();
int sid = HdSimulcastLogicalChannel.getServiceId();
for (cChannel *Channel = Channels->First(); Channel; Channel = Channels->Next(Channel)) {
if (!Channel->GroupSep() && Channel->Sid() == sid && Channel->Nid() == ts.getOriginalNetworkId() && Channel->Tid() == ts.getTransportStreamId()) {
ChannelsModified |= Channel->SetLcn(lcn);

52
pat.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: pat.c 4.1 2015/08/17 08:46:55 kls Exp $
* $Id: pat.c 4.3 2016/12/23 14:02:07 kls Exp $
*/
#include "pat.h"
@ -81,7 +81,7 @@ public:
bool Is(cCaDescriptors * CaDescriptors);
bool Empty(void) { return caDescriptors.Count() == 0; }
void AddCaDescriptor(SI::CaDescriptor *d, int EsPid);
int GetCaDescriptors(const int *CaSystemIds, int BufSize, uchar *Data, int EsPid);
void GetCaDescriptors(const int *CaSystemIds, cDynamicBuffer &Buffer, int EsPid);
int GetCaPids(const int *CaSystemIds, int BufSize, int *Pids);
const int GetPmtPid(void) { return pmtPid; };
const int *CaIds(void) { return caIds; }
@ -159,30 +159,20 @@ void cCaDescriptors::AddCaDescriptor(SI::CaDescriptor *d, int EsPid)
// =0 - common CaDescriptor
// <0 - all CaDescriptors regardless of type (old default)
int cCaDescriptors::GetCaDescriptors(const int *CaSystemIds, int BufSize, uchar *Data, int EsPid)
void cCaDescriptors::GetCaDescriptors(const int *CaSystemIds, cDynamicBuffer &Buffer, int EsPid)
{
Buffer.Clear();
if (!CaSystemIds || !*CaSystemIds)
return 0;
if (BufSize > 0 && Data) {
int length = 0;
for (cCaDescriptor *d = caDescriptors.First(); d; d = caDescriptors.Next(d)) {
if (EsPid < 0 || d->EsPid() == EsPid) {
const int *caids = CaSystemIds;
do {
if (*caids == 0xFFFF || d->CaSystem() == *caids) {
if (length + d->Length() <= BufSize) {
memcpy(Data + length, d->Data(), d->Length());
length += d->Length();
}
else
return -1;
}
} while (*++caids);
}
return;
for (cCaDescriptor *d = caDescriptors.First(); d; d = caDescriptors.Next(d)) {
if (EsPid < 0 || d->EsPid() == EsPid) {
const int *caids = CaSystemIds;
do {
if (*caids == 0xFFFF || d->CaSystem() == *caids)
Buffer.Append(d->Data(), d->Length());
} while (*++caids);
}
return length;
}
return -1;
}
}
int cCaDescriptors::GetCaPids(const int *CaSystemIds, int BufSize, int *Pids)
@ -219,7 +209,7 @@ public:
// Returns 0 if this is an already known descriptor,
// 1 if it is an all new descriptor with actual contents,
// and 2 if an existing descriptor was changed.
int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, int EsPid);
void GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, cDynamicBuffer &Buffer, int EsPid);
int GetCaPids(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, int *Pids);
int GetPmtPid(int Source, int Transponder, int ServiceId);
};
@ -242,14 +232,15 @@ int cCaDescriptorHandler::AddCaDescriptors(cCaDescriptors *CaDescriptors)
return CaDescriptors->Empty() ? 0 : 1;
}
int cCaDescriptorHandler::GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, int EsPid)
void cCaDescriptorHandler::GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, cDynamicBuffer &Buffer, int EsPid)
{
cMutexLock MutexLock(&mutex);
for (cCaDescriptors *ca = First(); ca; ca = Next(ca)) {
if (ca->Is(Source, Transponder, ServiceId))
return ca->GetCaDescriptors(CaSystemIds, BufSize, Data, EsPid);
if (ca->Is(Source, Transponder, ServiceId)) {
ca->GetCaDescriptors(CaSystemIds, Buffer, EsPid);
break;
}
}
return 0;
}
int cCaDescriptorHandler::GetCaPids(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, int *Pids)
@ -274,9 +265,9 @@ int cCaDescriptorHandler::GetPmtPid(int Source, int Transponder, int ServiceId)
cCaDescriptorHandler CaDescriptorHandler;
int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, int EsPid)
void GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, cDynamicBuffer &Buffer, int EsPid)
{
return CaDescriptorHandler.GetCaDescriptors(Source, Transponder, ServiceId, CaSystemIds, BufSize, Data, EsPid);
CaDescriptorHandler.GetCaDescriptors(Source, Transponder, ServiceId, CaSystemIds, Buffer, EsPid);
}
int GetCaPids(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, int *Pids)
@ -439,6 +430,7 @@ void cPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length
case 1: // STREAMTYPE_11172_VIDEO
case 2: // STREAMTYPE_13818_VIDEO
case 0x1B: // H.264
case 0x24: // H.265
Vpid = esPid;
Ppid = pmt.getPCRPid();
Vtype = stream.getStreamType();

8
pat.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: pat.h 4.0 2015/01/04 13:17:22 kls Exp $
* $Id: pat.h 4.1 2016/12/23 14:03:24 kls Exp $
*/
#ifndef __PAT_H
@ -38,14 +38,12 @@ public:
void Trigger(int Sid = -1);
};
int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, int EsPid);
void GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, cDynamicBuffer &Buffer, int EsPid);
///< Gets all CA descriptors for a given channel.
///< Copies all available CA descriptors for the given Source, Transponder and ServiceId
///< into the provided buffer at Data (at most BufSize bytes). Only those CA descriptors
///< into the provided buffer. Only those CA descriptors
///< are copied that match one of the given CA system IDs (or all of them, if CaSystemIds
///< is 0xFFFF).
///< Returns the number of bytes copied into Data (0 if no CA descriptors are
///< available), or -1 if BufSize was too small to hold all CA descriptors.
int GetCaPids(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, int *Pids);
///< Gets all CA pids for a given channel.

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: player.h 4.0 2013/12/25 13:25:02 kls Exp $
* $Id: player.h 4.2 2016/12/22 10:38:11 kls Exp $
*/
#ifndef __PLAYER_H
@ -57,6 +57,10 @@ public:
virtual bool GetIndex(int &Current, int &Total, bool SnapToIFrame = false) { return false; }
// Returns the current and total frame index, optionally snapped to the
// nearest I-frame.
virtual bool GetFrameNumber(int &Current, int &Total) { return false; }
// Returns the current and total frame number. In contrast to GetIndex(),
// this function respects the chronological order of frames, which is
// different from its index for streams containing B frames (e.g. H264)
virtual bool GetReplayMode(bool &Play, bool &Forward, int &Speed) { return false; }
// Returns the current replay mode (if applicable).
// 'Play' tells whether we are playing or pausing, 'Forward' tells whether
@ -98,9 +102,10 @@ public:
///< skins as a last resort, in case they want to display the state of the
///< current player. The return value is expected to be a short, single line
///< string. The default implementation returns an empty string.
double FramesPerSecond(void) { return player->FramesPerSecond(); }
bool GetIndex(int &Current, int &Total, bool SnapToIFrame = false) { return player->GetIndex(Current, Total, SnapToIFrame); }
bool GetReplayMode(bool &Play, bool &Forward, int &Speed) { return player->GetReplayMode(Play, Forward, Speed); }
double FramesPerSecond(void) const { return player->FramesPerSecond(); }
bool GetIndex(int &Current, int &Total, bool SnapToIFrame = false) const { return player->GetIndex(Current, Total, SnapToIFrame); }
bool GetFrameNumber(int &Current, int &Total) const { return player->GetFrameNumber(Current, Total); }
bool GetReplayMode(bool &Play, bool &Forward, int &Speed) const { return player->GetReplayMode(Play, Forward, Speed); }
static void Launch(cControl *Control);
static void Attach(void);
static void Shutdown(void);

View File

@ -68,7 +68,7 @@ msgid "Transmission"
msgstr "Transmissioon"
msgid "Guard"
msgstr "Kaitseintervall"
msgstr "Kaitsevahemik"
msgid "Hierarchy"
msgstr "Hierarhia"
@ -326,7 +326,7 @@ msgid "Content$Unpublished"
msgstr "Avaldamata"
msgid "Content$Live Broadcast"
msgstr "Otseülekanne"
msgstr "Telepilt"
#, c-format
msgid "ParentalRating$from %d"
@ -477,7 +477,7 @@ msgid "Key$Subtitles"
msgstr "Subtiitrid"
msgid "Key$Schedule"
msgstr "Kava"
msgstr "Ajakava"
msgid "Key$Channels"
msgstr "Kanalid"
@ -486,10 +486,10 @@ msgid "Key$Timers"
msgstr "Taimerid"
msgid "Key$Recordings"
msgstr "Salvestused"
msgstr "Salvestised"
msgid "Key$Setup"
msgstr "Sätted"
msgstr "Seadistamine"
msgid "Key$Commands"
msgstr "Käsud"
@ -528,7 +528,7 @@ msgid "Free To Air"
msgstr "FTA"
msgid "encrypted"
msgstr "krüptitud"
msgstr "kodeeritud"
msgid "Edit channel"
msgstr "Kanali muutmine"
@ -588,16 +588,16 @@ msgid "Channels"
msgstr "Kanalid"
msgid "Button$Edit"
msgstr "Muutmine"
msgstr "Muuda"
msgid "Button$New"
msgstr "Uus"
msgid "Button$Delete"
msgstr "Kustutada"
msgstr "Kustuta"
msgid "Button$Mark"
msgstr "Märkimine"
msgstr "Märgi"
msgid "Channel is being used by a timer!"
msgstr "Kanal on taimeris kasutusel!"
@ -606,7 +606,7 @@ msgid "Delete channel?"
msgstr "Kustutada kanal?"
msgid "Edit folder"
msgstr "Kausta muutmine"
msgstr "Muuda kausta"
msgid "New folder"
msgstr "Uus kaust"
@ -622,7 +622,7 @@ msgid "Folder name must not contain '%c'!"
msgstr "Kausta nimi ei saa sisaldada '%c' sümbolit!"
msgid "Button$Open"
msgstr "Avada"
msgstr "Ava"
msgid "Delete folder and all sub folders?"
msgstr "Kustutada kaust ja kõik alamkaustad?"
@ -631,7 +631,7 @@ msgid "Delete folder?"
msgstr "Kustutada kaust?"
msgid "Edit timer"
msgstr "Taimeri redigeerimine"
msgstr "Muuda taimer"
msgid "Active"
msgstr "Aktiivne"
@ -661,13 +661,13 @@ msgid "File"
msgstr "Fail"
msgid "Record on"
msgstr ""
msgstr "Salvestamine"
msgid "Button$Folder"
msgstr "Kaust"
msgid "Button$Single"
msgstr "Üks kord"
msgstr "Üksik"
msgid "Button$Repeating"
msgstr "Korduv"
@ -676,13 +676,13 @@ msgid "First day"
msgstr "1. päev"
msgid "Error while accessing remote timer"
msgstr ""
msgstr "Kaugtaimeri viga"
msgid "Timer has been deleted!"
msgstr ""
msgstr "Taimer kustutatud"
msgid "Select folder"
msgstr "Kausta valik"
msgstr "Vali kaust"
msgid "Timers"
msgstr "Taimerid"
@ -700,38 +700,38 @@ msgid "Timer still recording - really delete?"
msgstr "Salvestus aktiivne - kas kustutada?"
msgid "Event"
msgstr "Saade"
msgstr "Saateinfo"
msgid "Button$Timer"
msgstr "Taimer"
msgid "Button$Record"
msgstr "Salvestada"
msgstr "Salvesta"
msgid "Button$Switch"
msgstr "Vali"
msgid "What's on now?"
msgstr "Hetkel eetris"
msgstr "Hetkel"
msgid "What's on next?"
msgstr "Järgmisena eetris"
msgstr "Järgmine"
msgid "Button$Next"
msgstr "Tulekul"
msgstr "Järgmine"
msgid "Button$Now"
msgstr "Hetkel"
msgid "Button$Schedule"
msgstr "Kava"
msgstr "Ajakava"
msgid "Can't switch channel!"
msgstr "Kanali vahetus ei ole võimalik!"
#, c-format
msgid "Schedule - %s"
msgstr "Kava - %s"
msgstr "Ajakava - %s"
#, c-format
msgid "This event - %s"
@ -761,55 +761,55 @@ msgstr "Kaust on juba kasutusel - muutmine ei ole võimalik!"
#, c-format
msgid "Move entire folder containing %d recordings?"
msgstr "Teisaldada kaust mis sisaldab %d salvestust?"
msgstr "Liigutada kaust mis sisaldab %d salvestist?"
msgid "Error while moving folder!"
msgstr "Kausta teisaldamise viga!"
msgstr "Kausta liigutamise viga!"
msgid "Edit recording"
msgstr "Salvestuse redigeerimine"
msgstr "Muuda salvestist"
msgid "This recording is currently in use - no changes are possible!"
msgstr "Salvestus hetkel kasutusel - muutmine ei ole võimalik!"
msgstr "Salvestis hetkel kasutusel - muutmine ei ole võimalik!"
msgid "Button$Cancel cutting"
msgstr "Lõikamise tühistamine"
msgstr "Tühista lõikamine"
msgid "Button$Stop cutting"
msgstr "Lõikamise peatamine"
msgstr "Peata lõikamine"
msgid "Button$Cancel moving"
msgstr "Teisaldamise tühistamine"
msgstr "Tühista liigutamine"
msgid "Button$Stop moving"
msgstr "Teisaldamise peatamine"
msgstr "Peata liigutamine"
msgid "Button$Cancel copying"
msgstr "Kopeerimise tühistamine"
msgstr "Tühista kopeerimine"
msgid "Button$Stop copying"
msgstr "Kopeerimise peatamine"
msgstr "Peata kopeerimine"
msgid "Button$Cut"
msgstr "Lõika"
msgid "Button$Delete marks"
msgstr "Markerite kustutamine"
msgstr "Kustuta markerid"
msgid "Recording vanished!"
msgstr "Salvestus kadunud!"
msgstr "Salvestis puudub!"
msgid "Edited version already exists - overwrite?"
msgstr "Redigeeritud versioon juba olemas - kirjutada üle?"
msgstr "Muudetud versioon juba olemas - kirjutada üle?"
msgid "Error while queueing recording for cutting!"
msgstr "Salvestuse lisamine lõikamiseks ebaõnnestus!"
msgstr "Salvestise lisamine lõikamiseks ebaõnnestus!"
msgid "Rename recording to folder name?"
msgstr "Nimetada salvestuse nimi kaustaks?"
msgstr "Ümbernimetada kaust salvestise nimega?"
msgid "Delete editing marks for this recording?"
msgstr "Kustutada selle salvestuse markerid?"
msgstr "Kustutada selle salvestise markerid?"
msgid "Error while deleting editing marks!"
msgstr "Markerite kustutamine ebaõnnestus!"
@ -821,55 +821,55 @@ msgid "Error while changing folder/name!"
msgstr "Kausta/nime muutmine ebaõnnestus!"
msgid "Recording info"
msgstr "Salvestuse info"
msgstr "Salvestise info"
msgid "Button$Play"
msgstr "Start"
msgid "Button$Rewind"
msgstr "Algusesse"
msgstr "Tagasikerimine"
msgid "Recordings"
msgstr "Salvestused"
msgstr "Salvestised"
msgid "Commands"
msgstr "Käsud"
msgid "Delete recording?"
msgstr "Kustutada salvestus?"
msgstr "Kustutada salvestis?"
msgid "Recording is being edited - really delete?"
msgstr "Salvestust on muudetud - kas kustutada?"
msgstr "Salvestist on muudetud - kas kustutada?"
msgid "Error while deleting recording!"
msgstr "Salvestuse kustutamine ebaõnnestus!"
msgstr "Salvestise kustutamine ebaõnnestus!"
msgid "Recording commands"
msgstr "Salvestuse käsud"
msgid "never"
msgstr "ealeski"
msgstr "mitte kunagi"
msgid "skin dependent"
msgstr "kestast sõltuv"
msgstr "kujundusest sõltuv"
msgid "always"
msgstr "alati"
msgid "by name"
msgstr ""
msgstr "nime järgi"
msgid "by time"
msgstr ""
msgstr "aja järgi"
msgid "OSD"
msgstr "Ekraanikuva"
msgstr "OSD"
msgid "Setup.OSD$Language"
msgstr "Keel"
msgid "Setup.OSD$Skin"
msgstr "Kest"
msgstr "Kujundus"
msgid "Setup.OSD$Theme"
msgstr "Teema"
@ -893,7 +893,7 @@ msgid "Setup.OSD$Use small font"
msgstr "Väikese fondi kasutus"
msgid "Setup.OSD$Anti-alias"
msgstr "Fondi sakitõrje"
msgstr "Fondi silumine"
msgid "Setup.OSD$Default font"
msgstr "Vaikefont"
@ -902,7 +902,7 @@ msgid "Setup.OSD$Small font"
msgstr "Väike font"
msgid "Setup.OSD$Fixed font"
msgstr "Fikseeritud font"
msgstr "Püsisammuga font"
msgid "Setup.OSD$Default font size (%)"
msgstr "Vaikefondi suurus (%)"
@ -911,7 +911,7 @@ msgid "Setup.OSD$Small font size (%)"
msgstr "Väikese fondi suurus (%)"
msgid "Setup.OSD$Fixed font size (%)"
msgstr "Fiks. fondi suurus (%)"
msgstr "Püsisammuga fondi suurus (%)"
msgid "Setup.OSD$Channel info position"
msgstr "Kanaliinfo asukoht"
@ -929,7 +929,7 @@ msgid "Setup.OSD$Info on channel switch"
msgstr "Kanaliinfo kuvamine"
msgid "Setup.OSD$Timeout requested channel info"
msgstr "Kanaliinfo ajapiirang"
msgstr "Kanaliinfo aegumine"
msgid "Setup.OSD$Scroll pages"
msgstr "Lehekülje kerimine"
@ -941,16 +941,16 @@ msgid "Setup.OSD$Menu key closes"
msgstr "Sulgemine Menüü klahviga"
msgid "Setup.OSD$Recording directories"
msgstr "Kausta nime salvestamine"
msgstr "Salvestise kaustade kuvamine"
msgid "Setup.OSD$Folders in timer menu"
msgstr "Kaustad taimeri menüüs"
msgstr "Kaustade kuvamine taimeri menüüs"
msgid "Setup.OSD$Always sort folders first"
msgstr "Sorteerida kaustad alati ette"
msgstr "Järjesta kaustad alati ette"
msgid "Setup.OSD$Default sort mode for recordings"
msgstr ""
msgstr "Salvestiste vaikimisi järjestus"
msgid "Setup.OSD$Number keys for characters"
msgstr "Teksti sisestamine numbriklahvidega"
@ -971,7 +971,7 @@ msgid "EPG"
msgstr "EPG"
msgid "Button$Scan"
msgstr "Uuendada"
msgstr "Uuenda"
msgid "Setup.EPG$EPG scan timeout (h)"
msgstr "EPG skaneerimise viide (h)"
@ -983,10 +983,10 @@ msgid "Setup.EPG$EPG linger time (min)"
msgstr "Vana EPG viide (min)"
msgid "Setup.EPG$Set system time"
msgstr "Kella sünkroniseerimine"
msgstr "Süsteemi aja sünkimine"
msgid "Setup.EPG$Use time from transponder"
msgstr "Sünkroniseerimise transponder"
msgstr "Sünkimise transponder"
#. TRANSLATORS: note the plural!
msgid "Setup.EPG$Preferred languages"
@ -1009,7 +1009,7 @@ msgid "no"
msgstr "ei"
msgid "names only"
msgstr "nimed"
msgstr "ainult nimed"
msgid "PIDs only"
msgstr "PID-id"
@ -1097,7 +1097,7 @@ msgid "Setup.LNB$own"
msgstr "oma"
msgid "Setup.LNB$Use dish positioner"
msgstr "Antenni positsioneerija kasutamine"
msgstr "Ajami kasutamine"
msgid "Setup.LNB$Site latitude (degrees)"
msgstr "Asukoha laiuskraad (°)"
@ -1118,32 +1118,32 @@ msgid "East"
msgstr "itta (E)"
msgid "Setup.LNB$Max. positioner swing (degrees)"
msgstr "Positsioneerija pöördeulatus (°)"
msgstr "Ajami pöördeulatus (°)"
msgid "Setup.LNB$Positioner speed (degrees/s)"
msgstr "Positsioneerija kiirus (°/s)"
msgstr "Ajami kiirus (°/s)"
msgid "CAM reset"
msgstr "CAM taaskäivitamine"
msgid "CAM present"
msgstr "CAM esitletud"
msgstr "CAM saadaval"
msgid "CAM ready"
msgstr "CAM töövalmis"
msgstr "CAM valmis"
#. TRANSLATORS: note the leading blank!
msgid " (activating)"
msgstr " (aktiveerimine)"
msgid "@ device"
msgstr ""
msgstr "@ seade"
msgid "CAM"
msgstr "CAM"
msgid "Button$Cancel activation"
msgstr "Aktiveerimise tühistamine"
msgstr "Tühista aktiveerimine"
msgid "Button$Activate"
msgstr "Aktiveeri"
@ -1152,7 +1152,7 @@ msgid "Button$Menu"
msgstr "Menüü"
msgid "Button$Reset"
msgstr "Reset"
msgstr "Lähtesta"
msgid "Opening CAM menu..."
msgstr "CAM-menüü avamine..."
@ -1164,61 +1164,61 @@ msgid "Can't activate CAM!"
msgstr "Ei saa CAM'i aktiveerida!"
msgid "CAM is in use - really reset?"
msgstr "CAM on kasutuses - taaskäivitada?"
msgstr "CAM on kasutuses - lähtestada?"
msgid "Can't reset CAM!"
msgstr "CAM mooduli taaskäivitus ebaõnnestus!"
msgstr "CAM mooduli lähtestamine ebaõnnestus!"
msgid "no instant recording"
msgstr ""
msgstr "kohene salvestus puudub"
msgid "confirm instant recording"
msgstr ""
msgstr "kinnita kohene salvestus"
msgid "record instantly"
msgstr ""
msgstr "kohene salvestus"
msgid "do not pause live video"
msgstr "mitte peatada"
msgid "confirm pause live video"
msgstr "peatam. kinnitus"
msgstr "peatamise kinnitus"
msgid "pause live video"
msgstr "peatada"
msgstr "peata"
msgid "confirm"
msgstr "kinnitada"
msgstr "kinnita"
msgid "yes"
msgstr "jah"
msgid "Recording"
msgstr "Salvestamine"
msgstr "Salvestus"
msgid "Setup.Recording$Margin at start (min)"
msgstr "Salvestamise algusvaru (min)"
msgstr "Salvestuse algusvaru (min)"
msgid "Setup.Recording$Margin at stop (min)"
msgstr "Salvestamise lõpuvaru (min)"
msgstr "Salvestuse lõpuvaru (min)"
msgid "Setup.Recording$Default priority"
msgstr "Vaikimisi prioriteet"
msgid "Setup.Recording$Default lifetime (d)"
msgstr "Salvestuse eluiga (päevi)"
msgstr "Salvestuse eluiga (päevad)"
msgid "Setup.Recording$Record key handling"
msgstr ""
msgstr "Salvestuse klahvi käsitlus"
msgid "Setup.Recording$Pause key handling"
msgstr "Pausi klahvi käsitlemine"
msgstr "Pausi klahvi käsitlus"
msgid "Setup.Recording$Pause priority"
msgstr "Pausi prioriteet"
msgid "Setup.Recording$Pause lifetime (d)"
msgstr "Pausi eluiga (päevi)"
msgstr "Pausi eluiga (päevad)"
msgid "Setup.Recording$Use episode name"
msgstr "Episoodinime kasutamine"
@ -1230,37 +1230,37 @@ msgid "Setup.Recording$VPS margin (s)"
msgstr "VPS-i algusvaru (s)"
msgid "Setup.Recording$Mark instant recording"
msgstr "Kiirsalvestuse märgistamine"
msgstr "Kohese salvestuse märgistamine"
msgid "Setup.Recording$Name instant recording"
msgstr "Kiirsalvestuse nimi"
msgstr "Kohese salvestuse nimi"
msgid "Setup.Recording$Instant rec. time (min)"
msgstr "Kiirsalvestuse kestus (min)"
msgstr "Kohese salvestuse kestus (min)"
msgid "Setup.Recording$present event"
msgstr "hetkesündmus"
msgstr "käesolev saade"
msgid "Setup.Recording$Max. video file size (MB)"
msgstr "Maks. failisuurus (MB)"
msgid "Setup.Recording$Split edited files"
msgstr "Redigeeritud failide tükeldamine"
msgstr "Tükelda muudetud faile"
msgid "Setup.Recording$Delete timeshift recording"
msgstr "Ajanihke salvestuse kustutamine"
msgstr "Kustuta ajanihke salvestisi"
msgid "Replay"
msgstr "Taasesitus"
msgid "Setup.Replay$Multi speed mode"
msgstr "Mitmikkiiruse režiim"
msgstr "Mitme kiiruse režiim"
msgid "Setup.Replay$Show replay mode"
msgstr "Korduse režiimi kuvamine"
msgid "Setup.Replay$Show remaining time"
msgstr "Järelejäänud aja kuvamine"
msgstr "Kuva jäänud aega"
msgid "Setup.Replay$Progress display time (s)"
msgstr "Edenemiseriba kuvamise aeg (s)"
@ -1272,7 +1272,7 @@ msgid "Setup.Replay$Pause replay when jumping to a mark"
msgstr "Paus markerile siirdamisel"
msgid "Setup.Replay$Skip edited parts"
msgstr "Redigeeritud osade vahelejätmine"
msgstr "Markeeritud osade vahelejätmine"
msgid "Setup.Replay$Pause replay at last mark"
msgstr "Paus viimasel markeril"
@ -1281,7 +1281,7 @@ msgid "Setup.Replay$Initial duration for adaptive skipping (s)"
msgstr "Adaptiivse hüppe pikkuse algväärtus (s)"
msgid "Setup.Replay$Reset timeout for adaptive skipping (s)"
msgstr "Adaptiivse hüppe lähtestamise viide (s)"
msgstr "Adaptiivse hüppe lähtestamise aegumine (s)"
msgid "Setup.Replay$Alternate behavior for adaptive skipping"
msgstr "Adaptiivse hüppe vaheldumise omadus"
@ -1299,31 +1299,31 @@ msgid "Setup.Replay$Resume ID"
msgstr "Taasesituse tunnus"
msgid "Miscellaneous"
msgstr "Muud sätted"
msgstr "Muud seaded"
msgid "Setup.Miscellaneous$Min. event timeout (min)"
msgstr "Min. aeg saateni (min)"
msgstr "Minimaalne aeg saateni (min)"
msgid "Setup.Miscellaneous$Min. user inactivity (min)"
msgstr "Min. kasutaja tegevusetus (min)"
msgstr "Minimaalne kasutaja jõudeolek (min)"
msgid "Setup.Miscellaneous$SVDRP timeout (s)"
msgstr "SVDRP ooteaeg (s)"
msgstr "SVDRP aegumine (s)"
msgid "Setup.Miscellaneous$SVDRP peering"
msgstr ""
msgstr "SVDRP partnerlus"
msgid "Setup.Miscellaneous$SVDRP host name"
msgstr ""
msgstr "SVDRP hostinimi"
msgid "Setup.Miscellaneous$SVDRP default host"
msgstr ""
msgstr "SVDRP vaikehost"
msgid "Setup.Miscellaneous$Zap timeout (s)"
msgstr "Kanalivahetuse ooteaeg (s)"
msgstr "Kanalivahetuse aegumine (s)"
msgid "Setup.Miscellaneous$Channel entry timeout (ms)"
msgstr "Kanali sisestamise ajalimiit (ms)"
msgstr "Kanali sisestamise aegumine (ms)"
msgid "Setup.Miscellaneous$Remote control repeat delay (ms)"
msgstr "Kaugjuhtimispuldi kordamise viide (ms)"
@ -1356,30 +1356,30 @@ msgid "Setup.Miscellaneous$Emergency exit"
msgstr "Hädaväljumine"
msgid "Plugins"
msgstr "Laiendusmoodulid"
msgstr "Pluginad"
msgid "This plugin has no setup parameters!"
msgstr "Sellel laienudusmoodulil ei ole seadeid!"
msgstr "Sellel pluginal seaded puuduvad!"
msgid "Setup"
msgstr "Sätted"
msgstr "Seaded"
msgid "Restart"
msgstr "Restart"
msgstr "Taaskäivita"
msgid "Really restart?"
msgstr "Restart?"
msgstr "Taaskäivitada?"
#. TRANSLATORS: note the leading and trailing blanks!
msgid " Stop recording "
msgstr " Lõpetada salvestamine "
msgstr " Lõpeta salvestamine "
msgid "Schedule"
msgstr "Kava"
msgstr "Ajakava"
#. TRANSLATORS: note the leading blank!
msgid " Stop replaying"
msgstr " Lõpetada taasesitus"
msgstr " Lõpeta taasesitus"
msgid "Button$Pause"
msgstr "Paus"
@ -1392,7 +1392,7 @@ msgstr "Jätkamine"
#. TRANSLATORS: note the leading blank!
msgid " Cancel editing"
msgstr " Tühistada töötlemine"
msgstr " Tühista töötlemine"
msgid "Stop recording?"
msgstr "Lõpetada salvestamine?"
@ -1416,7 +1416,7 @@ msgid "No free DVB device to record!"
msgstr "Puudub vaba DVB seade salvestamiseks!"
msgid "Pausing live video..."
msgstr "Otseedastuse peatamine..."
msgstr "Telepildi peatamine..."
msgid "Delete timeshift recording?"
msgstr "Kustutada ajanihke salvestust?"
@ -1426,19 +1426,19 @@ msgid "Jump: "
msgstr "Hüpe: "
msgid "No editing marks defined!"
msgstr "Redigeerimise markerid puuduvad!"
msgstr "Muutmise markerid puuduvad!"
msgid "No editing sequences defined!"
msgstr "Redigeerimise järjestus määramata!"
msgstr "Muutmise järjestus määramata!"
msgid "Can't start editing process!"
msgstr "Redigeerimise start ebaõnnestus!"
msgstr "Muutmise start ebaõnnestus!"
msgid "Editing process started"
msgstr "Redigeerimine käivitatud"
msgstr "Töötlemine käivitatud"
msgid "Editing process already active!"
msgstr "Redigeerimine juba aktiivne!"
msgstr "Töötlemine juba aktiivne!"
msgid "FileNameChars$ abcdefghijklmnopqrstuvwxyz0123456789-.,#~\\^$[]|()*+?{}/:%@&"
msgstr " abcdefghijklmnopqrsšzžtuvwõäöüxy0123456789-.,#~\\^$[]|()*+?{}/:%@&"
@ -1456,7 +1456,7 @@ msgid "Button$Insert"
msgstr "Lisa (INS)"
msgid "Plugin"
msgstr "Laiendusmoodul"
msgstr "Plugin"
msgid "Up/Dn for new location - OK to move"
msgstr "'Üles/Alla' uus asukoht - 'OK' kinnitus"
@ -1494,16 +1494,16 @@ msgstr "lülitada välja?"
#, c-format
msgid "Plugin %s wakes up in %ld min, continue?"
msgstr "Laiendusmoodul %s ärkab %ld minuti pärast, jätkata?"
msgstr "Plugin %s ärkab %ld minuti pärast, jätkata?"
msgid "Editing - restart anyway?"
msgstr "Töötlemine aktiivne - restart?"
msgstr "Töötlemine aktiivne - taaskäivitada?"
msgid "Recording - restart anyway?"
msgstr "Salvestamine aktiivne - restart?"
msgstr "Salvestamine aktiivne - taaskäivitada ikkagi?"
msgid "restart anyway?"
msgstr "restart?"
msgstr "taaskäivitada ikkagi?"
#. TRANSLATORS: note the trailing blank!
msgid "Volume "
@ -1525,7 +1525,7 @@ msgid "DEVICES"
msgstr "SEADMED"
msgid "LIVE"
msgstr "LIVE"
msgstr "TELEPILT"
msgid "PLAY"
msgstr "ESITUS"
@ -1570,10 +1570,10 @@ msgid "Upcoming recording!"
msgstr "Salvestamine tulekul!"
msgid "Pause live video?"
msgstr "Peatada otseülekanne?"
msgstr "Peatada telepilt?"
msgid "Start recording?"
msgstr ""
msgstr "Käivitada salvestamine?"
msgid "Recording started"
msgstr "Salvestamine käivitatud"
@ -1594,7 +1594,7 @@ msgid "Editing process finished"
msgstr "Töötlemine lõpetatud"
msgid "Press any key to cancel restart"
msgstr "Restardi katkestamiseks vajuta suvalist klahvi"
msgstr "Taaskäivitamise katkestamiseks vajuta suvalist klahvi"
#, c-format
msgid "VDR will shut down in %s minutes"

View File

@ -12,7 +12,7 @@ msgstr ""
"Project-Id-Version: VDR 2.2.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2015-09-11 10:38+0200\n"
"PO-Revision-Date: 2015-02-12 19:31+0100\n"
"PO-Revision-Date: 2015-09-14 19:28+0100\n"
"Last-Translator: Diego Pierotto <vdr-italian@tiscali.it>\n"
"Language-Team: Italian <vdr@linuxtv.org>\n"
"Language: it\n"
@ -667,7 +667,7 @@ msgid "File"
msgstr "Nome"
msgid "Record on"
msgstr ""
msgstr "Registrazione avviata"
msgid "Button$Folder"
msgstr "Cartella"
@ -682,10 +682,10 @@ msgid "First day"
msgstr "1° giorno"
msgid "Error while accessing remote timer"
msgstr ""
msgstr "Errore durante l'accesso al timer remoto"
msgid "Timer has been deleted!"
msgstr ""
msgstr "Il timer è stata eliminato!"
msgid "Select folder"
msgstr "Seleziona cartella"
@ -863,10 +863,10 @@ msgid "always"
msgstr "sempre"
msgid "by name"
msgstr ""
msgstr "per nome"
msgid "by time"
msgstr ""
msgstr "per ora"
msgid "OSD"
msgstr "OSD"
@ -956,7 +956,7 @@ msgid "Setup.OSD$Always sort folders first"
msgstr "Ordina sempre per prima le cartelle"
msgid "Setup.OSD$Default sort mode for recordings"
msgstr ""
msgstr "Modalità ordinamento predefinito per registrazioni"
msgid "Setup.OSD$Number keys for characters"
msgstr "Tasti numerici per i caratteri"
@ -1143,7 +1143,7 @@ msgid " (activating)"
msgstr " (attivazione)"
msgid "@ device"
msgstr ""
msgstr "@ dispositivo"
msgid "CAM"
msgstr "Accesso condizionato CAM"
@ -1176,13 +1176,13 @@ msgid "Can't reset CAM!"
msgstr "Impossibile reimpostare il modulo CAM!"
msgid "no instant recording"
msgstr ""
msgstr "nessuna registrazione istantanea"
msgid "confirm instant recording"
msgstr ""
msgstr "conferma registrazione istantanea"
msgid "record instantly"
msgstr ""
msgstr "registra istantaneamente"
msgid "do not pause live video"
msgstr "non mettere in pausa il video dal vivo"
@ -1215,7 +1215,7 @@ msgid "Setup.Recording$Default lifetime (d)"
msgstr "Scadenza predefinita (gg)"
msgid "Setup.Recording$Record key handling"
msgstr ""
msgstr "Gestione chiave registrazione"
msgid "Setup.Recording$Pause key handling"
msgstr "Gestione tasto Pausa"
@ -1317,13 +1317,13 @@ msgid "Setup.Miscellaneous$SVDRP timeout (s)"
msgstr "Scadenza SVDRP (s)"
msgid "Setup.Miscellaneous$SVDRP peering"
msgstr ""
msgstr "Punto SVDRP"
msgid "Setup.Miscellaneous$SVDRP host name"
msgstr ""
msgstr "Nome sistema SVDRP"
msgid "Setup.Miscellaneous$SVDRP default host"
msgstr ""
msgstr "Sistema predefinito SVDRP"
msgid "Setup.Miscellaneous$Zap timeout (s)"
msgstr "Scadenza Zapping (s)"
@ -1579,7 +1579,7 @@ msgid "Pause live video?"
msgstr "Pausare video dal vivo?"
msgid "Start recording?"
msgstr ""
msgstr "Avviare registrazione?"
msgid "Recording started"
msgstr "Registrazione avviata"

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: receiver.c 4.0 2015/01/12 14:04:31 kls Exp $
* $Id: receiver.c 4.1 2015/09/16 11:19:47 kls Exp $
*/
#include "receiver.h"
@ -37,8 +37,10 @@ void cReceiver::SetPriority(int Priority)
bool cReceiver::AddPid(int Pid)
{
if (Pid) {
if (numPids < MAXRECEIVEPIDS)
pids[numPids++] = Pid;
if (numPids < MAXRECEIVEPIDS) {
if (!WantsPid(Pid))
pids[numPids++] = Pid;
}
else {
dsyslog("too many PIDs in cReceiver (Pid = %d)", Pid);
return false;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: recording.c 4.4 2015/09/09 10:21:58 kls Exp $
* $Id: recording.c 4.6 2016/12/22 12:58:20 kls Exp $
*/
#include "recording.h"
@ -1701,7 +1701,7 @@ void cDirCopier::Action(void)
int To = -1;
size_t BufferSize = BUFSIZ;
while (Running()) {
// Suspend cutting if we have severe throughput problems:
// Suspend copying if we have severe throughput problems:
if (Throttled()) {
cCondWait::SleepMs(100);
continue;
@ -1900,6 +1900,7 @@ bool cRecordingsHandlerEntry::Active(bool &Error)
cRecordingsHandler RecordingsHandler;
cRecordingsHandler::cRecordingsHandler(void)
:cThread("recordings handler")
{
finished = true;
error = false;
@ -1907,6 +1908,23 @@ cRecordingsHandler::cRecordingsHandler(void)
cRecordingsHandler::~cRecordingsHandler()
{
Cancel(3);
}
void cRecordingsHandler::Action(void)
{
while (Running()) {
{
cMutexLock MutexLock(&mutex);
while (cRecordingsHandlerEntry *r = operations.First()) {
if (!r->Active(error))
operations.Del(r);
}
if (!operations.Count())
break;
}
cCondWait::SleepMs(100);
}
}
cRecordingsHandlerEntry *cRecordingsHandler::Get(const char *FileName)
@ -1934,8 +1952,7 @@ bool cRecordingsHandler::Add(int Usage, const char *FileNameSrc, const char *Fil
Usage |= ruPending;
operations.Add(new cRecordingsHandlerEntry(Usage, FileNameSrc, FileNameDst));
finished = false;
Active(); // start it right away if possible
LOCK_RECORDINGS_WRITE; // to trigger a state change
Start();
return true;
}
else
@ -1955,17 +1972,17 @@ bool cRecordingsHandler::Add(int Usage, const char *FileNameSrc, const char *Fil
void cRecordingsHandler::Del(const char *FileName)
{
cMutexLock MutexLock(&mutex);
if (cRecordingsHandlerEntry *r = Get(FileName)) {
if (cRecordingsHandlerEntry *r = Get(FileName))
operations.Del(r);
LOCK_RECORDINGS_WRITE; // to trigger a state change
}
}
void cRecordingsHandler::DelAll(void)
{
cMutexLock MutexLock(&mutex);
operations.Clear();
LOCK_RECORDINGS_WRITE; // to trigger a state change
{
cMutexLock MutexLock(&mutex);
operations.Clear();
}
Cancel(3);
}
int cRecordingsHandler::GetUsage(const char *FileName)
@ -1976,18 +1993,6 @@ int cRecordingsHandler::GetUsage(const char *FileName)
return ruNone;
}
bool cRecordingsHandler::Active(void)
{
cMutexLock MutexLock(&mutex);
while (cRecordingsHandlerEntry *r = operations.First()) {
if (r->Active(error))
return true;
else
operations.Del(r);
}
return false;
}
bool cRecordingsHandler::Finished(bool &Error)
{
cMutexLock MutexLock(&mutex);
@ -2324,7 +2329,7 @@ void cIndexFileGenerator::Action(void)
Buffer.Del(Processed);
}
}
else if (PatPmtParser.Vpid()) {
else if (PatPmtParser.Completed()) {
// Step 2 - sync FrameDetector:
int Processed = FrameDetector.Analyze(Data, Length);
if (Processed > 0) {
@ -2346,9 +2351,9 @@ void cIndexFileGenerator::Action(void)
PatPmtParser.ParsePmt(p, TS_SIZE);
Length -= TS_SIZE;
p += TS_SIZE;
if (PatPmtParser.Vpid()) {
// Found Vpid, so rewind to sync FrameDetector:
FrameDetector.SetPid(PatPmtParser.Vpid(), PatPmtParser.Vtype());
if (PatPmtParser.Completed()) {
// Found pid, so rewind to sync FrameDetector:
FrameDetector.SetPid(PatPmtParser.Vpid() ? PatPmtParser.Vpid() : PatPmtParser.Apid(0), PatPmtParser.Vpid() ? PatPmtParser.Vtype() : PatPmtParser.Atype(0));
BufferChunks = IFG_BUFFER_SIZE;
Rewind = true;
break;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: recording.h 4.3 2015/08/29 14:12:14 kls Exp $
* $Id: recording.h 4.4 2016/12/13 13:12:12 kls Exp $
*/
#ifndef __RECORDING_H
@ -302,16 +302,18 @@ DEF_LIST_LOCK2(Recordings, DeletedRecordings);
class cRecordingsHandlerEntry;
class cRecordingsHandler {
class cRecordingsHandler : public cThread {
private:
cMutex mutex;
cList<cRecordingsHandlerEntry> operations;
bool finished;
bool error;
cRecordingsHandlerEntry *Get(const char *FileName);
protected:
virtual void Action(void);
public:
cRecordingsHandler(void);
~cRecordingsHandler();
virtual ~cRecordingsHandler();
bool Add(int Usage, const char *FileNameSrc, const char *FileNameDst = NULL);
///< Adds the given FileNameSrc to the recordings handler for (later)
///< processing. Usage can be either ruCut, ruMove or ruCopy. FileNameDst
@ -329,12 +331,6 @@ public:
///< Deletes/terminates all operations.
int GetUsage(const char *FileName);
///< Returns the usage type for the given FileName.
bool Active(void);
///< Checks whether there is currently any operation running and starts
///> the next one form the list if the previous one has finished.
///< This function must be called regularly to trigger switching to the
///< next operation in the list.
///< Returns true if there are any operations in the list.
bool Finished(bool &Error);
///< Returns true if all operations in the list have been finished.
///< If there have been any errors, Errors will be set to true.

92
remux.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: remux.c 4.1 2015/03/11 09:49:38 kls Exp $
* $Id: remux.c 4.3 2016/12/22 12:58:20 kls Exp $
*/
#include "remux.h"
@ -603,6 +603,7 @@ cPatPmtParser::cPatPmtParser(bool UpdatePrimaryDevice)
void cPatPmtParser::Reset(void)
{
completed = false;
pmtSize = 0;
patVersion = pmtVersion = -1;
pmtPids[0] = 0;
@ -708,6 +709,7 @@ void cPatPmtParser::ParsePmt(const uchar *Data, int Length)
case 0x01: // STREAMTYPE_11172_VIDEO
case 0x02: // STREAMTYPE_13818_VIDEO
case 0x1B: // H.264
case 0x24: // H.265
vpid = stream.getPid();
vtype = stream.getStreamType();
ppid = Pmt.getPCRPid();
@ -892,6 +894,7 @@ void cPatPmtParser::ParsePmt(const uchar *Data, int Length)
}
}
pmtVersion = Pmt.getVersionNumber();
completed = true;
}
else
esyslog("ERROR: can't parse PMT");
@ -1204,16 +1207,16 @@ private:
nutSequenceParameterSet = 7,
nutAccessUnitDelimiter = 9,
};
cTsPayload tsPayload;
uchar byte; // holds the current byte value in case of bitwise access
int bit; // the bit index into the current byte (-1 if we're not in bit reading mode)
int zeroBytes; // the number of consecutive zero bytes (to detect 0x000003)
uint32_t scanner;
// Identifiers written in '_' notation as in "ITU-T H.264":
bool separate_colour_plane_flag;
int log2_max_frame_num;
bool frame_mbs_only_flag;
//
protected:
cTsPayload tsPayload;
uint32_t scanner;
bool gotAccessUnitDelimiter;
bool gotSequenceParameterSet;
uchar GetByte(bool Raw = false);
@ -1430,6 +1433,81 @@ void cH264Parser::ParseSliceHeader(void)
}
}
// --- cH265Parser -----------------------------------------------------------
class cH265Parser : public cH264Parser {
private:
enum eNalUnitType {
nutSliceSegmentTrailingN = 0,
nutSliceSegmentTrailingR = 1,
nutSliceSegmentTSAN = 2,
nutSliceSegmentTSAR = 3,
nutSliceSegmentSTSAN = 4,
nutSliceSegmentSTSAR = 5,
nutSliceSegmentRADLN = 6,
nutSliceSegmentRADLR = 7,
nutSliceSegmentRASLN = 8,
nutSliceSegmentRASLR = 9,
nutSliceSegmentBLAWLP = 16,
nutSliceSegmentBLAWRADL = 17,
nutSliceSegmentBLANLP = 18,
nutSliceSegmentIDRWRADL = 19,
nutSliceSegmentIDRNLP = 20,
nutSliceSegmentCRANUT = 21,
nutVideoParameterSet = 32,
nutSequenceParameterSet = 33,
nutPictureParameterSet = 34,
nutAccessUnitDelimiter = 35,
nutEndOfSequence = 36,
nutEndOfBitstream = 37,
nutFillerData = 38,
nutPrefixSEI = 39,
nutSuffixSEI = 40,
nutNonVCLRes0 = 41,
nutNonVCLRes3 = 44,
nutUnspecified0 = 48,
nutUnspecified7 = 55,
};
public:
cH265Parser(void);
virtual int Parse(const uchar *Data, int Length, int Pid);
};
cH265Parser::cH265Parser(void)
:cH264Parser()
{
}
int cH265Parser::Parse(const uchar *Data, int Length, int Pid)
{
newFrame = independentFrame = false;
tsPayload.Setup(const_cast<uchar *>(Data), Length, Pid);
if (TsPayloadStart(Data)) {
tsPayload.SkipPesHeader();
scanner = EMPTY_SCANNER;
}
for (;;) {
scanner = (scanner << 8) | GetByte(true);
if ((scanner & 0xFFFFFF00) == 0x00000100) { // NAL unit start
uchar NalUnitType = (scanner >> 1) & 0x3F;
GetByte(); // nuh_layer_id + nuh_temporal_id_plus1
if (NalUnitType <= nutSliceSegmentRASLR || (NalUnitType >= nutSliceSegmentBLAWLP && NalUnitType <= nutSliceSegmentCRANUT)) {
if (NalUnitType == nutSliceSegmentIDRWRADL || NalUnitType == nutSliceSegmentIDRNLP || NalUnitType == nutSliceSegmentCRANUT)
independentFrame = true;
if (GetBit()) { // first_slice_segment_in_pic_flag
newFrame = true;
tsPayload.Statistics();
}
break;
}
}
if (tsPayload.AtPayloadStart() // stop at any new payload start to have the buffer refilled if necessary
|| tsPayload.Eof()) // or if we're out of data
break;
}
return tsPayload.Used();
}
// --- cFrameDetector --------------------------------------------------------
cFrameDetector::cFrameDetector(int Pid, int Type)
@ -1456,14 +1534,16 @@ void cFrameDetector::SetPid(int Pid, int Type)
{
pid = Pid;
type = Type;
isVideo = type == 0x01 || type == 0x02 || type == 0x1B; // MPEG 1, 2 or H.264
isVideo = type == 0x01 || type == 0x02 || type == 0x1B || type == 0x24; // MPEG 1, 2, H.264 or H.265
delete parser;
parser = NULL;
if (type == 0x01 || type == 0x02)
parser = new cMpeg2Parser;
else if (type == 0x1B)
parser = new cH264Parser;
else if (type == 0x04 || type == 0x06) // MPEG audio or AC3 audio
else if (type == 0x24)
parser = new cH265Parser;
else if (type == 0x03 || type == 0x04 || type == 0x06) // MPEG audio or AC3 audio
parser = new cAudioParser;
else if (type != 0)
esyslog("ERROR: unknown stream type %d (PID %d) in frame detector", type, pid);

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: remux.h 4.0 2014/03/22 14:58:24 kls Exp $
* $Id: remux.h 4.1 2016/12/22 13:09:54 kls Exp $
*/
#ifndef __REMUX_H
@ -361,6 +361,7 @@ private:
uint16_t compositionPageIds[MAXSPIDS];
uint16_t ancillaryPageIds[MAXSPIDS];
bool updatePrimaryDevice;
bool completed;
protected:
int SectionLength(const uchar *Data, int Length) { return (Length >= 3) ? ((int(Data[1]) & 0x0F) << 8)| Data[2] : 0; }
public:
@ -397,6 +398,8 @@ public:
int Vtype(void) const { return vtype; }
///< Returns the video stream type as defined by the current PMT, or 0 if no video
///< stream type has been detected, yet.
bool Completed(void) { return completed; }
///< Returns true if the PMT has been completely parsed.
const int *Apids(void) const { return apids; }
const int *Dpids(void) const { return dpids; }
const int *Spids(void) const { return spids; }

View File

@ -7,7 +7,7 @@
* Parts of this file were inspired by the 'ringbuffy.c' from the
* LinuxDVB driver (see linuxtv.org).
*
* $Id: ringbuffer.c 4.0 2012/09/22 11:26:49 kls Exp $
* $Id: ringbuffer.c 4.1 2016/12/22 10:26:13 kls Exp $
*/
#include "ringbuffer.h"
@ -390,12 +390,13 @@ void cRingBufferLinear::Del(int Count)
// --- cFrame ----------------------------------------------------------------
cFrame::cFrame(const uchar *Data, int Count, eFrameType Type, int Index, uint32_t Pts)
cFrame::cFrame(const uchar *Data, int Count, eFrameType Type, int Index, uint32_t Pts, bool Independent)
{
count = abs(Count);
type = Type;
index = Index;
pts = Pts;
independent = Type == ftAudio ? true : Independent;
if (Count < 0)
data = (uchar *)Data;
else {

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: ringbuffer.h 4.0 2013/02/16 15:20:37 kls Exp $
* $Id: ringbuffer.h 4.1 2016/12/22 10:26:13 kls Exp $
*/
#ifndef __RINGBUFFER_H
@ -113,8 +113,9 @@ private:
eFrameType type;
int index;
uint32_t pts;
bool independent;
public:
cFrame(const uchar *Data, int Count, eFrameType = ftUnknown, int Index = -1, uint32_t Pts = 0);
cFrame(const uchar *Data, int Count, eFrameType = ftUnknown, int Index = -1, uint32_t Pts = 0, bool independent = false);
///< Creates a new cFrame object.
///< If Count is negative, the cFrame object will take ownership of the given
///< Data. Otherwise it will allocate Count bytes of memory and copy Data.
@ -124,6 +125,7 @@ public:
eFrameType Type(void) const { return type; }
int Index(void) const { return index; }
uint32_t Pts(void) const { return pts; }
bool Independent(void) const { return independent; }
};
class cRingBufferFrame : public cRingBuffer {

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: skinclassic.c 4.0 2013/03/03 15:26:09 kls Exp $
* $Id: skinclassic.c 4.1 2016/12/22 14:07:04 kls Exp $
*/
#include "skinclassic.h"
@ -352,8 +352,7 @@ void cSkinClassicDisplayMenu::SetEvent(const cEvent *Event)
const cFont *font = cFont::GetFont(fontOsd);
int y = y2;
cTextScroller ts;
char t[32];
snprintf(t, sizeof(t), "%s %s - %s", *Event->GetDateString(), *Event->GetTimeString(), *Event->GetEndTimeString());
cString t = cString::sprintf("%s %s - %s", *Event->GetDateString(), *Event->GetTimeString(), *Event->GetEndTimeString());
ts.Set(osd, x1, y, x2 - x1, y3 - y, t, font, Theme.Color(clrMenuEventTime), Theme.Color(clrBackground));
if (Event->Vps() && Event->Vps() != Event->StartTime()) {
cString buffer = cString::sprintf(" VPS: %s ", *Event->GetVpsString());

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: skinlcars.c 4.1 2015/09/01 10:07:07 kls Exp $
* $Id: skinlcars.c 4.2 2016/12/22 14:05:56 kls Exp $
*/
// "Star Trek: The Next Generation"(R) is a registered trademark of Paramount Pictures,
@ -1636,8 +1636,7 @@ void cSkinLCARSDisplayMenu::SetEvent(const cEvent *Event)
int xl = xi00;
int y = yi00;
cTextScroller ts;
char t[32];
snprintf(t, sizeof(t), "%s %s - %s", *Event->GetDateString(), *Event->GetTimeString(), *Event->GetEndTimeString());
cString t = cString::sprintf("%s %s - %s", *Event->GetDateString(), *Event->GetTimeString(), *Event->GetEndTimeString());
ts.Set(osd, xl, y, xi01 - xl, yi01 - y, t, font, Theme.Color(clrEventTime), Theme.Color(clrBackground));
if (Event->Vps() && Event->Vps() != Event->StartTime()) {
cString buffer = cString::sprintf(" VPS: %s ", *Event->GetVpsString());

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: skinsttng.c 4.0 2013/11/15 15:33:14 kls Exp $
* $Id: skinsttng.c 4.1 2016/12/22 14:07:22 kls Exp $
*/
// "Star Trek: The Next Generation"(R) is a registered trademark of Paramount Pictures
@ -655,8 +655,7 @@ void cSkinSTTNGDisplayMenu::SetEvent(const cEvent *Event)
int xl = x3 + TextSpacing;
int y = y3;
cTextScroller ts;
char t[32];
snprintf(t, sizeof(t), "%s %s - %s", *Event->GetDateString(), *Event->GetTimeString(), *Event->GetEndTimeString());
cString t = cString::sprintf("%s %s - %s", *Event->GetDateString(), *Event->GetTimeString(), *Event->GetEndTimeString());
ts.Set(osd, xl, y, x4 - xl, y4 - y, t, font, Theme.Color(clrMenuEventTime), Theme.Color(clrBackground));
if (Event->Vps() && Event->Vps() != Event->StartTime()) {
cString buffer = cString::sprintf(" VPS: %s ", *Event->GetVpsString());

View File

@ -51,6 +51,7 @@ S52.5E Yahsat 1A
S53E Express AM22
S56E DirecTV 1R
S57E NSS 12
S58.5E Kazsat 3
S60E Intelsat 904
S62E Intelsat 902
S64E Intelsat 906
@ -109,80 +110,80 @@ S172E Eutelsat 172A
S180E Intelsat 18
S177W NSS 9
# Atlantic
S0.8W Intelsat 10-02
S1W Thor 5/6
S4W Amos 2/3
S5W Eutelsat 5 West A
S7W Nilesat 101/201 & Eutelsat 7 West A
S8W Eutelsat 8 West A/C
S11W Express AM44
S12.5W Eutelsat 12 West A
S14W Express A4
S15W Telstar 12
S18W Intelsat 901
S20W NSS 7
S22W SES 4
S24.5W Intelsat 905
S27.5W Intelsat 907
S30W Hispasat 1D/1E
S31.5W Intelsat 25
S34.5W Intelsat 903
S37.5W NSS 10 & Telstar 11N
S40.5W SES 6
S43W Intelsat 11
S45W Intelsat 14
S50W Intelsat 1R
S53W Intelsat 23
S55.5W Intelsat 805
S58W Intelsat 21
S61W Amazonas 2/3
# America
S61.5W Echostar 16
S63W Telstar 14R
S65W Star One C1
S67W AMC 4
S70W Star One C2
S72W AMC 6
S72.7W Nimiq 5
S75W Star One C3
S77W QuetzSat 1
S82W Nimiq 4
S83W AMC 9
S84W Brasilsat B4
S139W AMC 8
S137W AMC 7
S135W AMC 10
S133W Galaxy 15
S131W AMC 11
S129W Ciel 2
S127W Galaxy 13/Horizons 1
S125W Galaxy 14 & AMC 21
S123W Galaxy 18
S121W Echostar 9/Galaxy 23
S119W Echostar 14 & DirecTV 7S
S118.8W Anik F3
S116.8W SatMex 8
S114.9W SatMex 5
S113W SatMex 6
S111.1W Anik F2
S110W DirecTV 5 & Echostar 10/11
S107.3W Anik F1R/G1
S105W AMC 15/18
S103W AMC 1
S101W DirecTV 4S/8 & SES 1
S99.2W Galaxy 16
S97W Galaxy 19
S95W Galaxy 3C
S93.1W Galaxy 25
S91W Galaxy 17 & Nimiq 6
S89W Galaxy 28
S87W SES 2
S85W AMC 16
S85.1W XM 3
S87W SES 2
S89W Galaxy 28
S91W Galaxy 17 & Nimiq 6
S93.1W Galaxy 25
S95W Galaxy 3C
S97W Galaxy 19
S99.2W Galaxy 16
S101W DirecTV 4S/8 & SES 1
S103W AMC 1
S105W AMC 15/18
S107.3W Anik F1R/G1
S110W DirecTV 5 & Echostar 10/11
S111.1W Anik F2
S113W SatMex 6
S114.9W SatMex 5
S116.8W SatMex 8
S118.8W Anik F3
S119W Echostar 14 & DirecTV 7S
S121W Echostar 9/Galaxy 23
S123W Galaxy 18
S125W Galaxy 14 & AMC 21
S127W Galaxy 13/Horizons 1
S129W Ciel 2
S131W AMC 11
S133W Galaxy 15
S135W AMC 10
S137W AMC 7
S139W AMC 8
S84W Brasilsat B4
S83W AMC 9
S82W Nimiq 4
S77W QuetzSat 1
S75W Star One C3
S72W AMC 6
S72.7W Nimiq 5
S70W Star One C2
S67W AMC 4
S65W Star One C1
S63W Telstar 14R
S61.5W Echostar 16
# Atlantic
S61W Amazonas 2/3
S58W Intelsat 21
S55.5W Intelsat 805
S53W Intelsat 23
S50W Intelsat 1R
S45W Intelsat 14
S43W Intelsat 11
S40.5W SES 6
S37.5W NSS 10 & Telstar 11N
S34.5W Intelsat 903
S31.5W Intelsat 25
S30W Hispasat 1D/1E
S27.5W Intelsat 907
S24.5W Intelsat 905
S22W SES 4
S20W NSS 7
S18W Intelsat 901
S15W Telstar 12
S14W Express A4
S12.5W Eutelsat 12 West A
S11W Express AM44
S8W Eutelsat 8 West A/C
S7W Nilesat 101/201 & Eutelsat 7 West A
S5W Eutelsat 5 West A
S4W Amos 2/3
S1W Thor 5/6
S0.8W Intelsat 10-02
S360E Any satellite

10
svdrp.c
View File

@ -10,7 +10,7 @@
* and interact with the Video Disk Recorder - or write a full featured
* graphical interface that sits on top of an SVDRP connection.
*
* $Id: svdrp.c 4.9 2015/09/14 13:23:06 kls Exp $
* $Id: svdrp.c 4.11 2016/12/08 10:48:53 kls Exp $
*/
#include "svdrp.h"
@ -1228,6 +1228,10 @@ void cSVDRPServer::CmdDELC(const char *Option)
int n = Channels->GetNextNormal(CurrentChannel->Index());
if (n < 0)
n = Channels->GetPrevNormal(CurrentChannel->Index());
if (n < 0) {
Reply(501, "Can't delete channel \"%s\" - list would be empty", Option);
return;
}
CurrentChannel = Channels->Get(n);
CurrentChannelNr = 0; // triggers channel switch below
}
@ -1240,7 +1244,7 @@ void cSVDRPServer::CmdDELC(const char *Option)
if (!cDevice::PrimaryDevice()->Replaying() || cDevice::PrimaryDevice()->Transferring())
Channels->SwitchTo(CurrentChannel->Number());
else
cDevice::SetCurrentChannel(CurrentChannel);
cDevice::SetCurrentChannel(CurrentChannel->Number());
}
Reply(250, "Channel \"%s\" deleted", Option);
}
@ -1899,7 +1903,7 @@ void cSVDRPServer::CmdMOVC(const char *Option)
if (!cDevice::PrimaryDevice()->Replaying() || cDevice::PrimaryDevice()->Transferring())
Channels->SwitchTo(CurrentChannel->Number());
else
cDevice::SetCurrentChannel(CurrentChannel);
cDevice::SetCurrentChannel(CurrentChannel->Number());
}
isyslog("SVDRP < %s channel %d moved to %d", *connection, FromNumber, ToNumber);
Reply(250,"Channel \"%d\" moved to \"%d\"", From, To);

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: thread.c 4.1 2015/08/29 14:43:03 kls Exp $
* $Id: thread.c 4.2 2016/12/08 09:45:25 kls Exp $
*/
#include "thread.h"
@ -151,6 +151,8 @@ void cCondVar::Broadcast(void)
cRwLock::cRwLock(bool PreferWriter)
{
locked = 0;
writeLockThreadId = 0;
pthread_rwlockattr_t attr;
pthread_rwlockattr_init(&attr);
pthread_rwlockattr_setkind_np(&attr, PreferWriter ? PTHREAD_RWLOCK_PREFER_WRITER_NP : PTHREAD_RWLOCK_PREFER_READER_NP);
@ -170,8 +172,15 @@ bool cRwLock::Lock(bool Write, int TimeoutMs)
if (!GetAbsTime(&abstime, TimeoutMs))
TimeoutMs = 0;
}
if (Write)
if (Write) {
Result = TimeoutMs ? pthread_rwlock_timedwrlock(&rwlock, &abstime) : pthread_rwlock_wrlock(&rwlock);
if (Result == 0)
writeLockThreadId = cThread::ThreadId();
}
else if (writeLockThreadId == cThread::ThreadId()) {
locked++; // there can be any number of stacked read locks, so we keep track here
Result = 0; // aquiring a read lock while holding a write lock within the same thread is OK
}
else
Result = TimeoutMs ? pthread_rwlock_timedrdlock(&rwlock, &abstime) : pthread_rwlock_rdlock(&rwlock);
return Result == 0;
@ -179,6 +188,13 @@ bool cRwLock::Lock(bool Write, int TimeoutMs)
void cRwLock::Unlock(void)
{
if (writeLockThreadId == cThread::ThreadId()) { // this is the thread that obtained the initial write lock
if (locked) { // this is the unlock of a read lock within the write lock
locked--;
return;
}
}
writeLockThreadId = 0;
pthread_rwlock_unlock(&rwlock);
}
@ -206,8 +222,8 @@ void cMutex::Lock(void)
void cMutex::Unlock(void)
{
if (!--locked)
pthread_mutex_unlock(&mutex);
if (!--locked)
pthread_mutex_unlock(&mutex);
}
// --- cThread ---------------------------------------------------------------
@ -474,9 +490,11 @@ void cStateLock::Unlock(cStateKey &StateKey, bool IncState)
if (StateKey.write && IncState && !explicitModify)
state++;
StateKey.state = state;
StateKey.write = false;
threadId = 0;
explicitModify = false;
if (StateKey.write) {
StateKey.write = false;
threadId = 0;
explicitModify = false;
}
rwLock.Unlock();
}

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: thread.h 4.1 2015/08/17 13:06:24 kls Exp $
* $Id: thread.h 4.2 2016/12/08 09:11:24 kls Exp $
*/
#ifndef __THREAD_H
@ -14,6 +14,8 @@
#include <stdio.h>
#include <sys/types.h>
typedef pid_t tThreadId;
class cCondWait {
private:
pthread_mutex_t mutex;
@ -53,6 +55,8 @@ public:
class cRwLock {
private:
pthread_rwlock_t rwlock;
int locked;
tThreadId writeLockThreadId;
public:
cRwLock(bool PreferWriter = false);
~cRwLock();
@ -72,8 +76,6 @@ public:
void Unlock(void);
};
typedef pid_t tThreadId;
class cThread {
friend class cThreadLock;
private:

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: timers.c 4.5 2015/09/13 13:10:24 kls Exp $
* $Id: timers.c 4.7 2016/12/23 09:48:39 kls Exp $
*/
#include "timers.h"
@ -748,9 +748,9 @@ const cTimer *cTimers::GetById(int Id) const
return NULL;
}
cTimer *cTimers::GetTimer(cTimer *Timer)
const cTimer *cTimers::GetTimer(const cTimer *Timer) const
{
for (cTimer *ti = First(); ti; ti = Next(ti)) {
for (const cTimer *ti = First(); ti; ti = Next(ti)) {
if (!ti->Remote() &&
ti->Channel() == Timer->Channel() &&
(ti->WeekDays() && ti->WeekDays() == Timer->WeekDays() || !ti->WeekDays() && ti->Day() == Timer->Day()) &&

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: timers.h 4.3 2015/09/09 10:40:24 kls Exp $
* $Id: timers.h 4.6 2016/12/23 09:49:31 kls Exp $
*/
#ifndef __TIMERS_H
@ -122,7 +122,7 @@ public:
cTimers(void);
static const cTimers *GetTimersRead(cStateKey &StateKey, int TimeoutMs = 0);
///< Gets the list of timers for read access. If TimeoutMs is given,
///< it will wait that long to get a write lock before giving up.
///< it will wait that long to get a read lock before giving up.
///< Otherwise it will wait indefinitely. If no read lock can be
///< obtained within the given timeout, NULL will be returned.
///< The list is locked and a pointer to it is returned if the state
@ -170,7 +170,8 @@ public:
static int NewTimerId(void);
const cTimer *GetById(int Id) const;
cTimer *GetById(int Id) { return const_cast<cTimer *>(static_cast<const cTimers *>(this)->GetById(Id)); };
cTimer *GetTimer(cTimer *Timer);
const cTimer *GetTimer(const cTimer *Timer) const;
cTimer *GetTimer(const cTimer *Timer) { return const_cast<cTimer *>(static_cast<const cTimers *>(this)->GetTimer(Timer)); };
const cTimer *GetMatch(time_t t) const;
cTimer *GetMatch(time_t t) { return const_cast<cTimer *>(static_cast<const cTimers *>(this)->GetMatch(t)); };
const cTimer *GetMatch(const cEvent *Event, eTimerMatch *Match = NULL) const;

40
tools.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: tools.c 4.4 2015/09/10 13:17:55 kls Exp $
* $Id: tools.c 4.5 2016/12/23 14:03:40 kls Exp $
*/
#include "tools.h"
@ -2272,6 +2272,44 @@ void cListBase::Sort(void)
free(a);
}
// --- cDynamicBuffer --------------------------------------------------------
cDynamicBuffer::cDynamicBuffer(int InitialSize)
{
initialSize = InitialSize;
buffer = NULL;
size = used = 0;
}
cDynamicBuffer::~cDynamicBuffer()
{
free(buffer);
}
bool cDynamicBuffer::Realloc(int NewSize)
{
if (size < NewSize) {
NewSize = max(NewSize, size ? size * 3 / 2 : initialSize); // increase size by at least 50%
if (uchar *NewBuffer = (uchar *)realloc(buffer, NewSize)) {
buffer = NewBuffer;
size = NewSize;
}
else {
esyslog("ERROR: out of memory");
return false;
}
}
return true;
}
void cDynamicBuffer::Append(const uchar *Data, int Length)
{
if (Assert(used + Length)) {
memcpy(buffer + used, Data, Length);
used += Length;
}
}
// --- cHashBase -------------------------------------------------------------
cHashBase::cHashBase(int Size)

24
tools.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: tools.h 4.3 2015/09/06 10:45:54 kls Exp $
* $Id: tools.h 4.5 2016/12/23 13:56:35 kls Exp $
*/
#ifndef __TOOLS_H
@ -609,7 +609,7 @@ public: \
else \
list = c##Class::Get##Name##Read(stateKey); \
} \
~c##Name##Lock() { stateKey.Remove(); } \
~c##Name##Lock() { if (list) stateKey.Remove(); } \
const c##Class *Name(void) const { return list; } \
c##Class *Name(void) { return const_cast<c##Class *>(list); } \
}
@ -775,6 +775,26 @@ public:
bool Load(const char *Directory, bool DirsOnly = false);
};
class cDynamicBuffer {
private:
uchar *buffer;
int initialSize;
int size; // the total size of the buffer (bytes in memory)
int used; // the number of used bytes, starting at the beginning of the buffer
bool Realloc(int NewSize);
bool Assert(int NewSize) { return size < NewSize ? Realloc(NewSize) : true; } // inline for performance!
public:
cDynamicBuffer(int InitialSize = 1024);
~cDynamicBuffer();
void Append(const uchar *Data, int Length);
void Append(uchar Data) { if (Assert(used + 1)) buffer[used++] = Data; }
void Set(int Index, uchar Data) { if (Assert(Index + 1)) buffer[Index] = Data; }
uchar Get(int Index) { return Index < used ? buffer[Index] : 0; }
void Clear(void) { used = 0; }
uchar *Data(void) { return buffer; }
int Length(void) { return used; }
};
class cHashObject : public cListObject {
friend class cHashBase;
private:

36
vdr.c
View File

@ -22,7 +22,7 @@
*
* The project's page is at http://www.tvdr.de
*
* $Id: vdr.c 4.7 2015/09/11 08:02:50 kls Exp $
* $Id: vdr.c 4.9 2016/12/23 14:34:37 kls Exp $
*/
#include <getopt.h>
@ -171,6 +171,9 @@ static void Watchdog(int signum)
// Something terrible must have happened that prevented the 'alarm()' from
// being called in time, so let's get out of here:
esyslog("PANIC: watchdog timer expired - exiting!");
#ifdef SDNOTIFY
sd_notify(0, "STOPPING=1\nSTATUS=PANIC");
#endif
exit(1);
}
@ -235,6 +238,10 @@ int main(int argc, char *argv[])
#if defined(VDR_USER)
VdrUser = VDR_USER;
#endif
#ifdef SDNOTIFY
time_t SdWatchdog;
int SdWatchdogTimeout = 0;
#endif
cArgs *Args = NULL;
if (argc == 1) {
@ -914,6 +921,16 @@ int main(int argc, char *argv[])
}
#ifdef SDNOTIFY
if (sd_watchdog_enabled(0, NULL) > 0) {
uint64_t timeout;
SdWatchdog = time(NULL);
sd_watchdog_enabled(0, &timeout);
SdWatchdogTimeout = (int)timeout/1000000;
dsyslog("SD_WATCHDOG enabled with timeout set to %d seconds", SdWatchdogTimeout);
}
// Startup notification:
sd_notify(0, "READY=1\nSTATUS=Ready");
#endif
@ -976,6 +993,14 @@ int main(int argc, char *argv[])
dsyslog("max. latency time %d seconds", MaxLatencyTime);
}
}
#ifdef SDNOTIFY
// Ping systemd watchdog when half the timeout is elapsed:
if (SdWatchdogTimeout && (Now - SdWatchdog) * 2 > SdWatchdogTimeout) {
sd_notify(0, "WATCHDOG=1");
SdWatchdog = Now;
dsyslog("SD_WATCHDOG ping");
}
#endif
// Handle channel and timer modifications:
{
// Channels and timers need to be stored in a consistent manner,
@ -1480,9 +1505,6 @@ int main(int argc, char *argv[])
ShutdownHandler.countdown.Cancel();
}
// Keep the recordings handler alive:
RecordingsHandler.Active();
if ((Now - LastInteract) > ACTIVITYTIMEOUT && !cRecordControls::Active() && !RecordingsHandler.Active() && (Now - cRemote::LastActivity()) > ACTIVITYTIMEOUT) {
// Handle housekeeping tasks
@ -1568,5 +1590,11 @@ Exit:
closelog();
if (HasStdin)
tcsetattr(STDIN_FILENO, TCSANOW, &savedTm);
#ifdef SDNOTIFY
if (ShutdownHandler.GetExitCode() == 2)
sd_notify(0, "STOPPING=1\nSTATUS=Startup failed, exiting");
else
sd_notify(0, "STOPPING=1\nSTATUS=Exiting");
#endif
return ShutdownHandler.GetExitCode();
}