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 for suggesting to ignore channels with an RID that is not 0 when checking for obsolete
channels channels
for fixing a possible stack overflow in cListBase::Sort() for fixing a possible stack overflow in cListBase::Sort()
for reporting a crash when deleting a recording
Reinhard Walter Buchner <rw.buchner@freenet.de> Reinhard Walter Buchner <rw.buchner@freenet.de>
for adding some satellites to 'sources.conf' for adding some satellites to 'sources.conf'
@ -1844,6 +1845,7 @@ Lucian Muresan <lucianm@users.sourceforge.net>
for exporting some libsi functions for exporting some libsi functions
for suggesting to add functions to cDevice that allow derived output devices to for suggesting to add functions to cDevice that allow derived output devices to
implement scaling the video to a given size and location implement scaling the video to a given size and location
fpr sorting sources.conf by continous azimuth
Mattias Grönlund <Mattias@Gronlund.net> Mattias Grönlund <Mattias@Gronlund.net>
for pointing out a missing cleanup at program exit in case there is a problem 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 possible NULL pointer dereference in cCiSession::SendData()
for reporting a superfluous assignment in cPipe::Open() for reporting a superfluous assignment in cPipe::Open()
for avoiding unnecessary pkg-config warnings in plugin Makefiles 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> Steffen Beyer <cpunk@reactor.de>
for fixing setting the colored button help after deleting a recording in case the next 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 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 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 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> Alex Lasnier <alex@fepg.org>
for adding tuning support for ATSC devices for adding tuning support for ATSC devices
@ -3225,6 +3233,7 @@ Malte Forkel <malte.forkel@berlin.de>
Marc Perrudin <vdr@ekass.net> Marc Perrudin <vdr@ekass.net>
for translating OSD texts to the French language for translating OSD texts to the French language
for adding support for the systemd watchdog
Bernard Jaulin <bernard.jaulin@gmail.com> Bernard Jaulin <bernard.jaulin@gmail.com>
for translating OSD texts to the French language for translating OSD texts to the French language
@ -3322,6 +3331,18 @@ Thomas Reufer <thomas@reufer.ch>
ViewPort and DrawPort ViewPort and DrawPort
for suggesting to reduce the priority of the "video directory scanner" thread for suggesting to reduce the priority of the "video directory scanner" thread
for making the 'newplugin' script create the 'po' subdirectory for translations 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> Eike Sauer <EikeSauer@t-online.de>
for reporting a problem with channels that need more than 5 TS packets for detecting 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> Stefan Pöschel <basic.master@gmx.de>
for coding the AFFcleaner, parts of which were used to make the recorder skip empty for coding the AFFcleaner, parts of which were used to make the recorder skip empty
adaptation field TS packets 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). live tv (suggested by Dietmar Spingler).
- Empty adaptation field TS packets are now skipped when recording (thanks to - Empty adaptation field TS packets are now skipped when recording (thanks to
Christopher Reimer, based on the "AFFcleaner" by Stefan Pöschel). 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 # See the main source file 'vdr.c' for copyright information and
# how to reach the author. # 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: .DELETE_ON_ERROR:
@ -95,9 +95,9 @@ DEFINES += -DBIDI
LIBS += $(shell pkg-config --libs fribidi) LIBS += $(shell pkg-config --libs fribidi)
endif endif
ifdef SDNOTIFY ifdef SDNOTIFY
INCLUDES += $(shell pkg-config --cflags libsystemd-daemon) INCLUDES += $(shell pkg-config --silence-errors --cflags libsystemd-daemon || pkg-config --cflags libsystemd)
DEFINES += -DSDNOTIFY DEFINES += -DSDNOTIFY
LIBS += $(shell pkg-config --libs libsystemd-daemon) LIBS += $(shell pkg-config --silence-errors --libs libsystemd-daemon || pkg-config --libs libsystemd)
endif endif
LIRC_DEVICE ?= /var/run/lirc/lircd LIRC_DEVICE ?= /var/run/lirc/lircd

View File

@ -130,3 +130,10 @@ VDR Plugin 'skincurses' Revision History
2015-02-19: Version 2.2.0 2015-02-19: Version 2.2.0
- Official release. - 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. * 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> #include <ncurses.h>
@ -12,7 +12,7 @@
#include <vdr/skins.h> #include <vdr/skins.h>
#include <vdr/videodir.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 *DESCRIPTION = trNOOP("A text only skin");
static const char *MAINMENUENTRY = NULL; static const char *MAINMENUENTRY = NULL;
@ -20,6 +20,7 @@ static const char *MAINMENUENTRY = NULL;
class cCursesFont : public cFont { class cCursesFont : public cFont {
public: public:
virtual int Width(void) const { return 1; }
virtual int Width(uint c) 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 Width(const char *s) const { return s ? Utf8StrLen(s) : 0; }
virtual int Height(void) const { return 1; } virtual int Height(void) const { return 1; }
@ -407,8 +408,7 @@ void cSkinCursesDisplayMenu::SetEvent(const cEvent *Event)
return; return;
int y = 2; int y = 2;
cTextScroller ts; cTextScroller ts;
char t[32]; cString t = cString::sprintf("%s %s - %s", *Event->GetDateString(), *Event->GetTimeString(), *Event->GetEndTimeString());
snprintf(t, sizeof(t), "%s %s - %s", *Event->GetDateString(), *Event->GetTimeString(), *Event->GetEndTimeString());
ts.Set(osd, 0, y, ScOsdWidth, ScOsdHeight - y - 2, t, &Font, clrYellow, clrBackground); ts.Set(osd, 0, y, ScOsdWidth, ScOsdHeight - y - 2, t, &Font, clrYellow, clrBackground);
if (Event->Vps() && Event->Vps() != Event->StartTime()) { if (Event->Vps() && Event->Vps() != Event->StartTime()) {
cString buffer = cString::sprintf(" VPS: %s", *Event->GetVpsString()); 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 * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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" #include "ci.h"
@ -756,9 +756,9 @@ class cCiCaPmt {
friend class cCiConditionalAccessSupport; friend class cCiConditionalAccessSupport;
private: private:
uint8_t cmdId; uint8_t cmdId;
int length;
int esInfoLengthPos; int esInfoLengthPos;
uint8_t capmt[2048]; ///< XXX is there a specified maximum? cDynamicBuffer caDescriptors;
cDynamicBuffer capmt;
int source; int source;
int transponder; int transponder;
int programNumber; int programNumber;
@ -768,7 +768,7 @@ public:
cCiCaPmt(uint8_t CmdId, int Source, int Transponder, int ProgramNumber, const int *CaSystemIds); cCiCaPmt(uint8_t CmdId, int Source, int Transponder, int ProgramNumber, const int *CaSystemIds);
uint8_t CmdId(void) { return cmdId; } uint8_t CmdId(void) { return cmdId; }
void SetListManagement(uint8_t ListManagement); 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); 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] = CaSystemIds[i];
} }
caSystemIds[i] = 0; caSystemIds[i] = 0;
uint8_t caDescriptors[512]; GetCaDescriptors(source, transponder, programNumber, caSystemIds, caDescriptors, 0);
int caDescriptorsLength = GetCaDescriptors(source, transponder, programNumber, caSystemIds, sizeof(caDescriptors), caDescriptors, 0); capmt.Append(CPLM_ONLY);
length = 0; capmt.Append((ProgramNumber >> 8) & 0xFF);
capmt[length++] = CPLM_ONLY; capmt.Append( ProgramNumber & 0xFF);
capmt[length++] = (ProgramNumber >> 8) & 0xFF; capmt.Append(0x01); // version_number, current_next_indicator - apparently vn doesn't matter, but cni must be 1
capmt[length++] = ProgramNumber & 0xFF; esInfoLengthPos = capmt.Length();
capmt[length++] = 0x01; // version_number, current_next_indicator - apparently vn doesn't matter, but cni must be 1 capmt.Append(0x00); // program_info_length H (at program level)
esInfoLengthPos = length; capmt.Append(0x00); // program_info_length L
capmt[length++] = 0x00; // program_info_length H (at program level) AddCaDescriptors(caDescriptors.Length(), caDescriptors.Data());
capmt[length++] = 0x00; // program_info_length L
AddCaDescriptors(caDescriptorsLength, caDescriptors);
} }
void cCiCaPmt::SetListManagement(uint8_t ListManagement) void cCiCaPmt::SetListManagement(uint8_t ListManagement)
{ {
capmt[0] = ListManagement; capmt.Set(0, ListManagement);
} }
void cCiCaPmt::AddPid(int Pid, uint8_t StreamType) void cCiCaPmt::AddPid(int Pid, uint8_t StreamType)
{ {
if (Pid) { if (Pid) {
uint8_t caDescriptors[512]; GetCaDescriptors(source, transponder, programNumber, caSystemIds, caDescriptors, Pid);
int caDescriptorsLength = GetCaDescriptors(source, transponder, programNumber, caSystemIds, sizeof(caDescriptors), caDescriptors, Pid); capmt.Append(StreamType);
//XXX buffer overflow check??? capmt.Append((Pid >> 8) & 0xFF);
capmt[length++] = StreamType; capmt.Append( Pid & 0xFF);
capmt[length++] = (Pid >> 8) & 0xFF; esInfoLengthPos = capmt.Length();
capmt[length++] = Pid & 0xFF; capmt.Append(0x00); // ES_info_length H (at ES level)
esInfoLengthPos = length; capmt.Append(0x00); // ES_info_length L
capmt[length++] = 0x00; // ES_info_length H (at ES level) AddCaDescriptors(caDescriptors.Length(), caDescriptors.Data());
capmt[length++] = 0x00; // ES_info_length L
AddCaDescriptors(caDescriptorsLength, caDescriptors);
} }
} }
void cCiCaPmt::AddCaDescriptors(int Length, const uint8_t *Data) void cCiCaPmt::AddCaDescriptors(int Length, const uint8_t *Data)
{ {
if (esInfoLengthPos) { if (esInfoLengthPos) {
if (length + Length < int(sizeof(capmt))) { if (Length || cmdId == CPCI_QUERY) {
if (Length || cmdId == CPCI_QUERY) { capmt.Append(cmdId);
capmt[length++] = cmdId; capmt.Append(Data, Length);
memcpy(capmt + length, Data, Length); int l = capmt.Length() - esInfoLengthPos - 2;
length += Length; capmt.Set(esInfoLengthPos, (l >> 8) & 0xFF);
int l = length - esInfoLengthPos - 2; capmt.Set(esInfoLengthPos + 1, l & 0xFF);
capmt[esInfoLengthPos] = (l >> 8) & 0xFF;
capmt[esInfoLengthPos + 1] = l & 0xFF;
}
} }
else
esyslog("ERROR: buffer overflow in CA descriptor");
esInfoLengthPos = 0; esInfoLengthPos = 0;
} }
else else
@ -995,7 +986,7 @@ void cCiConditionalAccessSupport::SendPMT(cCiCaPmt *CaPmt)
{ {
if (CaPmt && state >= 2) { if (CaPmt && state >= 2) {
dbgprotocol("Slot %d: ==> Ca Pmt (%d) %d %d\n", Tc()->CamSlot()->SlotNumber(), SessionId(), CaPmt->ListManagement(), CaPmt->CmdId()); 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 state = 4; // sent ca pmt
} }
} }

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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 #ifndef __CONFIG_H
@ -22,13 +22,13 @@
// VDR's own version number: // VDR's own version number:
#define VDRVERSION "2.3.1" #define VDRVERSION "2.3.2"
#define VDRVERSNUM 20301 // Version * 10000 + Major * 100 + Minor #define VDRVERSNUM 20302 // Version * 10000 + Major * 100 + Minor
// The plugin API's version number: // The plugin API's version number:
#define APIVERSION "2.3.1" #define APIVERSION "2.3.2"
#define APIVERSNUM 20301 // Version * 10000 + Major * 100 + Minor #define APIVERSNUM 20302 // Version * 10000 + Major * 100 + Minor
// When loading plugins, VDR searches them by their APIVERSION, which // When loading plugins, VDR searches them by their APIVERSION, which
// may be smaller than VDRVERSION in case there have been no changes to // 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 * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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" #include "device.h"
@ -1768,6 +1768,7 @@ void cTSBuffer::Action(void)
break; 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 * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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 #ifndef __DEVICE_H
@ -322,7 +322,11 @@ protected:
public: public:
static int CurrentChannel(void) { return primaryDevice ? currentChannel : 0; } static int CurrentChannel(void) { return primaryDevice ? currentChannel : 0; }
///< Returns the number of the current channel on the primary device. ///< 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; } 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 ///< Sets the number of the current channel on the primary device, without
///< actually switching to it. This can be used to correct the current ///< actually switching to it. This can be used to correct the current
///< channel number while replaying. ///< channel number while replaying.

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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" #include "dvbdevice.h"
@ -201,21 +201,6 @@ int MapToDriver(int Value, const tDvbParameterMap *Map)
cDvbTransponderParameters::cDvbTransponderParameters(const char *Parameters) 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); Parse(Parameters);
} }
@ -266,6 +251,21 @@ const char *cDvbTransponderParameters::ParseParameter(const char *s, int &Value,
bool cDvbTransponderParameters::Parse(const char *s) 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) { while (s && *s) {
switch (toupper(*s)) { switch (toupper(*s)) {
case 'B': s = ParseParameter(s, bandwidth, BandwidthValues); break; 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 * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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" #include "dvbplayer.h"
@ -17,13 +17,14 @@
// --- cPtsIndex ------------------------------------------------------------- // --- cPtsIndex -------------------------------------------------------------
#define PTSINDEX_ENTRIES 500 #define PTSINDEX_ENTRIES 1024
class cPtsIndex { class cPtsIndex {
private: private:
struct tPtsIndex { struct tPtsIndex {
uint32_t pts; // no need for 33 bit - some devices don't even supply the msb uint32_t pts; // no need for 33 bit - some devices don't even supply the msb
int index; int index;
bool independent;
}; };
tPtsIndex pi[PTSINDEX_ENTRIES]; tPtsIndex pi[PTSINDEX_ENTRIES];
int w, r; int w, r;
@ -33,8 +34,9 @@ public:
cPtsIndex(void); cPtsIndex(void);
void Clear(void); void Clear(void);
bool IsEmpty(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 FindIndex(uint32_t Pts);
int FindFrameNumber(uint32_t Pts);
}; };
cPtsIndex::cPtsIndex(void) cPtsIndex::cPtsIndex(void)
@ -55,10 +57,11 @@ bool cPtsIndex::IsEmpty(void)
return w == r; return w == r;
} }
void cPtsIndex::Put(uint32_t Pts, int Index) void cPtsIndex::Put(uint32_t Pts, int Index, bool Independent)
{ {
cMutexLock MutexLock(&mutex); cMutexLock MutexLock(&mutex);
pi[w].pts = Pts; pi[w].pts = Pts;
pi[w].independent = Independent;
pi[w].index = Index; pi[w].index = Index;
w = (w + 1) % PTSINDEX_ENTRIES; w = (w + 1) % PTSINDEX_ENTRIES;
if (w == r) if (w == r)
@ -87,6 +90,36 @@ int cPtsIndex::FindIndex(uint32_t Pts)
return Index; 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 ------------------------------------------------ // --- cNonBlockingFileReader ------------------------------------------------
class cNonBlockingFileReader : public cThread { class cNonBlockingFileReader : public cThread {
@ -251,6 +284,7 @@ public:
virtual double FramesPerSecond(void) { return framesPerSecond; } virtual double FramesPerSecond(void) { return framesPerSecond; }
virtual void SetAudioTrack(eTrackType Type, const tTrackId *TrackId); virtual void SetAudioTrack(eTrackType Type, const tTrackId *TrackId);
virtual bool GetIndex(int &Current, int &Total, bool SnapToIFrame = false); 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); virtual bool GetReplayMode(bool &Play, bool &Forward, int &Speed);
}; };
@ -433,6 +467,8 @@ void cDvbPlayer::Action(void)
} }
StateKey.Remove(); StateKey.Remove();
} }
if (readIndex > 0) // will first be incremented in the loop!
--readIndex;
nonBlockingFileReader = new cNonBlockingFileReader; nonBlockingFileReader = new cNonBlockingFileReader;
int Length = 0; int Length = 0;
@ -440,7 +476,7 @@ void cDvbPlayer::Action(void)
bool WaitingForData = false; bool WaitingForData = false;
time_t StuckAtEof = 0; time_t StuckAtEof = 0;
uint32_t LastStc = 0; uint32_t LastStc = 0;
int LastReadIFrame = -1; int LastReadFrame = -1;
int SwitchToPlayFrame = 0; int SwitchToPlayFrame = 0;
bool CutIn = false; bool CutIn = false;
bool AtLastMark = false; bool AtLastMark = false;
@ -544,12 +580,9 @@ void cDvbPlayer::Action(void)
int r = nonBlockingFileReader->Result(&b); int r = nonBlockingFileReader->Result(&b);
if (r > 0) { if (r > 0) {
WaitingForData = false; WaitingForData = false;
uint32_t Pts = 0; LastReadFrame = readIndex;
if (readIndependent) { uint32_t Pts = isPesRecording ? (PesHasPts(b) ? PesGetPts(b) : -1) : TsGetPts(b, r);
Pts = isPesRecording ? PesGetPts(b) : TsGetPts(b, r); readFrame = new cFrame(b, -r, ftUnknown, readIndex, Pts, readIndependent); // hands over b to the ringBuffer
LastReadIFrame = readIndex;
}
readFrame = new cFrame(b, -r, ftUnknown, readIndex, Pts); // hands over b to the ringBuffer
} }
else if (r < 0) { else if (r < 0) {
if (errno == EAGAIN) if (errno == EAGAIN)
@ -604,7 +637,7 @@ void cDvbPlayer::Action(void)
pc = playFrame->Count(); pc = playFrame->Count();
if (p) { if (p) {
if (playFrame->Index() >= 0 && playFrame->Pts() != 0) if (playFrame->Index() >= 0 && playFrame->Pts() != 0)
ptsIndex.Put(playFrame->Pts(), playFrame->Index()); ptsIndex.Put(playFrame->Pts(), playFrame->Index(), playFrame->Independent());
if (firstPacket) { if (firstPacket) {
if (isPesRecording) { if (isPesRecording) {
PlayPes(NULL, 0); PlayPes(NULL, 0);
@ -667,7 +700,7 @@ void cDvbPlayer::Action(void)
LastStc = Stc; LastStc = Stc;
int Index = ptsIndex.FindIndex(Stc); int Index = ptsIndex.FindIndex(Stc);
if (playDir == pdForward && !SwitchToPlayFrame) { if (playDir == pdForward && !SwitchToPlayFrame) {
if (Index >= LastReadIFrame) if (Index >= LastReadFrame)
break; // automatically stop at end of recording break; // automatically stop at end of recording
} }
else if (Index <= 0 || SwitchToPlayFrame && Index >= SwitchToPlayFrame) else if (Index <= 0 || SwitchToPlayFrame && Index >= SwitchToPlayFrame)
@ -878,7 +911,7 @@ void cDvbPlayer::Goto(int Index, bool Still)
if (playMode == pmPause) if (playMode == pmPause)
DevicePlay(); DevicePlay();
DeviceStillPicture(b, r); DeviceStillPicture(b, r);
ptsIndex.Put(isPesRecording ? PesGetPts(b) : TsGetPts(b, r), Index); ptsIndex.Put(isPesRecording ? PesGetPts(b) : TsGetPts(b, r), Index, true);
} }
playMode = pmStill; playMode = pmStill;
readIndex = Index; readIndex = Index;
@ -923,6 +956,17 @@ bool cDvbPlayer::GetIndex(int &Current, int &Total, bool SnapToIFrame)
return false; 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) bool cDvbPlayer::GetReplayMode(bool &Play, bool &Forward, int &Speed)
{ {
Play = (playMode == pmPlay || playMode == pmFast); Play = (playMode == pmPlay || playMode == pmFast);
@ -1009,6 +1053,15 @@ bool cDvbPlayerControl::GetIndex(int &Current, int &Total, bool SnapToIFrame)
return false; 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) bool cDvbPlayerControl::GetReplayMode(bool &Play, bool &Forward, int &Speed)
{ {
return player && player->GetReplayMode(Play, Forward, 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 * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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 #ifndef __DVBPLAYER_H
@ -50,6 +50,10 @@ public:
bool GetIndex(int &Current, int &Total, bool SnapToIFrame = false); bool GetIndex(int &Current, int &Total, bool SnapToIFrame = false);
// Returns the current and total frame index, optionally snapped to the // Returns the current and total frame index, optionally snapped to the
// nearest I-frame. // 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); bool GetReplayMode(bool &Play, bool &Forward, int &Speed);
// Returns the current replay mode (if applicable). // Returns the current replay mode (if applicable).
// 'Play' tells whether we are playing or pausing, 'Forward' tells whether // '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. * 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" #include "font.h"
@ -100,6 +100,7 @@ class cFreetypeFont : public cFont {
private: private:
cString fontName; cString fontName;
int size; int size;
int width;
int height; int height;
int bottom; int bottom;
FT_Library library; ///< Handle to library FT_Library library; ///< Handle to library
@ -114,6 +115,7 @@ public:
virtual ~cFreetypeFont(); virtual ~cFreetypeFont();
virtual const char *FontName(void) const { return fontName; } virtual const char *FontName(void) const { return fontName; }
virtual int Size(void) const { return size; } virtual int Size(void) const { return size; }
virtual int Width(void) const { return width; }
virtual int Width(uint c) const; virtual int Width(uint c) const;
virtual int Width(const char *s) const; virtual int Width(const char *s) const;
virtual int Height(void) const { return height; } virtual int Height(void) const { return height; }
@ -125,6 +127,7 @@ cFreetypeFont::cFreetypeFont(const char *Name, int CharHeight, int CharWidth)
{ {
fontName = Name; fontName = Name;
size = CharHeight; size = CharHeight;
width = CharWidth;
height = 0; height = 0;
bottom = 0; bottom = 0;
int error = FT_Init_FreeType(&library); 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 { class cDummyFont : public cFont {
private: private:
int height; int height;
int width;
public: public:
cDummyFont(int CharHeight) { height = CharHeight; } cDummyFont(int CharHeight, int CharWidth) { height = CharHeight; width = CharWidth; }
virtual int Width(uint c) const { return height; } virtual int Width(void) const { return width ? width : height; }
virtual int Width(const char *s) const { return 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 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(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 {}; 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); cString fn = GetFontFileName(Name);
cFont *f = *fn ? new cFreetypeFont(fn, CharHeight, CharWidth) : NULL; cFont *f = *fn ? new cFreetypeFont(fn, CharHeight, CharWidth) : NULL;
if (!f || !f->Height()) if (!f || !f->Height())
f = new cDummyFont(CharHeight); f = new cDummyFont(CharHeight, CharWidth);
return f; return f;
} }

8
font.h
View File

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

3
menu.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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 #ifndef __MENU_H
@ -300,6 +300,7 @@ private:
bool lastPlay, lastForward; bool lastPlay, lastForward;
int lastSpeed; int lastSpeed;
time_t timeoutShow; time_t timeoutShow;
time_t lastProgressUpdate;
bool timeSearchActive, timeSearchHide; bool timeSearchActive, timeSearchHide;
int timeSearchTime, timeSearchPos; int timeSearchTime, timeSearchPos;
void TimeSearchDisplay(void); void TimeSearchDisplay(void);

16
nit.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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" #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 }; static int RollOffs[] = { ROLLOFF_35, ROLLOFF_25, ROLLOFF_20, ROLLOFF_AUTO };
dtp.SetRollOff(sd->getModulationSystem() ? RollOffs[sd->getRollOff()] : ROLLOFF_AUTO); dtp.SetRollOff(sd->getModulationSystem() ? RollOffs[sd->getRollOff()] : ROLLOFF_AUTO);
int SymbolRate = BCD2INT(sd->getSymbolRate()) / 10; 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) { if (Setup.UpdateChannels >= 5) {
bool found = false; bool found = false;
bool forceTransponderUpdate = 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 }; static int Modulations[] = { QPSK, QAM_16, QAM_32, QAM_64, QAM_128, QAM_256, QAM_AUTO };
dtp.SetModulation(Modulations[min(sd->getModulation(), 6)]); dtp.SetModulation(Modulations[min(sd->getModulation(), 6)]);
int SymbolRate = BCD2INT(sd->getSymbolRate()) / 10; 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) { if (Setup.UpdateChannels >= 5) {
bool found = false; bool found = false;
bool forceTransponderUpdate = 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()]); dtp.SetGuard(GuardIntervals[sd->getGuardInterval()]);
static int TransmissionModes[] = { TRANSMISSION_MODE_2K, TRANSMISSION_MODE_8K, TRANSMISSION_MODE_4K, TRANSMISSION_MODE_AUTO }; static int TransmissionModes[] = { TRANSMISSION_MODE_2K, TRANSMISSION_MODE_8K, TRANSMISSION_MODE_4K, TRANSMISSION_MODE_AUTO };
dtp.SetTransmission(TransmissionModes[sd->getTransmissionMode()]); 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) { if (Setup.UpdateChannels >= 5) {
bool found = false; bool found = false;
bool forceTransponderUpdate = 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 *lcd = (SI::LogicalChannelDescriptor *)d;
SI::LogicalChannelDescriptor::LogicalChannel LogicalChannel; SI::LogicalChannelDescriptor::LogicalChannel LogicalChannel;
for (SI::Loop::Iterator it4; lcd->logicalChannelLoop.getNext(LogicalChannel, it4); ) { for (SI::Loop::Iterator it4; lcd->logicalChannelLoop.getNext(LogicalChannel, it4); ) {
int lcn = LogicalChannel.getLogicalChannelNumber();
int sid = LogicalChannel.getServiceId();
if (LogicalChannel.getVisibleServiceFlag()) { if (LogicalChannel.getVisibleServiceFlag()) {
int lcn = LogicalChannel.getLogicalChannelNumber();
int sid = LogicalChannel.getServiceId();
for (cChannel *Channel = Channels->First(); Channel; Channel = Channels->Next(Channel)) { for (cChannel *Channel = Channels->First(); Channel; Channel = Channels->Next(Channel)) {
if (!Channel->GroupSep() && Channel->Sid() == sid && Channel->Nid() == ts.getOriginalNetworkId() && Channel->Tid() == ts.getTransportStreamId()) { if (!Channel->GroupSep() && Channel->Sid() == sid && Channel->Nid() == ts.getOriginalNetworkId() && Channel->Tid() == ts.getTransportStreamId()) {
ChannelsModified |= Channel->SetLcn(lcn); 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 *lcd = (SI::HdSimulcastLogicalChannelDescriptor *)d;
SI::HdSimulcastLogicalChannelDescriptor::HdSimulcastLogicalChannel HdSimulcastLogicalChannel; SI::HdSimulcastLogicalChannelDescriptor::HdSimulcastLogicalChannel HdSimulcastLogicalChannel;
for (SI::Loop::Iterator it4; lcd->hdSimulcastLogicalChannelLoop.getNext(HdSimulcastLogicalChannel, it4); ) { for (SI::Loop::Iterator it4; lcd->hdSimulcastLogicalChannelLoop.getNext(HdSimulcastLogicalChannel, it4); ) {
int lcn = HdSimulcastLogicalChannel.getLogicalChannelNumber();
int sid = HdSimulcastLogicalChannel.getServiceId();
if (HdSimulcastLogicalChannel.getVisibleServiceFlag()) { if (HdSimulcastLogicalChannel.getVisibleServiceFlag()) {
int lcn = HdSimulcastLogicalChannel.getLogicalChannelNumber();
int sid = HdSimulcastLogicalChannel.getServiceId();
for (cChannel *Channel = Channels->First(); Channel; Channel = Channels->Next(Channel)) { for (cChannel *Channel = Channels->First(); Channel; Channel = Channels->Next(Channel)) {
if (!Channel->GroupSep() && Channel->Sid() == sid && Channel->Nid() == ts.getOriginalNetworkId() && Channel->Tid() == ts.getTransportStreamId()) { if (!Channel->GroupSep() && Channel->Sid() == sid && Channel->Nid() == ts.getOriginalNetworkId() && Channel->Tid() == ts.getTransportStreamId()) {
ChannelsModified |= Channel->SetLcn(lcn); ChannelsModified |= Channel->SetLcn(lcn);

52
pat.c
View File

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

8
pat.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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 #ifndef __PAT_H
@ -38,14 +38,12 @@ public:
void Trigger(int Sid = -1); 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. ///< Gets all CA descriptors for a given channel.
///< Copies all available CA descriptors for the given Source, Transponder and ServiceId ///< 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 ///< are copied that match one of the given CA system IDs (or all of them, if CaSystemIds
///< is 0xFFFF). ///< 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); int GetCaPids(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, int *Pids);
///< Gets all CA pids for a given channel. ///< 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 * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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 #ifndef __PLAYER_H
@ -57,6 +57,10 @@ public:
virtual bool GetIndex(int &Current, int &Total, bool SnapToIFrame = false) { return false; } virtual bool GetIndex(int &Current, int &Total, bool SnapToIFrame = false) { return false; }
// Returns the current and total frame index, optionally snapped to the // Returns the current and total frame index, optionally snapped to the
// nearest I-frame. // 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; } virtual bool GetReplayMode(bool &Play, bool &Forward, int &Speed) { return false; }
// Returns the current replay mode (if applicable). // Returns the current replay mode (if applicable).
// 'Play' tells whether we are playing or pausing, 'Forward' tells whether // '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 ///< 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 ///< current player. The return value is expected to be a short, single line
///< string. The default implementation returns an empty string. ///< string. The default implementation returns an empty string.
double FramesPerSecond(void) { return player->FramesPerSecond(); } double FramesPerSecond(void) const { return player->FramesPerSecond(); }
bool GetIndex(int &Current, int &Total, bool SnapToIFrame = false) { return player->GetIndex(Current, Total, SnapToIFrame); } bool GetIndex(int &Current, int &Total, bool SnapToIFrame = false) const { return player->GetIndex(Current, Total, SnapToIFrame); }
bool GetReplayMode(bool &Play, bool &Forward, int &Speed) { return player->GetReplayMode(Play, Forward, Speed); } 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 Launch(cControl *Control);
static void Attach(void); static void Attach(void);
static void Shutdown(void); static void Shutdown(void);

View File

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

View File

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

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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" #include "receiver.h"
@ -37,8 +37,10 @@ void cReceiver::SetPriority(int Priority)
bool cReceiver::AddPid(int Pid) bool cReceiver::AddPid(int Pid)
{ {
if (Pid) { if (Pid) {
if (numPids < MAXRECEIVEPIDS) if (numPids < MAXRECEIVEPIDS) {
pids[numPids++] = Pid; if (!WantsPid(Pid))
pids[numPids++] = Pid;
}
else { else {
dsyslog("too many PIDs in cReceiver (Pid = %d)", Pid); dsyslog("too many PIDs in cReceiver (Pid = %d)", Pid);
return false; return false;

View File

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

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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 #ifndef __RECORDING_H
@ -302,16 +302,18 @@ DEF_LIST_LOCK2(Recordings, DeletedRecordings);
class cRecordingsHandlerEntry; class cRecordingsHandlerEntry;
class cRecordingsHandler { class cRecordingsHandler : public cThread {
private: private:
cMutex mutex; cMutex mutex;
cList<cRecordingsHandlerEntry> operations; cList<cRecordingsHandlerEntry> operations;
bool finished; bool finished;
bool error; bool error;
cRecordingsHandlerEntry *Get(const char *FileName); cRecordingsHandlerEntry *Get(const char *FileName);
protected:
virtual void Action(void);
public: public:
cRecordingsHandler(void); cRecordingsHandler(void);
~cRecordingsHandler(); virtual ~cRecordingsHandler();
bool Add(int Usage, const char *FileNameSrc, const char *FileNameDst = NULL); bool Add(int Usage, const char *FileNameSrc, const char *FileNameDst = NULL);
///< Adds the given FileNameSrc to the recordings handler for (later) ///< Adds the given FileNameSrc to the recordings handler for (later)
///< processing. Usage can be either ruCut, ruMove or ruCopy. FileNameDst ///< processing. Usage can be either ruCut, ruMove or ruCopy. FileNameDst
@ -329,12 +331,6 @@ public:
///< Deletes/terminates all operations. ///< Deletes/terminates all operations.
int GetUsage(const char *FileName); int GetUsage(const char *FileName);
///< Returns the usage type for the given 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); bool Finished(bool &Error);
///< Returns true if all operations in the list have been finished. ///< Returns true if all operations in the list have been finished.
///< If there have been any errors, Errors will be set to true. ///< 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 * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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" #include "remux.h"
@ -603,6 +603,7 @@ cPatPmtParser::cPatPmtParser(bool UpdatePrimaryDevice)
void cPatPmtParser::Reset(void) void cPatPmtParser::Reset(void)
{ {
completed = false;
pmtSize = 0; pmtSize = 0;
patVersion = pmtVersion = -1; patVersion = pmtVersion = -1;
pmtPids[0] = 0; pmtPids[0] = 0;
@ -708,6 +709,7 @@ void cPatPmtParser::ParsePmt(const uchar *Data, int Length)
case 0x01: // STREAMTYPE_11172_VIDEO case 0x01: // STREAMTYPE_11172_VIDEO
case 0x02: // STREAMTYPE_13818_VIDEO case 0x02: // STREAMTYPE_13818_VIDEO
case 0x1B: // H.264 case 0x1B: // H.264
case 0x24: // H.265
vpid = stream.getPid(); vpid = stream.getPid();
vtype = stream.getStreamType(); vtype = stream.getStreamType();
ppid = Pmt.getPCRPid(); ppid = Pmt.getPCRPid();
@ -892,6 +894,7 @@ void cPatPmtParser::ParsePmt(const uchar *Data, int Length)
} }
} }
pmtVersion = Pmt.getVersionNumber(); pmtVersion = Pmt.getVersionNumber();
completed = true;
} }
else else
esyslog("ERROR: can't parse PMT"); esyslog("ERROR: can't parse PMT");
@ -1204,16 +1207,16 @@ private:
nutSequenceParameterSet = 7, nutSequenceParameterSet = 7,
nutAccessUnitDelimiter = 9, nutAccessUnitDelimiter = 9,
}; };
cTsPayload tsPayload;
uchar byte; // holds the current byte value in case of bitwise access 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 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) int zeroBytes; // the number of consecutive zero bytes (to detect 0x000003)
uint32_t scanner;
// Identifiers written in '_' notation as in "ITU-T H.264": // Identifiers written in '_' notation as in "ITU-T H.264":
bool separate_colour_plane_flag; bool separate_colour_plane_flag;
int log2_max_frame_num; int log2_max_frame_num;
bool frame_mbs_only_flag; bool frame_mbs_only_flag;
// protected:
cTsPayload tsPayload;
uint32_t scanner;
bool gotAccessUnitDelimiter; bool gotAccessUnitDelimiter;
bool gotSequenceParameterSet; bool gotSequenceParameterSet;
uchar GetByte(bool Raw = false); 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::cFrameDetector(int Pid, int Type) cFrameDetector::cFrameDetector(int Pid, int Type)
@ -1456,14 +1534,16 @@ void cFrameDetector::SetPid(int Pid, int Type)
{ {
pid = Pid; pid = Pid;
type = Type; 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; delete parser;
parser = NULL; parser = NULL;
if (type == 0x01 || type == 0x02) if (type == 0x01 || type == 0x02)
parser = new cMpeg2Parser; parser = new cMpeg2Parser;
else if (type == 0x1B) else if (type == 0x1B)
parser = new cH264Parser; 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; parser = new cAudioParser;
else if (type != 0) else if (type != 0)
esyslog("ERROR: unknown stream type %d (PID %d) in frame detector", type, pid); 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 * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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 #ifndef __REMUX_H
@ -361,6 +361,7 @@ private:
uint16_t compositionPageIds[MAXSPIDS]; uint16_t compositionPageIds[MAXSPIDS];
uint16_t ancillaryPageIds[MAXSPIDS]; uint16_t ancillaryPageIds[MAXSPIDS];
bool updatePrimaryDevice; bool updatePrimaryDevice;
bool completed;
protected: protected:
int SectionLength(const uchar *Data, int Length) { return (Length >= 3) ? ((int(Data[1]) & 0x0F) << 8)| Data[2] : 0; } int SectionLength(const uchar *Data, int Length) { return (Length >= 3) ? ((int(Data[1]) & 0x0F) << 8)| Data[2] : 0; }
public: public:
@ -397,6 +398,8 @@ public:
int Vtype(void) const { return vtype; } int Vtype(void) const { return vtype; }
///< Returns the video stream type as defined by the current PMT, or 0 if no video ///< Returns the video stream type as defined by the current PMT, or 0 if no video
///< stream type has been detected, yet. ///< 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 *Apids(void) const { return apids; }
const int *Dpids(void) const { return dpids; } const int *Dpids(void) const { return dpids; }
const int *Spids(void) const { return spids; } 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 * Parts of this file were inspired by the 'ringbuffy.c' from the
* LinuxDVB driver (see linuxtv.org). * 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" #include "ringbuffer.h"
@ -390,12 +390,13 @@ void cRingBufferLinear::Del(int Count)
// --- cFrame ---------------------------------------------------------------- // --- 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); count = abs(Count);
type = Type; type = Type;
index = Index; index = Index;
pts = Pts; pts = Pts;
independent = Type == ftAudio ? true : Independent;
if (Count < 0) if (Count < 0)
data = (uchar *)Data; data = (uchar *)Data;
else { else {

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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 #ifndef __RINGBUFFER_H
@ -113,8 +113,9 @@ private:
eFrameType type; eFrameType type;
int index; int index;
uint32_t pts; uint32_t pts;
bool independent;
public: 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. ///< Creates a new cFrame object.
///< If Count is negative, the cFrame object will take ownership of the given ///< 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. ///< Data. Otherwise it will allocate Count bytes of memory and copy Data.
@ -124,6 +125,7 @@ public:
eFrameType Type(void) const { return type; } eFrameType Type(void) const { return type; }
int Index(void) const { return index; } int Index(void) const { return index; }
uint32_t Pts(void) const { return pts; } uint32_t Pts(void) const { return pts; }
bool Independent(void) const { return independent; }
}; };
class cRingBufferFrame : public cRingBuffer { class cRingBufferFrame : public cRingBuffer {

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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" #include "skinclassic.h"
@ -352,8 +352,7 @@ void cSkinClassicDisplayMenu::SetEvent(const cEvent *Event)
const cFont *font = cFont::GetFont(fontOsd); const cFont *font = cFont::GetFont(fontOsd);
int y = y2; int y = y2;
cTextScroller ts; cTextScroller ts;
char t[32]; cString t = cString::sprintf("%s %s - %s", *Event->GetDateString(), *Event->GetTimeString(), *Event->GetEndTimeString());
snprintf(t, sizeof(t), "%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)); ts.Set(osd, x1, y, x2 - x1, y3 - y, t, font, Theme.Color(clrMenuEventTime), Theme.Color(clrBackground));
if (Event->Vps() && Event->Vps() != Event->StartTime()) { if (Event->Vps() && Event->Vps() != Event->StartTime()) {
cString buffer = cString::sprintf(" VPS: %s ", *Event->GetVpsString()); 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 * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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, // "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 xl = xi00;
int y = yi00; int y = yi00;
cTextScroller ts; cTextScroller ts;
char t[32]; cString t = cString::sprintf("%s %s - %s", *Event->GetDateString(), *Event->GetTimeString(), *Event->GetEndTimeString());
snprintf(t, sizeof(t), "%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)); ts.Set(osd, xl, y, xi01 - xl, yi01 - y, t, font, Theme.Color(clrEventTime), Theme.Color(clrBackground));
if (Event->Vps() && Event->Vps() != Event->StartTime()) { if (Event->Vps() && Event->Vps() != Event->StartTime()) {
cString buffer = cString::sprintf(" VPS: %s ", *Event->GetVpsString()); 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 * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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 // "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 xl = x3 + TextSpacing;
int y = y3; int y = y3;
cTextScroller ts; cTextScroller ts;
char t[32]; cString t = cString::sprintf("%s %s - %s", *Event->GetDateString(), *Event->GetTimeString(), *Event->GetEndTimeString());
snprintf(t, sizeof(t), "%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)); ts.Set(osd, xl, y, x4 - xl, y4 - y, t, font, Theme.Color(clrMenuEventTime), Theme.Color(clrBackground));
if (Event->Vps() && Event->Vps() != Event->StartTime()) { if (Event->Vps() && Event->Vps() != Event->StartTime()) {
cString buffer = cString::sprintf(" VPS: %s ", *Event->GetVpsString()); cString buffer = cString::sprintf(" VPS: %s ", *Event->GetVpsString());

View File

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

10
svdrp.c
View File

@ -10,7 +10,7 @@
* and interact with the Video Disk Recorder - or write a full featured * and interact with the Video Disk Recorder - or write a full featured
* graphical interface that sits on top of an SVDRP connection. * 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" #include "svdrp.h"
@ -1228,6 +1228,10 @@ void cSVDRPServer::CmdDELC(const char *Option)
int n = Channels->GetNextNormal(CurrentChannel->Index()); int n = Channels->GetNextNormal(CurrentChannel->Index());
if (n < 0) if (n < 0)
n = Channels->GetPrevNormal(CurrentChannel->Index()); 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); CurrentChannel = Channels->Get(n);
CurrentChannelNr = 0; // triggers channel switch below CurrentChannelNr = 0; // triggers channel switch below
} }
@ -1240,7 +1244,7 @@ void cSVDRPServer::CmdDELC(const char *Option)
if (!cDevice::PrimaryDevice()->Replaying() || cDevice::PrimaryDevice()->Transferring()) if (!cDevice::PrimaryDevice()->Replaying() || cDevice::PrimaryDevice()->Transferring())
Channels->SwitchTo(CurrentChannel->Number()); Channels->SwitchTo(CurrentChannel->Number());
else else
cDevice::SetCurrentChannel(CurrentChannel); cDevice::SetCurrentChannel(CurrentChannel->Number());
} }
Reply(250, "Channel \"%s\" deleted", Option); Reply(250, "Channel \"%s\" deleted", Option);
} }
@ -1899,7 +1903,7 @@ void cSVDRPServer::CmdMOVC(const char *Option)
if (!cDevice::PrimaryDevice()->Replaying() || cDevice::PrimaryDevice()->Transferring()) if (!cDevice::PrimaryDevice()->Replaying() || cDevice::PrimaryDevice()->Transferring())
Channels->SwitchTo(CurrentChannel->Number()); Channels->SwitchTo(CurrentChannel->Number());
else else
cDevice::SetCurrentChannel(CurrentChannel); cDevice::SetCurrentChannel(CurrentChannel->Number());
} }
isyslog("SVDRP < %s channel %d moved to %d", *connection, FromNumber, ToNumber); isyslog("SVDRP < %s channel %d moved to %d", *connection, FromNumber, ToNumber);
Reply(250,"Channel \"%d\" moved to \"%d\"", From, To); 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 * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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" #include "thread.h"
@ -151,6 +151,8 @@ void cCondVar::Broadcast(void)
cRwLock::cRwLock(bool PreferWriter) cRwLock::cRwLock(bool PreferWriter)
{ {
locked = 0;
writeLockThreadId = 0;
pthread_rwlockattr_t attr; pthread_rwlockattr_t attr;
pthread_rwlockattr_init(&attr); pthread_rwlockattr_init(&attr);
pthread_rwlockattr_setkind_np(&attr, PreferWriter ? PTHREAD_RWLOCK_PREFER_WRITER_NP : PTHREAD_RWLOCK_PREFER_READER_NP); 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)) if (!GetAbsTime(&abstime, TimeoutMs))
TimeoutMs = 0; TimeoutMs = 0;
} }
if (Write) if (Write) {
Result = TimeoutMs ? pthread_rwlock_timedwrlock(&rwlock, &abstime) : pthread_rwlock_wrlock(&rwlock); 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 else
Result = TimeoutMs ? pthread_rwlock_timedrdlock(&rwlock, &abstime) : pthread_rwlock_rdlock(&rwlock); Result = TimeoutMs ? pthread_rwlock_timedrdlock(&rwlock, &abstime) : pthread_rwlock_rdlock(&rwlock);
return Result == 0; return Result == 0;
@ -179,6 +188,13 @@ bool cRwLock::Lock(bool Write, int TimeoutMs)
void cRwLock::Unlock(void) 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); pthread_rwlock_unlock(&rwlock);
} }
@ -206,8 +222,8 @@ void cMutex::Lock(void)
void cMutex::Unlock(void) void cMutex::Unlock(void)
{ {
if (!--locked) if (!--locked)
pthread_mutex_unlock(&mutex); pthread_mutex_unlock(&mutex);
} }
// --- cThread --------------------------------------------------------------- // --- cThread ---------------------------------------------------------------
@ -474,9 +490,11 @@ void cStateLock::Unlock(cStateKey &StateKey, bool IncState)
if (StateKey.write && IncState && !explicitModify) if (StateKey.write && IncState && !explicitModify)
state++; state++;
StateKey.state = state; StateKey.state = state;
StateKey.write = false; if (StateKey.write) {
threadId = 0; StateKey.write = false;
explicitModify = false; threadId = 0;
explicitModify = false;
}
rwLock.Unlock(); rwLock.Unlock();
} }

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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 #ifndef __THREAD_H
@ -14,6 +14,8 @@
#include <stdio.h> #include <stdio.h>
#include <sys/types.h> #include <sys/types.h>
typedef pid_t tThreadId;
class cCondWait { class cCondWait {
private: private:
pthread_mutex_t mutex; pthread_mutex_t mutex;
@ -53,6 +55,8 @@ public:
class cRwLock { class cRwLock {
private: private:
pthread_rwlock_t rwlock; pthread_rwlock_t rwlock;
int locked;
tThreadId writeLockThreadId;
public: public:
cRwLock(bool PreferWriter = false); cRwLock(bool PreferWriter = false);
~cRwLock(); ~cRwLock();
@ -72,8 +76,6 @@ public:
void Unlock(void); void Unlock(void);
}; };
typedef pid_t tThreadId;
class cThread { class cThread {
friend class cThreadLock; friend class cThreadLock;
private: private:

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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" #include "timers.h"
@ -748,9 +748,9 @@ const cTimer *cTimers::GetById(int Id) const
return NULL; 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() && if (!ti->Remote() &&
ti->Channel() == Timer->Channel() && ti->Channel() == Timer->Channel() &&
(ti->WeekDays() && ti->WeekDays() == Timer->WeekDays() || !ti->WeekDays() && ti->Day() == Timer->Day()) && (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 * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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 #ifndef __TIMERS_H
@ -122,7 +122,7 @@ public:
cTimers(void); cTimers(void);
static const cTimers *GetTimersRead(cStateKey &StateKey, int TimeoutMs = 0); static const cTimers *GetTimersRead(cStateKey &StateKey, int TimeoutMs = 0);
///< Gets the list of timers for read access. If TimeoutMs is given, ///< 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 ///< Otherwise it will wait indefinitely. If no read lock can be
///< obtained within the given timeout, NULL will be returned. ///< obtained within the given timeout, NULL will be returned.
///< The list is locked and a pointer to it is returned if the state ///< The list is locked and a pointer to it is returned if the state
@ -170,7 +170,8 @@ public:
static int NewTimerId(void); static int NewTimerId(void);
const cTimer *GetById(int Id) const; const cTimer *GetById(int Id) const;
cTimer *GetById(int Id) { return const_cast<cTimer *>(static_cast<const cTimers *>(this)->GetById(Id)); }; 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; const cTimer *GetMatch(time_t t) const;
cTimer *GetMatch(time_t t) { return const_cast<cTimer *>(static_cast<const cTimers *>(this)->GetMatch(t)); }; 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; 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 * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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" #include "tools.h"
@ -2272,6 +2272,44 @@ void cListBase::Sort(void)
free(a); 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::cHashBase(int Size) cHashBase::cHashBase(int Size)

24
tools.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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 #ifndef __TOOLS_H
@ -609,7 +609,7 @@ public: \
else \ else \
list = c##Class::Get##Name##Read(stateKey); \ 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; } \ const c##Class *Name(void) const { return list; } \
c##Class *Name(void) { return const_cast<c##Class *>(list); } \ c##Class *Name(void) { return const_cast<c##Class *>(list); } \
} }
@ -775,6 +775,26 @@ public:
bool Load(const char *Directory, bool DirsOnly = false); 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 { class cHashObject : public cListObject {
friend class cHashBase; friend class cHashBase;
private: private:

36
vdr.c
View File

@ -22,7 +22,7 @@
* *
* The project's page is at http://www.tvdr.de * 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> #include <getopt.h>
@ -171,6 +171,9 @@ static void Watchdog(int signum)
// Something terrible must have happened that prevented the 'alarm()' from // Something terrible must have happened that prevented the 'alarm()' from
// being called in time, so let's get out of here: // being called in time, so let's get out of here:
esyslog("PANIC: watchdog timer expired - exiting!"); esyslog("PANIC: watchdog timer expired - exiting!");
#ifdef SDNOTIFY
sd_notify(0, "STOPPING=1\nSTATUS=PANIC");
#endif
exit(1); exit(1);
} }
@ -235,6 +238,10 @@ int main(int argc, char *argv[])
#if defined(VDR_USER) #if defined(VDR_USER)
VdrUser = VDR_USER; VdrUser = VDR_USER;
#endif #endif
#ifdef SDNOTIFY
time_t SdWatchdog;
int SdWatchdogTimeout = 0;
#endif
cArgs *Args = NULL; cArgs *Args = NULL;
if (argc == 1) { if (argc == 1) {
@ -914,6 +921,16 @@ int main(int argc, char *argv[])
} }
#ifdef SDNOTIFY #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"); sd_notify(0, "READY=1\nSTATUS=Ready");
#endif #endif
@ -976,6 +993,14 @@ int main(int argc, char *argv[])
dsyslog("max. latency time %d seconds", MaxLatencyTime); 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: // Handle channel and timer modifications:
{ {
// Channels and timers need to be stored in a consistent manner, // Channels and timers need to be stored in a consistent manner,
@ -1480,9 +1505,6 @@ int main(int argc, char *argv[])
ShutdownHandler.countdown.Cancel(); ShutdownHandler.countdown.Cancel();
} }
// Keep the recordings handler alive:
RecordingsHandler.Active();
if ((Now - LastInteract) > ACTIVITYTIMEOUT && !cRecordControls::Active() && !RecordingsHandler.Active() && (Now - cRemote::LastActivity()) > ACTIVITYTIMEOUT) { if ((Now - LastInteract) > ACTIVITYTIMEOUT && !cRecordControls::Active() && !RecordingsHandler.Active() && (Now - cRemote::LastActivity()) > ACTIVITYTIMEOUT) {
// Handle housekeeping tasks // Handle housekeeping tasks
@ -1568,5 +1590,11 @@ Exit:
closelog(); closelog();
if (HasStdin) if (HasStdin)
tcsetattr(STDIN_FILENO, TCSANOW, &savedTm); 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(); return ShutdownHandler.GetExitCode();
} }