diff options
author | Klaus Schmidinger <Klaus (dot) Schmidinger (at) tvdr (dot) de> | 2013-02-09 15:35:00 +0100 |
---|---|---|
committer | Dieter Hametner <dh (plus) vdr (at) gekrumbel (dot) de> | 2013-02-09 18:56:41 +0100 |
commit | 14bd32b9486980a99ca552ec4eda6a11ab3a286a (patch) | |
tree | d845a1325e4cef40875d87d882149e3b5a87fe18 /recording.c | |
parent | 889f7deeb4d75553f1d8acde2d2ba93775065a59 (diff) | |
download | vdr-patches-14bd32b9486980a99ca552ec4eda6a11ab3a286a.tar.gz vdr-patches-14bd32b9486980a99ca552ec4eda6a11ab3a286a.tar.bz2 |
Version 1.7.37
VDR developer version 1.7.37 is now available at
ftp://ftp.tvdr.de/vdr/Developer/vdr-1.7.37.tar.bz2
A 'diff' against the previous version is available at
ftp://ftp.tvdr.de/vdr/Developer/vdr-1.7.36-1.7.37.diff
MD5 checksums:
602dc7e678bcfcf075da36344a337562 vdr-1.7.37.tar.bz2
34e953fcffc112f316cbfc1f53915324 vdr-1.7.36-1.7.37.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.
Approaching version 2.0.0:
==========================
If all goes well, there should be no more functional or API changes
before the final version 2.0.0. There will just be a few more fixes.
From the HISTORY file:
- Now also using FindHeader() in cMpeg2Fixer::AdjTref() (pointed out by Sören Moch).
- Added missing template for DVBDIR to Make.config.template (reported by Derek Kelly).
- The LCARS menu now also works if the OSD has only 1bpp (two colors).
- Fixed possible garbage in the remaining time of the LCARS replay display in case the
hours change from two to one digit.
- Fixed upscaling bitmaps. The last row and column of the scaled bitmap was not filled,
which resulted in empty lines between scaled subtitles.
- Fixed a leftover line in case a two line subtitle was followed by a one line
subtitle on the dvbhddevice in "high level" OSD mode.
- Returning 0 from cDvbSdFfDevice::NumProvidedSystems() if option --outputonly is given.
- The index file is now closed after initially reading it if it is older than 3600 seconds.
- Improved responsiveness during replay when close to the recording's end.
- Fixed a leftover progress display in the LCARS main menu when replay of a recording
ends while the menu is open, and the live channel has no EPG information.
- Fixed possible audio chatter when a recording is replayed to its very end.
- Added dependency on 'i18n' to 'install-i18n' in the VDR Makefile (thanks to Tobias
Grimm).
- Changed several calls to Skins.Message() in vdr.c to Skins.QueueMessage() in order to
avoid a black screen while such a message is displayed in case the channel will be
switched (reported by Uwe Scheffler).
- Updated the Slovakian language texts (thanks to Milan Hrala).
- Improved LIRC timing for repeat function.
- When pausing live video, the current audio and subtitle tracks are now retained.
- Added some notes about plugin Makefiles to PLUGINS.html.
- Avoiding an extra key press event if the repeat function kicks in when controlling
VDR via the PC keyboard.
- The new options "Setup/Miscellaneous/Remote control repeat delay" and
"Setup/Miscellaneous/Remote control repeat delta" can be used to adjust the
behavior of the remote control in case a key is held pressed down for a while, so
that the repeat function kicks in (see MANUAL).
The builtin LIRC and KBD remote controls already use these parameters. It is
recommended that plugins that implement an interface to any kind of remote controls
also use the parameters Setup.RcRepeatDelay and Setup.RcRepeatDelta for the desired
purpose, and remove any setup options they might have that serve the same purpose.
- cTimer no longer does any special "VFAT" handling to shorten directory names to 40
characters. When a string is used as a directory name for a recording, the maximum
length of the directory path, as well as the individual directory names, is now
limited to the values specified by the new command line option --dirnames (see
man vdr(1) for details). For backwards compatibility the option --vfat is still
available and has the same effect as --dirnames=250,40,1.
- The macro MaxFileName is now obsolete and may be removed in future versions. Use
NAME_MAX directly instead.
- There is no more fixed limit to the maximum number of cPixmap objects an OSD can
create. However, a particular device may still be unable to create an arbitrary
number of pixmaps, due to limited resources. So it's always a good idea to use
as few pixmaps as possible.
- Fixed formatting and removed some superfluous break statements in vdr.c's command
line option switch.
Diffstat (limited to 'recording.c')
-rw-r--r-- | recording.c | 151 |
1 files changed, 130 insertions, 21 deletions
diff --git a/recording.c b/recording.c index 9cd0522..57248a0 100644 --- a/recording.c +++ b/recording.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: recording.c 2.83 2013/01/16 14:17:44 kls Exp $ + * $Id: recording.c 2.86 2013/02/08 09:02:07 kls Exp $ */ #include "recording.h" @@ -64,11 +64,11 @@ #define MARKSUPDATEDELTA 10 // seconds between checks for updating editing marks #define MININDEXAGE 3600 // seconds before an index file is considered no longer to be written -#define MAX_SUBTITLE_LENGTH 40 - #define MAX_LINK_LEVEL 6 -bool VfatFileSystem = false; +int DirectoryPathMax = PATH_MAX; +int DirectoryNameMax = NAME_MAX; +bool DirectoryEncoding = false; int InstanceId = 0; cRecordings DeletedRecordings(true); @@ -540,22 +540,30 @@ tCharExchange CharExchange[] = { { 0, 0 } }; +const char *InvalidChars = "\"\\/:*?|<>#"; + +bool NeedsConversion(const char *p) +{ + return DirectoryEncoding && + (strchr(InvalidChars, *p) // characters that can't be part of a Windows file/directory name + || *p == '.' && (!*(p + 1) || *(p + 1) == FOLDERDELIMCHAR)); // Windows can't handle '.' at the end of file/directory names +} + char *ExchangeChars(char *s, bool ToFileSystem) { char *p = s; while (*p) { - if (VfatFileSystem) { - // The VFAT file system can't handle all characters, so we + if (DirectoryEncoding) { + // Some file systems can't handle all characters, so we // have to take extra efforts to encode/decode them: if (ToFileSystem) { - const char *InvalidChars = "\"\\/:*?|<>#"; switch (*p) { // characters that can be mapped to other characters: case ' ': *p = '_'; break; case FOLDERDELIMCHAR: *p = '/'; break; // characters that have to be encoded: default: - if (strchr(InvalidChars, *p) || *p == '.' && (!*(p + 1) || *(p + 1) == FOLDERDELIMCHAR)) { // Windows can't handle '.' at the end of file/directory names + if (NeedsConversion(p)) { int l = p - s; if (char *NewBuffer = (char *)realloc(s, strlen(s) + 10)) { s = NewBuffer; @@ -610,6 +618,107 @@ char *ExchangeChars(char *s, bool ToFileSystem) return s; } +char *LimitNameLengths(char *s, int PathMax, int NameMax) +{ + // Limits the total length of the directory path in 's' to PathMax, and each + // individual directory name to NameMax. The lengths of characters that need + // conversion when using 's' as a file name are taken into account accordingly. + // If a directory name exceeds NameMax, it will be truncated. If the whole + // directory path exceeds PathMax, individual directory names will be shortened + // (from right to left) until the limit is met, or until the currently handled + // directory name consists of only a single character. All operations are performed + // directly on the given 's', which may become shorter (but never longer) than + // the original value. + // Returns a pointer to 's'. + int Length = strlen(s); + int PathLength = 0; + // Collect the resulting lengths of each character: + bool NameTooLong = false; + int8_t a[Length]; + int n = 0; + int NameLength = 0; + for (char *p = s; *p; p++) { + if (*p == FOLDERDELIMCHAR) { + a[n] = -1; // FOLDERDELIMCHAR is a single character, neg. sign marks it + NameTooLong |= NameLength > NameMax; + NameLength = 0; + PathLength += 1; + } + else if (NeedsConversion(p)) { + a[n] = 3; // "#xx" + NameLength += 3; + PathLength += 3; + } + else { + int8_t l = Utf8CharLen(p); + a[n] = l; + NameLength += l; + PathLength += l; + while (l-- > 1) { + a[++n] = 0; + p++; + } + } + n++; + } + NameTooLong |= NameLength > NameMax; + // Limit names to NameMax: + if (NameTooLong) { + while (n > 0) { + // Calculate the length of the current name: + int NameLength = 0; + int i = n; + int b = i; + while (i-- > 0 && a[i] >= 0) { + NameLength += a[i]; + b = i; + } + // Shorten the name if necessary: + if (NameLength > NameMax) { + int l = 0; + i = n; + while (i-- > 0 && a[i] >= 0) { + l += a[i]; + if (NameLength - l <= NameMax) { + memmove(s + i, s + n, Length - n + 1); + memmove(a + i, a + n, Length - n + 1); + Length -= n - i; + PathLength -= l; + break; + } + } + } + // Switch to the next name: + n = b - 1; + } + } + // Limit path to PathMax: + n = Length; + while (PathLength > PathMax && n > 0) { + // Calculate how much to cut off the current name: + int i = n; + int b = i; + int l = 0; + while (--i > 0 && a[i - 1] >= 0) { + if (a[i] > 0) { + l += a[i]; + b = i; + if (PathLength - l <= PathMax) + break; + } + } + // Shorten the name if necessary: + if (l > 0) { + memmove(s + b, s + n, Length - n + 1); + Length -= n - b; + PathLength -= l; + } + // Switch to the next name: + n = i - 1; + } + return s; +} + cRecording::cRecording(cTimer *Timer, const cEvent *Event) { resume = RESUME_NOT_INITIALIZED; @@ -628,16 +737,10 @@ cRecording::cRecording(cTimer *Timer, const cEvent *Event) // set up the actual name: const char *Title = Event ? Event->Title() : NULL; const char *Subtitle = Event ? Event->ShortText() : NULL; - char SubtitleBuffer[MAX_SUBTITLE_LENGTH]; if (isempty(Title)) Title = Timer->Channel()->Name(); if (isempty(Subtitle)) Subtitle = " "; - else if (strlen(Subtitle) > MAX_SUBTITLE_LENGTH) { - // let's make sure the Subtitle doesn't produce too long a file name: - Utf8Strn0Cpy(SubtitleBuffer, Subtitle, MAX_SUBTITLE_LENGTH); - Subtitle = SubtitleBuffer; - } const char *macroTITLE = strstr(Timer->File(), TIMERMACRO_TITLE); const char *macroEPISODE = strstr(Timer->File(), TIMERMACRO_EPISODE); if (macroTITLE || macroEPISODE) { @@ -872,9 +975,12 @@ const char *cRecording::FileName(void) const const char *fmt = isPesRecording ? NAMEFORMATPES : NAMEFORMATTS; int ch = isPesRecording ? priority : channel; int ri = isPesRecording ? lifetime : instanceId; - name = ExchangeChars(name, true); - fileName = strdup(cString::sprintf(fmt, VideoDirectory, name, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, ch, ri)); - name = ExchangeChars(name, false); + char *Name = LimitNameLengths(strdup(name), DirectoryPathMax - strlen(VideoDirectory) - 1 - 42, DirectoryNameMax); // 42 = length of an actual recording directory name (generated with DATAFORMATTS) plus some reserve + if (strcmp(Name, name) != 0) + dsyslog("recording file name '%s' truncated to '%s'", name, Name); + Name = ExchangeChars(Name, true); + fileName = strdup(cString::sprintf(fmt, VideoDirectory, Name, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, ch, ri)); + free(Name); } return fileName; } @@ -1743,12 +1849,14 @@ cIndexFile::cIndexFile(const char *FileName, bool Record, bool IsPesRecording, b esyslog("ERROR: can't read from file '%s'", *fileName); free(index); index = NULL; - close(f); - f = -1; } - // we don't close f here, see CatchUp()! else if (isPesRecording) ConvertFromPes(index, size); + if (!index || time(NULL) - buf.st_mtime >= MININDEXAGE) { + close(f); + f = -1; + } + // otherwise we don't close f here, see CatchUp()! } else LOG_ERROR_STR(*fileName); @@ -1863,7 +1971,8 @@ bool cIndexFile::CatchUp(int Index) LOG_ERROR_STR(*fileName); if (Index < last) break; - cCondWait::SleepMs(INDEXCATCHUPWAIT); + cCondVar CondVar; + CondVar.TimedWait(mutex, INDEXCATCHUPWAIT); } } return index != NULL; |