[vdr] Update to 2.0.6

Ville Skyttä scop at fedoraproject.org
Sun Mar 23 14:01:31 UTC 2014


commit f1fafbbdbc93750dc1381a54dba2b9ada1512f2d
Author: Ville Skyttä <ville.skytta at iki.fi>
Date:   Sun Mar 23 10:27:41 2014 +0200

    Update to 2.0.6
    
    - Drop NALU dump (N/A for 2.0.6 at the moment) and resumereset patches
    - Bring back jumpplay patch from yavdr

 .gitignore                   |    3 +-
 sources                      |    8 +-
 vdr-2.0.6-filetransfer.patch | 1242 ++++++++++++++++++++++++++++++++++++++++++
 vdr.spec                     |   29 +-
 4 files changed, 1266 insertions(+), 16 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 381a3e8..b8e3e8d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,5 +4,6 @@
 /vdr-timer-info-0.5-1.7.13.diff
 /vdr.epgsearch-exttimeredit-0.0.2.diff
 /vdr-1.7.29-hlcutter-0.2.3.diff
-/vdr-1.7.40-ttxtsubs.patch
 /vdr-2.1.2-naludump-0.1.diff
+/vdr-2.0.6-ttxtsubs.patch
+/opt-24_jumpplay.patch
diff --git a/sources b/sources
index 154e9f5..260a11f 100644
--- a/sources
+++ b/sources
@@ -3,8 +3,10 @@
 04511ae02243eb1bab94f3f45b59e574  vdr-timer-info-0.5-1.7.13.diff
 71f7281d55eba1957f4267f596b11e29  vdr.epgsearch-exttimeredit-0.0.2.diff
 da3a3ab8c2a42a320171b1648c3b3258  vdr-1.7.29-hlcutter-0.2.3.diff
-239727ecce9a79e146aa4ca7866a0e1e  vdr-1.7.40-ttxtsubs.patch
-6fe5d740c7fdb12af842de9c47b80fe8  vdr-2.0.3-vasarajanauloja.patch.gz
 d76b06a7bf1f458a02f2d1169776fb7f  vdr_2.0.3-1.debian.tar.bz2
 6ca3d3c0794492e475d6b7656acb45fe  vdr-2.1.2-naludump-0.1.diff
-f58b9836a60440fde84480a2e37ee91d  vdr-2.0.5.tar.bz2
+f6916524c302f3209fd0af507ab97387  vdr-2.0.6.tar.bz2
+5eb1ced307d11d94e88cf9b0ac8317c9  vdr-2.0.6-ttxtsubs.patch
+4ab8c7b2df034988632b01cb50f4ac87  opt-24_jumpplay.patch
+77a827cf356b3446d6c25ed31490b957  vdr-2.1.6-binaryskip.patch.gz
+427f940f34367f156f981921c7a9cc51  vdr-2.1.6-menuselection.patch.gz
diff --git a/vdr-2.0.6-filetransfer.patch b/vdr-2.0.6-filetransfer.patch
new file mode 100644
index 0000000..a20106b
--- /dev/null
+++ b/vdr-2.0.6-filetransfer.patch
@@ -0,0 +1,1242 @@
+diff -up vdr-2.0.6/cutter.c~ vdr-2.0.6/cutter.c
+--- vdr-2.0.6/cutter.c~	2013-08-21 16:43:46.000000000 +0300
++++ vdr-2.0.6/cutter.c	2014-03-23 11:43:03.385540419 +0200
+@@ -8,6 +8,7 @@
+  */
+ 
+ #include "cutter.h"
++#include "interface.h"
+ #include "menu.h"
+ #include "recording.h"
+ #include "remux.h"
+@@ -649,7 +650,7 @@ cCuttingThread *cCutter::cuttingThread =
+ bool cCutter::error = false;
+ bool cCutter::ended = false;
+ 
+-bool cCutter::Start(const char *FileName)
++bool cCutter::Start(const char *FileName, const char *TargetFileName, bool Overwrite)
+ {
+   cMutexLock MutexLock(&mutex);
+   if (!cuttingThread) {
+@@ -663,11 +664,16 @@ bool cCutter::Start(const char *FileName
+      if (cMark *First = FromMarks.GetNextBegin())
+         Recording.SetStartTime(Recording.Start() + (int(First->Position() / Recording.FramesPerSecond() + 30) / 60) * 60);
+ 
+-     const char *evn = Recording.PrefixFileName('%');
+-     if (evn && RemoveVideoFile(evn) && MakeDirs(evn, true)) {
++     cString evn = (TargetFileName && *TargetFileName) ? Recording.UpdateFileName(TargetFileName) : Recording.PrefixFileName('%');
++     if (!Overwrite && *evn && (access(*evn, F_OK) == 0) && !Interface->Confirm(tr("File already exists - overwrite?"))) {
++        do {
++           evn = PrefixVideoFileName(*evn, '%');
++        } while (*evn && (access(*evn, F_OK) == 0));
++        }
++     if (*evn && RemoveVideoFile(*evn) && MakeDirs(*evn, true)) {
+         // XXX this can be removed once RenameVideoFile() follows symlinks (see videodir.c)
+         // remove a possible deleted recording with the same name to avoid symlink mixups:
+-        char *s = strdup(evn);
++        char *s = strdup(*evn);
+         char *e = strrchr(s, '.');
+         if (e) {
+            if (strcmp(e, ".rec") == 0) {
+diff -up vdr-2.0.6/cutter.h~ vdr-2.0.6/cutter.h
+--- vdr-2.0.6/cutter.h~	2012-02-16 14:05:33.000000000 +0200
++++ vdr-2.0.6/cutter.h	2014-03-23 11:43:03.385540419 +0200
+@@ -24,7 +24,7 @@ private:
+   static bool error;
+   static bool ended;
+ public:
+-  static bool Start(const char *FileName);
++  static bool Start(const char *FileName, const char *TargetFileName = NULL, bool Overwrite = true);
+   static void Stop(void);
+   static bool Active(const char *FileName = NULL);
+          ///< Returns true if the cutter is currently active.
+diff -up vdr-2.0.6/dvbplayer.c~ vdr-2.0.6/dvbplayer.c
+--- vdr-2.0.6/dvbplayer.c~	2013-03-08 15:44:19.000000000 +0200
++++ vdr-2.0.6/dvbplayer.c	2014-03-23 11:43:03.386540440 +0200
+@@ -374,11 +374,16 @@ bool cDvbPlayer::Save(void)
+   if (index) {
+      int Index = ptsIndex.FindIndex(DeviceGetSTC());
+      if (Index >= 0) {
+-        Index -= int(round(RESUMEBACKUP * framesPerSecond));
+-        if (Index > 0)
+-           Index = index->GetNextIFrame(Index, false);
+-        else
++        int backup = int(round(RESUMEBACKUP * framesPerSecond));
++        if (Index >= index->Last() - backup)
+            Index = 0;
++        else {
++           Index -= backup;
++           if (Index > 0)
++              Index = index->GetNextIFrame(Index, false);
++           else
++              Index = 0;
++           }
+         if (Index >= 0)
+            return index->StoreResume(Index);
+         }
+diff -up vdr-2.0.6/filetransfer.c~ vdr-2.0.6/filetransfer.c
+--- vdr-2.0.6/filetransfer.c~	2014-03-23 11:43:03.386540440 +0200
++++ vdr-2.0.6/filetransfer.c	2014-03-23 11:43:03.386540440 +0200
+@@ -0,0 +1,281 @@
++/*
++ * filetransfer.c: The video file transfer facilities
++ *
++ * See the main source file 'vdr.c' for copyright information and
++ * how to reach the author.
++ *
++ * $Id: $
++ */
++
++#include "videodir.h"
++#include "filetransfer.h"
++
++static cString StripLastDirectory(const char *DirName)
++{
++  if (DirName && *DirName) {
++     cString s(DirName);
++     int l = strlen(*s);
++     const char *p = *s + l;
++     while (l > 0) {
++           if (*p-- == '/')
++              break;
++           l--;
++           }
++     if (l)
++        s = s.Truncate(l);
++     return s;
++     }
++  return NULL;
++}
++
++// --- cCopyingThread --------------------------------------------------------
++
++class cCopyingThread : public cThread {
++private:
++  const char *error;
++  bool deleteSource;
++  cString source;
++  cString target;
++protected:
++  virtual void Action(void);
++public:
++  cCopyingThread(const char *SourceName, const char *ToFileName, bool DeleteSource = false);
++  virtual ~cCopyingThread();
++  const char *Error(void) { return error; }
++  };
++
++cCopyingThread::cCopyingThread(const char *SourceName, const char *TargetName, bool DeleteSource)
++:cThread("copying"),
++ error(NULL),
++ deleteSource(DeleteSource),
++ source(SourceName),
++ target(TargetName)
++{
++  // add missing directory delimiters
++  const char *delim = "/";
++  if (!endswith(*source, delim))
++     source = cString::sprintf("%s%s", *source, delim);
++  if (!endswith(*target, delim))
++     target = cString::sprintf("%s%s", *target, delim);
++
++  Start();
++}
++
++cCopyingThread::~cCopyingThread()
++{
++  Cancel(3);
++}
++
++void cCopyingThread::Action(void)
++{
++  SetPriority(19);
++  SetIOPriority(7);
++
++  if (strcmp(*source, *target)) {
++     // validate target directory
++     if (strstr(*target, *source)) {
++        error = "invalid target";
++        return;
++        }
++
++     // recordings methods require the last directory delimiter to be stripped off
++     cString recname = target;
++     recname.Truncate(strlen(*recname) - 1);
++     Recordings.AddByName(*recname, false);
++
++     RemoveFileOrDir(*target);
++     if (!MakeDirs(*target, true)) {
++        error = "MakeDirs";
++        return;
++        }
++
++     if (deleteSource && EntriesOnSameFileSystem(*source, *target)) {
++        if (rename(*source, *target) == -1) {
++           error = "rename";
++           return;
++           }
++        // delete all empty source directories
++        recname = source;
++        recname.Truncate(strlen(*recname) - 1);
++        recname = StripLastDirectory(*recname);
++        do {
++           if (!RemoveEmptyDirectories(*recname, true))
++              break;
++           recname = StripLastDirectory(*recname);
++           }
++        while (strcmp(*recname, VideoDirectory));
++        }
++     else {
++        int required = DirSizeMB(*source);
++        int available = FreeDiskSpaceMB(*target);
++
++        // validate free space
++        if (required < available) {
++           cReadDir d(*source);
++           struct dirent *e;
++           bool success = true;
++
++           // allocate copying buffer
++           const int len = 1024 * 1024;
++           char *buffer = MALLOC(char, len);
++           if (!buffer) {
++              error = "MALLOC";
++              return;
++              }
++
++           // loop through all files, but skip all sub-directories
++           while (Running() && (e = d.Next()) != NULL) {
++                 // skip generic entries
++                 if (strcmp(e->d_name, ".") && strcmp(e->d_name, "..") && strcmp(e->d_name, "lost+found")) {
++                    cString sourceFile = cString::sprintf("%s%s", *source, e->d_name);
++                    cString targetFile = cString::sprintf("%s%s", *target, e->d_name);
++
++                    // copy only regular files
++                    struct stat sts;
++                    if (!stat(*sourceFile, &sts) && S_ISREG(sts.st_mode)) {
++                       int r = -1, w = -1;
++                       cUnbufferedFile *inputFile = cUnbufferedFile::Create(*sourceFile, O_RDONLY | O_LARGEFILE);
++                       cUnbufferedFile *outputFile = cUnbufferedFile::Create(*targetFile, O_RDWR | O_CREAT | O_LARGEFILE);
++
++                       // validate files
++                       if (!inputFile || !outputFile) {
++                          success = false;
++                          break;
++                          }
++
++                       // do actual copy
++                       do {
++                         r = inputFile->Read(buffer, len);
++                         if (r > 0)
++                            w = outputFile->Write(buffer, r);
++                         else
++                            w = 0;
++                       } while (Running() && r > 0 && w > 0);
++                       DELETENULL(inputFile);
++                       DELETENULL(outputFile);
++
++                       // validate result
++                       if (!Running() || r < 0 || w < 0) {
++                          success = false;
++                          break;
++                          }
++                       }
++                   }
++                }
++
++           // release allocated buffer
++           free(buffer);
++
++           // delete all created target files and directories
++           if (!success) {
++              target = StripLastDirectory(*target);
++              RemoveFileOrDir(*target, true);
++              target = StripLastDirectory(*target);
++              RemoveEmptyDirectories(*target, true);
++              error = "copy failed";
++              return;
++              }
++           }
++        else {
++           // delete all created empty target directories
++           recname = target;
++           recname.Truncate(strlen(*recname) - 1);
++           recname = StripLastDirectory(*recname);
++           do {
++              if (!RemoveEmptyDirectories(*recname, true))
++                 break;
++              recname = StripLastDirectory(*recname);
++              }
++           while (strcmp(*recname, VideoDirectory));
++           error = "insufficient free space";
++           return;
++           }
++        }
++
++     if (deleteSource) {
++        // Recordings' methods require the last directory delimiter to be stripped off
++        source.Truncate(strlen(*source) - 1);
++        cRecording *recording = Recordings.GetByName(*source);
++        if (recording->Delete())
++           Recordings.DelByName(*source, false);
++        target.Truncate(strlen(*target) - 1);
++        Recordings.UpdateByName(*target);
++        }
++
++     // Must inform all VDR instances about the modification
++     Recordings.TouchUpdate();
++     }
++}
++
++// --- cFileTransfer ----------------------------------------------------------------
++
++cMutex cFileTransfer::mutex;
++char *cFileTransfer::copiedVersionName = NULL;
++cCopyingThread *cFileTransfer::copyingThread = NULL;
++bool cFileTransfer::error = false;
++bool cFileTransfer::ended = false;
++
++bool cFileTransfer::Start(cRecording *Recording, const char *FileName, bool CopyOnly)
++{
++  cMutexLock MutexLock(&mutex);
++  if (!copyingThread) {
++     cString NewName = NewVideoFileName(Recording->FileName(), FileName);
++     error = false;
++     ended = false;
++     if (strlen(*NewName)) {
++        copiedVersionName = strdup(*NewName);
++        copyingThread = new cCopyingThread(Recording->FileName(), copiedVersionName, !CopyOnly);
++        return true;
++        }
++     }
++  return false;
++}
++
++void cFileTransfer::Stop(void)
++{
++  cMutexLock MutexLock(&mutex);
++  bool Interrupted = copyingThread && copyingThread->Active();
++  const char *Error = copyingThread ? copyingThread->Error() : NULL;
++  DELETENULL(copyingThread);
++  if (Interrupted || Error) {
++     if (Interrupted)
++        isyslog("file transfer has been interrupted");
++     if (Error)
++        esyslog("ERROR: '%s' during file transfer", Error);
++     RemoveVideoFile(copiedVersionName); //XXX what if this file is currently being replayed?
++     Recordings.DelByName(copiedVersionName);
++     free(copiedVersionName);
++     copiedVersionName = NULL;
++     }
++}
++
++bool cFileTransfer::Active(void)
++{
++  cMutexLock MutexLock(&mutex);
++  if (copyingThread) {
++     if (copyingThread->Active())
++        return true;
++     error = copyingThread->Error();
++     Stop();
++     free(copiedVersionName);
++     copiedVersionName = NULL;
++     ended = true;
++     }
++  return false;
++}
++
++bool cFileTransfer::Error(void)
++{
++  cMutexLock MutexLock(&mutex);
++  bool result = error;
++  error = false;
++  return result;
++}
++
++bool cFileTransfer::Ended(void)
++{
++  cMutexLock MutexLock(&mutex);
++  bool result = ended;
++  ended = false;
++  return result;
++}
+diff -up vdr-2.0.6/filetransfer.h~ vdr-2.0.6/filetransfer.h
+--- vdr-2.0.6/filetransfer.h~	2014-03-23 11:43:03.386540440 +0200
++++ vdr-2.0.6/filetransfer.h	2014-03-23 11:43:03.386540440 +0200
+@@ -0,0 +1,33 @@
++/*
++ * filetransfer.h: The video file transfer facilities
++ *
++ * See the main source file 'vdr.c' for copyright information and
++ * how to reach the author.
++ *
++ * $Id: $
++ */
++
++#ifndef __FILETRANSFER_H
++#define __FILETRANSFER_H
++
++#include "recording.h"
++#include "thread.h"
++
++class cCopyingThread;
++
++class cFileTransfer {
++private:
++  static cMutex mutex;
++  static char *copiedVersionName;
++  static cCopyingThread *copyingThread;
++  static bool error;
++  static bool ended;
++public:
++  static bool Start(cRecording *Recording, const char *NewName, bool CopyOnly = false);
++  static void Stop(void);
++  static bool Active(void);
++  static bool Error(void);
++  static bool Ended(void);
++  };
++
++#endif //__FILETRANSFER_H
+diff -up vdr-2.0.6/Makefile~ vdr-2.0.6/Makefile
+--- vdr-2.0.6/Makefile~	2013-03-11 17:01:01.000000000 +0200
++++ vdr-2.0.6/Makefile	2014-03-23 11:43:03.386540440 +0200
+@@ -67,8 +67,8 @@ endif
+ SILIB    = $(LSIDIR)/libsi.a
+ 
+ OBJS = audio.o channels.o ci.o config.o cutter.o device.o diseqc.o dvbdevice.o dvbci.o\
+-       dvbplayer.o dvbspu.o dvbsubtitle.o eit.o eitscan.o epg.o filter.o font.o i18n.o interface.o keys.o\
+-       lirc.o menu.o menuitems.o nit.o osdbase.o osd.o pat.o player.o plugin.o\
++       dvbplayer.o dvbspu.o dvbsubtitle.o eit.o eitscan.o epg.o filetransfer.o filter.o font.o i18n.o\
++       interface.o keys.o lirc.o menu.o menuitems.o nit.o osdbase.o osd.o pat.o player.o plugin.o\
+        receiver.o recorder.o recording.o remote.o remux.o ringbuffer.o sdt.o sections.o shutdown.o\
+        skinclassic.o skinlcars.o skins.o skinsttng.o sourceparams.o sources.o spu.o status.o svdrp.o themes.o thread.o\
+        timers.o tools.o transfer.o vdr.o videodir.o
+diff -up vdr-2.0.6/menu.c~ vdr-2.0.6/menu.c
+--- vdr-2.0.6/menu.c~	2014-02-26 13:42:28.000000000 +0200
++++ vdr-2.0.6/menu.c	2014-03-23 11:43:03.387540462 +0200
+@@ -18,6 +18,7 @@
+ #include "config.h"
+ #include "cutter.h"
+ #include "eitscan.h"
++#include "filetransfer.h"
+ #include "i18n.h"
+ #include "interface.h"
+ #include "plugin.h"
+@@ -2223,6 +2224,167 @@ void cMenuRecordingItem::SetMenuItem(cSk
+      DisplayMenu->SetItem(Text(), Index, Current, Selectable);
+ }
+ 
++// --- cMenuEditRecording ----------------------------------------------------
++
++class cMenuEditRecording : public cOsdMenu {
++private:
++  char name[MaxFileName];
++  cMenuEditStrItem *file;
++  cOsdItem *marksItem, *resumeItem;
++  bool isResume, isMarks;
++  cRecording *recording;
++  void SetHelpKeys(void);
++  eOSState SetFolder(void);
++public:
++  cMenuEditRecording(cRecording *Recording);
++  virtual eOSState ProcessKey(eKeys Key);
++};
++
++cMenuEditRecording::cMenuEditRecording(cRecording *Recording)
++:cOsdMenu(tr("Edit recording"), 14)
++{
++  cMarks marks;
++
++  file = NULL;
++  recording = Recording;
++
++  if (recording) {
++     Utf8Strn0Cpy(name, recording->Name(), sizeof(name));
++     Add(file = new cMenuEditStrItem(tr("File"), name, sizeof(name)));
++
++     Add(new cOsdItem("", osUnknown, false));
++
++     Add(new cOsdItem(cString::sprintf("%s:\t%s", tr("Date"), *DayDateTime(recording->Start())), osUnknown, false));
++
++     cChannel *channel = Channels.GetByChannelID(((cRecordingInfo *)recording->Info())->ChannelID());
++     if (channel)
++        Add(new cOsdItem(cString::sprintf("%s:\t%s", tr("Channel"), *ChannelString(channel, 0)), osUnknown, false));
++
++     int recLen = recording->LengthInSeconds();
++     if (recLen >= 0)
++        Add(new cOsdItem(cString::sprintf("%s:\t%d:%02d:%02d", tr("Length"), recLen / 3600, recLen / 60 % 60, recLen % 60), osUnknown, false));
++     else
++        recLen = 0;
++
++     int dirSize = DirSizeMB(recording->FileName());
++     cString bitRate = recLen ? cString::sprintf(" (%.2f MBit/s)", 8.0 * dirSize / recLen) : cString("");
++     Add(new cOsdItem(cString::sprintf("%s:\t%s", tr("Format"), recording->IsPesRecording() ? tr("PES") : tr("TS")), osUnknown, false));
++     Add(new cOsdItem((dirSize > 9999) ? cString::sprintf("%s:\t%.2f GB%s", tr("Size"), dirSize / 1024.0, *bitRate) : cString::sprintf("%s:\t%d MB%s", tr("Size"), dirSize, *bitRate), osUnknown, false));
++
++     Add(new cOsdItem("", osUnknown, false));
++
++     isMarks = marks.Load(recording->FileName(), recording->FramesPerSecond(), recording->IsPesRecording()) && marks.Count();
++     marksItem = new cOsdItem(tr("Delete marks information?"), osUser1, isMarks);
++     Add(marksItem);
++
++     cResumeFile ResumeFile(recording->FileName(), recording->IsPesRecording());
++     isResume = (ResumeFile.Read() != -1);
++     resumeItem = new cOsdItem(tr("Delete resume information?"), osUser2, isResume);
++     Add(resumeItem);
++     }
++
++  SetHelpKeys();
++}
++
++void cMenuEditRecording::SetHelpKeys(void)
++{
++  SetHelp(tr("Button$Folder"), tr("Button$Cut"), tr("Button$Copy"), tr("Button$Rename/Move"));
++}
++
++eOSState cMenuEditRecording::SetFolder(void)
++{
++  cMenuFolder *mf = (cMenuFolder *)SubMenu();
++  if (mf) {
++     cString Folder = mf->GetFolder();
++     char *p = strrchr(name, FOLDERDELIMCHAR);
++     if (p)
++        p++;
++     else
++        p = name;
++     if (!isempty(*Folder))
++        strn0cpy(name, cString::sprintf("%s%c%s", *Folder, FOLDERDELIMCHAR, p), sizeof(name));
++     else if (p != name)
++        memmove(name, p, strlen(p) + 1);
++     SetCurrent(file);
++     Display();
++     }
++  return CloseSubMenu();
++}
++
++eOSState cMenuEditRecording::ProcessKey(eKeys Key)
++{
++  eOSState state = cOsdMenu::ProcessKey(Key);
++
++  if (state == osUnknown) {
++     switch (Key) {
++       case kRed:
++            return AddSubMenu(new cMenuFolder(tr("Select folder"), &Folders, name));
++            break;
++       case kGreen:
++            if (!cCutter::Active()) {
++               if (!isMarks)
++                  Skins.Message(mtError, tr("No editing marks defined!"));
++               else if (!cCutter::Start(recording->FileName(), strcmp(recording->Name(), name) ? *NewVideoFileName(recording->FileName(), name) : NULL, false))
++                  Skins.Message(mtError, tr("Can't start editing process!"));
++               else
++                  Skins.Message(mtInfo, tr("Editing process started"));
++               }
++            else
++               Skins.Message(mtError, tr("Editing process already active!"));
++            return osContinue;
++       case kYellow:
++       case kBlue:
++            if (strcmp(recording->Name(), name)) {
++               if (!cFileTransfer::Active()) {
++                  if (cFileTransfer::Start(recording, name, (Key == kYellow)))
++                     Skins.Message(mtInfo, tr("File transfer started"));
++                  else
++                     Skins.Message(mtError, tr("Can't start file transfer!"));
++                  }
++               else
++                  Skins.Message(mtError, tr("File transfer already active!"));
++               }
++            return osRecordings;
++       default:
++            break;
++       }
++     return osContinue;
++     }
++  else if (state == osEnd && HasSubMenu())
++     state = SetFolder();
++  else if (state == osUser1) {
++     if (isMarks && Interface->Confirm(tr("Delete marks information?"))) {
++        cMarks marks;
++        marks.Load(recording->FileName(), recording->FramesPerSecond(), recording->IsPesRecording());
++        cMark *mark = marks.First();
++        while (mark) {
++              cMark *nextmark = marks.Next(mark);
++              marks.Del(mark);
++              mark = nextmark;
++              }
++        marks.Save();
++        isMarks = false;
++        marksItem->SetSelectable(isMarks);
++        SetCurrent(First());
++        Display();
++        }
++     return osContinue;
++     }
++  else if (state == osUser2) {
++     if (isResume && Interface->Confirm(tr("Delete resume information?"))) {
++        cResumeFile ResumeFile(recording->FileName(), recording->IsPesRecording());
++        ResumeFile.Delete();
++        isResume = false;
++        resumeItem->SetSelectable(isResume);
++        SetCurrent(First());
++        Display();
++        }
++     return osContinue;
++     }
++
++  return state;
++}
++
+ // --- cMenuRecordings -------------------------------------------------------
+ 
+ cMenuRecordings::cMenuRecordings(const char *Base, int Level, bool OpenSubMenus)
+@@ -2464,6 +2626,16 @@ eOSState cMenuRecordings::Sort(void)
+   return osContinue;
+ }
+ 
++eOSState cMenuRecordings::Edit(void)
++{
++  if (HasSubMenu() || Count() == 0)
++     return osContinue;
++  cMenuRecordingItem *ri = (cMenuRecordingItem *)Get(Current());
++  if (ri && !ri->IsDirectory() && ri->Recording())
++     return AddSubMenu(new cMenuEditRecording(ri->Recording()));
++  return osContinue;
++}
++
+ eOSState cMenuRecordings::ProcessKey(eKeys Key)
+ {
+   bool HadSubMenu = HasSubMenu();
+@@ -2477,7 +2649,7 @@ eOSState cMenuRecordings::ProcessKey(eKe
+        case kRed:    return (helpKeys > 1 && RecordingCommands.Count()) ? Commands() : Play();
+        case kGreen:  return Rewind();
+        case kYellow: return Delete();
+-       case kInfo:
++       case kInfo:   return Edit();
+        case kBlue:   return Info();
+        case k0:      return Sort();
+        case k1...k9: return Commands(Key);
+@@ -3385,6 +3557,7 @@ cMenuMain::cMenuMain(eOSState State, boo
+   replaying = false;
+   stopReplayItem = NULL;
+   cancelEditingItem = NULL;
++  cancelFileTransferItem = NULL;
+   stopRecordingItem = NULL;
+   recordControlsState = 0;
+   Set();
+@@ -3479,6 +3652,19 @@ bool cMenuMain::Update(bool Force)
+      result = true;
+      }
+ 
++  // File transfer control:
++  bool FileTransferActive = cFileTransfer::Active();
++  if (FileTransferActive && !cancelFileTransferItem) {
++     // TRANSLATORS: note the leading blank!
++     Add(cancelFileTransferItem = new cOsdItem(tr(" Cancel file transfer"), osCancelTransfer));
++     result = true;
++     }
++  else if (cancelFileTransferItem && !FileTransferActive) {
++     Del(cancelFileTransferItem->Index());
++     cancelFileTransferItem = NULL;
++     result = true;
++     }
++
+   // Record control:
+   if (cRecordControls::StateChanged(recordControlsState)) {
+      while (stopRecordingItem) {
+@@ -3527,6 +3713,12 @@ eOSState cMenuMain::ProcessKey(eKeys Key
+                           return osEnd;
+                           }
+                        break;
++    case osCancelTransfer:
++                       if (Interface->Confirm(tr("Cancel file transfer?"))) {
++                          cFileTransfer::Stop();
++                          return osEnd;
++                          }
++                       break;
+     case osPlugin:     {
+                          cMenuPluginItem *item = (cMenuPluginItem *)Get(Current());
+                          if (item) {
+@@ -4850,7 +5049,7 @@ void cReplayControl::EditCut(void)
+            Skins.Message(mtError, tr("No editing marks defined!"));
+         else if (!marks.GetNumSequences())
+            Skins.Message(mtError, tr("No editing sequences defined!"));
+-        else if (!cCutter::Start(fileName))
++        else if (!cCutter::Start(fileName, NULL, false))
+            Skins.Message(mtError, tr("Can't start editing process!"));
+         else
+            Skins.Message(mtInfo, tr("Editing process started"));
+diff -up vdr-2.0.6/menu.h~ vdr-2.0.6/menu.h
+--- vdr-2.0.6/menu.h~	2013-10-16 12:46:15.000000000 +0300
++++ vdr-2.0.6/menu.h	2014-03-23 11:43:03.387540462 +0200
+@@ -101,6 +101,7 @@ private:
+   bool replaying;
+   cOsdItem *stopReplayItem;
+   cOsdItem *cancelEditingItem;
++  cOsdItem *cancelFileTransferItem;
+   cOsdItem *stopRecordingItem;
+   int recordControlsState;
+   static cOsdObject *pluginOsdObject;
+@@ -206,6 +207,7 @@ private:
+   eOSState Info(void);
+   eOSState Sort(void);
+   eOSState Commands(eKeys Key = kNone);
++  eOSState Edit(void);
+ protected:
+   cString DirectoryName(void);
+ public:
+diff -up vdr-2.0.6/osdbase.h~ vdr-2.0.6/osdbase.h
+--- vdr-2.0.6/osdbase.h~	2012-12-07 11:49:35.000000000 +0200
++++ vdr-2.0.6/osdbase.h	2014-03-23 11:43:03.387540462 +0200
+@@ -30,6 +30,7 @@ enum eOSState { osUnknown,
+                 osStopRecord,
+                 osStopReplay,
+                 osCancelEdit,
++                osCancelTransfer,
+                 osSwitchDvb,
+                 osBack,
+                 osEnd,
+diff -up vdr-2.0.6/po/de_DE.po~ vdr-2.0.6/po/de_DE.po
+--- vdr-2.0.6/po/de_DE.po~	2014-03-22 12:54:15.569991437 +0200
++++ vdr-2.0.6/po/de_DE.po	2014-03-23 11:43:03.388540484 +0200
+@@ -1398,3 +1398,70 @@ msgstr "Disk"
+ 
+ msgid "free"
+ msgstr "frei"
++
++msgid "Edit recording"
++msgstr "Aufnahme bearbeiten"
++
++msgid "Button$Cut"
++msgstr "Schneiden"
++
++msgid "Button$Copy"
++msgstr "Kopieren"
++
++msgid "Button$Rename/Move"
++msgstr "Umbenennen/Bewegen"
++
++msgid "Date"
++msgstr "Datum"
++
++msgid "Length"
++msgstr "Länge"
++
++msgid "Format"
++msgstr "Format"
++
++msgid "PES"
++msgstr "PES"
++
++msgid "TS"
++msgstr "TS"
++
++msgid "Size"
++msgstr "Größe"
++
++msgid "Delete marks information?"
++msgstr "Gespeicherte Schnittmarken löschen?"
++
++msgid "Delete resume information?"
++msgstr "Gespeicherten Zeitpunkt der letzten Wiedergabe löschen?"
++
++msgid "File transfer started"
++msgstr "Dateiübertragung gestartet"
++
++msgid "Can't start file transfer!"
++msgstr "Dateiübertragung kann nicht gestartet werden!"
++
++msgid "File transfer already active!"
++msgstr "Dateiübertragung bereits aktiv!"
++ 
++#. TRANSLATORS: note the leading blank!
++msgid " Cancel file transfer"
++msgstr " Dateiübertragung beenden"
++
++msgid "Cancel file transfer?"
++msgstr "Dateiübertragung beenden?"
++
++msgid "Transfering file - shut down anyway?"
++msgstr "Übertrage Datei - trotzdem ausschalten?"
++
++msgid "Transfering file - restart anyway?"
++msgstr "Übertrage Datei - trotzdem neustarten?"
++
++msgid "File transfer failed!"
++msgstr "Dateiübertragung fehlgeschlagen!"
++
++msgid "File transfer finished"
++msgstr "Dateiübertragung fertiggestellt"
++
++msgid "File already exists - overwrite?"
++msgstr "Datei besteht bereits - überschreiben?"
+diff -up vdr-2.0.6/po/fi_FI.po~ vdr-2.0.6/po/fi_FI.po
+--- vdr-2.0.6/po/fi_FI.po~	2014-03-22 12:54:15.019890792 +0200
++++ vdr-2.0.6/po/fi_FI.po	2014-03-23 11:43:03.388540484 +0200
+@@ -1402,3 +1402,70 @@ msgstr "Levy"
+ 
+ msgid "free"
+ msgstr "vapaana"
++
++msgid "Edit recording"
++msgstr "Muokkaa tallennetta"
++
++msgid "Button$Cut"
++msgstr "Leikkaa"
++
++msgid "Button$Copy"
++msgstr "Kopioi"
++
++msgid "Button$Rename/Move"
++msgstr "Nimeä/Siirrä"
++
++msgid "Date"
++msgstr "Päiväys"
++
++msgid "Length"
++msgstr "Pituus"
++
++msgid "Format"
++msgstr "Tiedostomuoto"
++
++msgid "PES"
++msgstr "PES"
++
++msgid "TS"
++msgstr "TS"
++
++msgid "Size"
++msgstr "Koko"
++
++msgid "Delete marks information?"
++msgstr "Poista tallenteen merkinnät?"
++
++msgid "Delete resume information?"
++msgstr "Poista tallenteen paluutiedot?"
++
++msgid "File transfer started"
++msgstr "Tiedoston siirto aloitettu"
++
++msgid "Can't start file transfer!"
++msgstr "Tiedoston siirron aloitus epäonnistui!"
++
++msgid "File transfer already active!"
++msgstr "Tiedoston siirto on jo käynnissä!"
++ 
++#. TRANSLATORS: note the leading blank!
++msgid " Cancel file transfer"
++msgstr " Peru tiedoston siirto"
++
++msgid "Cancel file transfer?"
++msgstr "Perutaanko tiedoston siirto?"
++
++msgid "Transfering file - shut down anyway?"
++msgstr "Tiedoston siirto kesken - sammutetaanko?"
++
++msgid "Transfering file - restart anyway?"
++msgstr "Tiedoston siirto kesken - käynnistetäänkö uudelleen?"
++
++msgid "File transfer failed!"
++msgstr "Tiedoston siirto epäonnistui!"
++
++msgid "File transfer finished"
++msgstr "Tiedoston siirto valmis"
++
++msgid "File already exists - overwrite?"
++msgstr "Tiedosto on jo olemassa - ylikirjoitetaanko?"
+diff -up vdr-2.0.6/po/hu_HU.po~ vdr-2.0.6/po/hu_HU.po
+--- vdr-2.0.6/po/hu_HU.po~	2014-03-22 12:54:14.959879812 +0200
++++ vdr-2.0.6/po/hu_HU.po	2014-03-23 11:43:03.388540484 +0200
+@@ -1402,3 +1402,70 @@ msgstr "Lemez"
+ 
+ msgid "free"
+ msgstr "szabad"
++
++msgid "Edit recording"
++msgstr "Felvétel szerkesztése"
++
++msgid "Button$Cut"
++msgstr "Vágás"
++
++msgid "Button$Copy"
++msgstr "Másolás"
++
++msgid "Button$Rename/Move"
++msgstr "Áthelyezés"
++
++msgid "Date"
++msgstr "Dátum"
++
++msgid "Length"
++msgstr "Hossz"
++
++msgid "Format"
++msgstr "Formátum"
++
++msgid "PES"
++msgstr "PES"
++
++msgid "TS"
++msgstr "TS"
++
++msgid "Size"
++msgstr "Méret"
++
++msgid "Delete marks information?"
++msgstr "Vágópontok törlése?"
++
++msgid "Delete resume information?"
++msgstr "Lejátszott pozició törlése?"
++
++msgid "File transfer started"
++msgstr "Áthelyezés folyamatban"
++
++msgid "Can't start file transfer!"
++msgstr "Áthelyezés nem indítható"
++
++msgid "File transfer already active!"
++msgstr "Áthelyezés már aktív!"
++ 
++#. TRANSLATORS: note the leading blank!
++msgid " Cancel file transfer"
++msgstr " Áthelyezés megszakítása"
++
++msgid "Cancel file transfer?"
++msgstr "Áthelyezés megszakítása?"
++
++msgid "Transfering file - shut down anyway?"
++msgstr "Áthelyezése folyamatban - biztos leállítjuk?"
++
++msgid "Transfering file - restart anyway?"
++msgstr "Áthelyezés folyamatban - biztos újraindítjuk?"
++
++msgid "File transfer failed!"
++msgstr "Sikertelen áthelyezés!"
++
++msgid "File transfer finished"
++msgstr "Áthelyezés befejezve"
++
++msgid "File already exists - overwrite?"
++msgstr "A file létezik - felülírjam?"
+diff -up vdr-2.0.6/recording.c~ vdr-2.0.6/recording.c
+--- vdr-2.0.6/recording.c~	2014-03-16 13:03:18.000000000 +0200
++++ vdr-2.0.6/recording.c	2014-03-23 11:43:03.388540484 +0200
+@@ -1089,6 +1089,16 @@ const char *cRecording::PrefixFileName(c
+   return NULL;
+ }
+ 
++const char *cRecording::UpdateFileName(const char *FileName)
++{
++  if (FileName && *FileName) {
++     free(fileName);
++     fileName = strdup(FileName);
++     return fileName;
++     }
++  return NULL;
++}
++
+ int cRecording::HierarchyLevels(void) const
+ {
+   const char *s = name;
+@@ -1401,7 +1411,7 @@ void cRecordings::AddByName(const char *
+      }
+ }
+ 
+-void cRecordings::DelByName(const char *FileName)
++void cRecordings::DelByName(const char *FileName, bool RemoveRecording)
+ {
+   LOCK_THREAD;
+   cRecording *recording = GetByName(FileName);
+@@ -1409,7 +1419,7 @@ void cRecordings::DelByName(const char *
+      cThreadLock DeletedRecordingsLock(&DeletedRecordings);
+      Del(recording, false);
+      char *ext = strrchr(recording->fileName, '.');
+-     if (ext) {
++     if (ext && RemoveRecording) {
+         strncpy(ext, DELEXT, strlen(ext));
+         if (access(recording->FileName(), F_OK) == 0) {
+            recording->deleted = time(NULL);
+@@ -2437,7 +2447,7 @@ int ReadFrame(cUnbufferedFile *f, uchar
+ 
+ // --- Recordings Sort Mode --------------------------------------------------
+ 
+-eRecordingsSortMode RecordingsSortMode = rsmName;
++eRecordingsSortMode RecordingsSortMode = rsmTime;
+ 
+ bool HasRecordingsSortMode(const char *Directory)
+ {
+diff -up vdr-2.0.6/recording.h~ vdr-2.0.6/recording.h
+--- vdr-2.0.6/recording.h~	2013-12-25 12:54:05.000000000 +0200
++++ vdr-2.0.6/recording.h	2014-03-23 11:43:03.389540505 +0200
+@@ -120,6 +120,7 @@ public:
+   const char *Title(char Delimiter = ' ', bool NewIndicator = false, int Level = -1) const;
+   const cRecordingInfo *Info(void) const { return info; }
+   const char *PrefixFileName(char Prefix);
++  const char *UpdateFileName(const char *FileName);
+   int HierarchyLevels(void) const;
+   void ResetResume(void) const;
+   double FramesPerSecond(void) const { return framesPerSecond; }
+@@ -131,7 +132,7 @@ public:
+   int FileSizeMB(void) const;
+        ///< Returns the total file size of this recording (in MB), or -1 if the file
+        ///< size is unknown.
+-  bool IsNew(void) const { return GetResume() <= 0; }
++  bool IsNew(void) const { return GetResume() < 0; }
+   bool IsEdited(void) const;
+   bool IsPesRecording(void) const { return isPesRecording; }
+   bool IsOnVideoDirectoryFileSystem(void) const;
+@@ -193,7 +194,7 @@ public:
+   void ClearSortNames(void);
+   cRecording *GetByName(const char *FileName);
+   void AddByName(const char *FileName, bool TriggerUpdate = true);
+-  void DelByName(const char *FileName);
++  void DelByName(const char *FileName, bool RemoveRecording = true);
+   void UpdateByName(const char *FileName);
+   int TotalFileSizeMB(void);
+   double MBperMinute(void);
+diff -up vdr-2.0.6/shutdown.c~ vdr-2.0.6/shutdown.c
+--- vdr-2.0.6/shutdown.c~	2013-02-18 12:33:26.000000000 +0200
++++ vdr-2.0.6/shutdown.c	2014-03-23 11:43:03.389540505 +0200
+@@ -17,6 +17,7 @@
+ #include "channels.h"
+ #include "config.h"
+ #include "cutter.h"
++#include "filetransfer.h"
+ #include "i18n.h"
+ #include "interface.h"
+ #include "menu.h"
+@@ -171,6 +172,10 @@ bool cShutdownHandler::ConfirmShutdown(b
+      if (!Interactive || !Interface->Confirm(tr("Editing - shut down anyway?")))
+         return false;
+      }
++  if (cFileTransfer::Active()) {
++     if (!Interactive || !Interface->Confirm(tr("Transfering file - shut down anyway?")))
++        return false;
++     }
+ 
+   cTimer *timer = Timers.GetNextActiveTimer();
+   time_t Next = timer ? timer->StartTime() : 0;
+@@ -214,6 +219,10 @@ bool cShutdownHandler::ConfirmRestart(bo
+      if (!Interactive || !Interface->Confirm(tr("Editing - restart anyway?")))
+         return false;
+      }
++  if (cFileTransfer::Active()) {
++     if (!Interactive || !Interface->Confirm(tr("Transfering file - restart anyway?")))
++        return false;
++     }
+ 
+   cTimer *timer = Timers.GetNextActiveTimer();
+   time_t Next  = timer ? timer->StartTime() : 0;
+diff -up vdr-2.0.6/svdrp.c~ vdr-2.0.6/svdrp.c
+--- vdr-2.0.6/svdrp.c~	2013-02-17 15:18:01.000000000 +0200
++++ vdr-2.0.6/svdrp.c	2014-03-23 11:43:03.389540505 +0200
+@@ -31,6 +31,7 @@
+ #include "cutter.h"
+ #include "device.h"
+ #include "eitscan.h"
++#include "filetransfer.h"
+ #include "keys.h"
+ #include "menu.h"
+ #include "plugin.h"
+@@ -193,6 +194,11 @@ const char *HelpPages[] = {
+   "    After a CLRE command, no further EPG processing is done for 10\n"
+   "    seconds, so that data sent with subsequent PUTE commands doesn't\n"
+   "    interfere with data from the broadcasters.",
++  "CPYR <number> <new name>\n"
++  "    Copy the recording with the given number. Before a recording can be\n"
++  "    copied, an LSTR command must have been executed in order to retrieve\n"
++  "    the recording numbers. The numbers don't change during subsequent CPYR\n"
++  "    commands.",
+   "DELC <number>\n"
+   "    Delete channel.",
+   "DELR <number>\n"
+@@ -258,6 +264,11 @@ const char *HelpPages[] = {
+   "    used to easily activate or deactivate a timer.",
+   "MOVC <number> <to>\n"
+   "    Move a channel to a new position.",
++  "MOVR <number> <new name>\n"
++  "    Move the recording with the given number. Before a recording can be\n"
++  "    moved, an LSTR command must have been executed in order to retrieve\n"
++  "    the recording numbers. The numbers don't change during subsequent MOVR\n"
++  "    commands.",
+   "NEWC <settings>\n"
+   "    Create a new channel. Settings must be in the same format as returned\n"
+   "    by the LSTC command.",
+@@ -612,6 +623,32 @@ void cSVDRP::CmdCLRE(const char *Option)
+      }
+ }
+ 
++void cSVDRP::CmdCPYR(const char *Option)
++{
++  if (*Option) {
++     char *tail;
++     int n = strtol(Option, &tail, 10);
++     cRecording *recording = Recordings.Get(n - 1);
++     if (recording && tail && tail != Option) {
++        char *oldName = strdup(recording->Name());
++        tail = skipspace(tail);
++        if (!cFileTransfer::Active()) {
++           if (cFileTransfer::Start(recording, tail, true))
++              Reply(250, "Copying recording \"%s\" to \"%s\"", oldName, tail);
++           else
++              Reply(554, "Can't start file transfer");
++           }
++        else
++           Reply(554, "File transfer already active");
++        free(oldName);
++        }
++     else
++        Reply(550, "Recording \"%d\" not found%s", n, Recordings.Count() ? "" : " (use LSTR before copying)");
++     }
++  else
++     Reply(501, "Invalid Option \"%s\"", Option);
++}
++
+ void cSVDRP::CmdDELC(const char *Option)
+ {
+   if (*Option) {
+@@ -1320,6 +1357,32 @@ void cSVDRP::CmdMOVC(const char *Option)
+      Reply(501, "Missing channel number");
+ }
+ 
++void cSVDRP::CmdMOVR(const char *Option)
++{
++  if (*Option) {
++     char *tail;
++     int n = strtol(Option, &tail, 10);
++     cRecording *recording = Recordings.Get(n - 1);
++     if (recording && tail && tail != Option) {
++        char *oldName = strdup(recording->Name());
++        tail = skipspace(tail);
++        if (!cFileTransfer::Active()) {
++           if (cFileTransfer::Start(recording, tail))
++              Reply(250, "Moving recording \"%s\" to \"%s\"", oldName, tail);
++           else
++              Reply(554, "Can't start file transfer");
++           }
++        else
++           Reply(554, "File transfer already active");
++        free(oldName);
++        }
++     else
++        Reply(550, "Recording \"%d\" not found%s", n, Recordings.Count() ? "" : " (use LSTR before moving)");
++     }
++  else
++     Reply(501, "Invalid Option \"%s\"", Option);
++}
++
+ void cSVDRP::CmdNEWC(const char *Option)
+ {
+   if (*Option) {
+@@ -1644,6 +1707,7 @@ void cSVDRP::Execute(char *Cmd)
+   s = skipspace(s);
+   if      (CMD("CHAN"))  CmdCHAN(s);
+   else if (CMD("CLRE"))  CmdCLRE(s);
++  else if (CMD("CPYR"))  CmdCPYR(s);
+   else if (CMD("DELC"))  CmdDELC(s);
+   else if (CMD("DELR"))  CmdDELR(s);
+   else if (CMD("DELT"))  CmdDELT(s);
+@@ -1659,6 +1723,7 @@ void cSVDRP::Execute(char *Cmd)
+   else if (CMD("MODC"))  CmdMODC(s);
+   else if (CMD("MODT"))  CmdMODT(s);
+   else if (CMD("MOVC"))  CmdMOVC(s);
++  else if (CMD("MOVR"))  CmdMOVR(s);
+   else if (CMD("NEWC"))  CmdNEWC(s);
+   else if (CMD("NEWT"))  CmdNEWT(s);
+   else if (CMD("NEXT"))  CmdNEXT(s);
+diff -up vdr-2.0.6/svdrp.h~ vdr-2.0.6/svdrp.h
+--- vdr-2.0.6/svdrp.h~	2012-04-26 13:30:06.000000000 +0300
++++ vdr-2.0.6/svdrp.h	2014-03-23 11:43:03.389540505 +0200
+@@ -56,6 +56,7 @@ private:
+   void PrintHelpTopics(const char **hp);
+   void CmdCHAN(const char *Option);
+   void CmdCLRE(const char *Option);
++  void CmdCPYR(const char *Option);
+   void CmdDELC(const char *Option);
+   void CmdDELR(const char *Option);
+   void CmdDELT(const char *Option);
+@@ -71,6 +72,7 @@ private:
+   void CmdMODC(const char *Option);
+   void CmdMODT(const char *Option);
+   void CmdMOVC(const char *Option);
++  void CmdMOVR(const char *Option);
+   void CmdNEWC(const char *Option);
+   void CmdNEWT(const char *Option);
+   void CmdNEXT(const char *Option);
+diff -up vdr-2.0.6/vdr.c~ vdr-2.0.6/vdr.c
+--- vdr-2.0.6/vdr.c~	2014-01-26 14:45:00.000000000 +0200
++++ vdr-2.0.6/vdr.c	2014-03-23 11:43:03.389540505 +0200
+@@ -45,6 +45,7 @@
+ #include "dvbdevice.h"
+ #include "eitscan.h"
+ #include "epg.h"
++#include "filetransfer.h"
+ #include "i18n.h"
+ #include "interface.h"
+ #include "keys.h"
+@@ -1322,6 +1323,12 @@ int main(int argc, char *argv[])
+               else
+                  Skins.Message(mtInfo, tr("Editing process finished"));
+               }
++           if (!cFileTransfer::Active() && cFileTransfer::Ended()) {
++              if (cFileTransfer::Error())
++                 Skins.Message(mtError, tr("File transfer failed!"));
++              else
++                 Skins.Message(mtInfo, tr("File transfer finished"));
++              }
+            }
+ 
+         // SIGHUP shall cause a restart:
+@@ -1337,7 +1344,7 @@ int main(int argc, char *argv[])
+               ShutdownHandler.countdown.Cancel();
+            }
+ 
+-        if ((Now - LastInteract) > ACTIVITYTIMEOUT && !cRecordControls::Active() && !cCutter::Active() && !Interface->HasSVDRPConnection() && (Now - cRemote::LastActivity()) > ACTIVITYTIMEOUT) {
++        if ((Now - LastInteract) > ACTIVITYTIMEOUT && !cRecordControls::Active() && !cCutter::Active() && !cFileTransfer::Active() && !Interface->HasSVDRPConnection() && (Now - cRemote::LastActivity()) > ACTIVITYTIMEOUT) {
+            // Handle housekeeping tasks
+ 
+            // Shutdown:
+@@ -1387,6 +1394,7 @@ Exit:
+ 
+   PluginManager.StopPlugins();
+   cRecordControls::Shutdown();
++  cFileTransfer::Stop();
+   cCutter::Stop();
+   delete Menu;
+   cControl::Shutdown();
+diff -up vdr-2.0.6/videodir.c~ vdr-2.0.6/videodir.c
+--- vdr-2.0.6/videodir.c~	2012-09-30 15:06:33.000000000 +0300
++++ vdr-2.0.6/videodir.c	2014-03-23 11:43:03.390540526 +0200
+@@ -229,6 +229,22 @@ cString PrefixVideoFileName(const char *
+   return NULL;
+ }
+ 
++cString NewVideoFileName(const char *FileName, const char *NewDirName)
++{
++  char *NewDir = ExchangeChars(strdup(NewDirName), true);
++  if (NewDir) {
++     const char *p = FileName + strlen(FileName); // p points at the terminating 0
++     while (p-- > FileName) {
++           if (*p == '/')
++              break;
++           }
++     cString NewName = cString::sprintf("%s/%s%s", VideoDirectory, NewDir, p);
++     free(NewDir);
++     return NewName;
++     }
++  return NULL;
++}
++
+ void RemoveEmptyVideoDirectories(const char *IgnoreFiles[])
+ {
+   cVideoDirectory Dir;
+diff -up vdr-2.0.6/videodir.h~ vdr-2.0.6/videodir.h
+--- vdr-2.0.6/videodir.h~	2012-09-30 14:01:15.000000000 +0300
++++ vdr-2.0.6/videodir.h	2014-03-23 11:43:03.390540526 +0200
+@@ -23,6 +23,7 @@ bool RemoveVideoFile(const char *FileNam
+ bool VideoFileSpaceAvailable(int SizeMB);
+ int VideoDiskSpace(int *FreeMB = NULL, int *UsedMB = NULL); // returns the used disk space in percent
+ cString PrefixVideoFileName(const char *FileName, char Prefix);
++cString NewVideoFileName(const char *FileName, const char *NewDirName);
+ void RemoveEmptyVideoDirectories(const char *IgnoreFiles[] = NULL);
+ bool IsOnVideoDirectoryFileSystem(const char *FileName);
+ 
diff --git a/vdr.spec b/vdr.spec
index 19b456c..2b92397 100644
--- a/vdr.spec
+++ b/vdr.spec
@@ -20,10 +20,10 @@
 %global vdr_user  vdr
 %global vdr_group video
 # From APIVERSION in config.h
-%global apiver    2.0.0
+%global apiver    2.0.6
 
 Name:           vdr
-Version:        2.0.5
+Version:        2.0.6
 Release:        1%{?dist}
 Summary:        Video Disk Recorder
 
@@ -53,17 +53,18 @@ Source20:       %{name}-rcu.conf
 Source21:       %{name}-set-wakeup.sh
 Patch0:         %{name}-channel+epg.patch
 Patch1:         http://zap.tartarus.org/~ds/debian/dists/stable/main/source/vdr_1.4.5-2.ds.diff.gz
-Patch2:         http://www.saunalahti.fi/~rahrenbe/vdr/patches/vdr-2.0.3-vasarajanauloja.patch.gz
+# Extracted from original at http://www.saunalahti.fi/~rahrenbe/vdr/patches/vdr-2.0.3-vasarajanauloja.patch.gz
+Patch2:         %{name}-2.0.6-filetransfer.patch
 # Extracted from http://copperhead.htpc-forum.de/downloads/extensionpatch/extpngvdr1.7.21v1.diff.gz
 Patch3:         %{name}-1.7.21-plugin-missing.patch
 Patch4:         %{name}-1.7.41-paths.patch
 Patch5:         http://toms-cafe.de/vdr/download/vdr-timer-info-0.5-1.7.13.diff
 # http://article.gmane.org/gmane.linux.vdr/36097
 Patch6:         %{name}-1.5.18-syncearly.patch
-Patch7:         http://projects.vdr-developer.org/projects/plg-ttxtsubs/repository/revisions/master/raw/patches/vdr-1.7.40-ttxtsubs.patch
+Patch7:         http://projects.vdr-developer.org/projects/plg-ttxtsubs/repository/revisions/master/raw/patches/vdr-2.0.6-ttxtsubs.patch
 # Extracted from http://copperhead.htpc-forum.de/downloads/extensionpatch/extpngvdr1.7.21v1.diff.gz
 # Original at http://toms-cafe.de/vdr/download/vdr-jumpplay-1.0-1.7.6.diff
-Patch8:         %{name}-1.7.28-vasarajanauloja-jumpplay.patch
+Patch8:         https://raw.githubusercontent.com/flensrocker/vdr-yavdr/master/debian/patches/opt-24_jumpplay.patch
 # http://www.udo-richter.de/vdr/patches.en.html#hlcutter
 Patch9:         http://www.udo-richter.de/vdr/files/vdr-1.7.29-hlcutter-0.2.3.diff
 # http://www.udo-richter.de/vdr/naludump.en.html
@@ -74,12 +75,12 @@ Patch11:        %{name}-2.0.4-mainmenuhooks101.patch
 # Modified so that it applies over the timer-info patch
 Patch12:        %{name}-1.7.21-timercmd.patch
 Patch13:        http://projects.vdr-developer.org/git/vdr-plugin-epgsearch.git/plain/patches/vdr-1.5.17-progressbar-support-0.0.1.diff
-# Extracted from http://www.saunalahti.fi/~rahrenbe/vdr/patches/vdr-2.0.5-kamalasamala.patch.gz
-Patch14:        %{name}-2.0.5-vasarajanauloja-resetresume.patch
+Patch14:        http://www.saunalahti.fi/~rahrenbe/vdr/patches/vdr-2.1.6-binaryskip.patch.gz
 Patch15:        %{name}-1.7.37-fedora-pkgconfig.patch
 Patch16:        %{name}-1.7.21-jumpplay-finnish.patch
 Patch17:        http://projects.vdr-developer.org/git/vdr-plugin-epgsearch.git/plain/patches/vdr.epgsearch-exttimeredit-0.0.2.diff
 Patch18:        %{name}-timer-info-1.7.28.patch
+Patch19:        http://www.saunalahti.fi/~rahrenbe/vdr/patches/vdr-2.1.6-menuselection.patch.gz
 
 BuildRequires:  libjpeg-devel
 BuildRequires:  libcap-devel
@@ -105,9 +106,7 @@ Requires:       font(:lang=en)
 # shadow-utils >= 4.1.1 for useradd -N
 Requires(pre):  shadow-utils >= 2:4.1.1
 # systemd >= 189 for RestartPreventExitStatus=
-Requires(post): systemd >= 189
-Requires(preun): systemd >= 189
-Requires(postun): systemd >= 189
+Requires(post,preun,postun): systemd >= 189
 Provides:       vdr(abi)%{?_isa} = %{apiver}
 Obsoletes:      vdr-subtitles <= 0.5.0
 Obsoletes:      vdr-sky < 1.7.11
@@ -195,9 +194,9 @@ sed \
 # TODO: does not apply
 #patch6 -p0
 %patch7 -p1
-#TODO: patch8 -p1
+%patch8 -p1
 #TODO: patch9 -p1 -F 2
-%patch10 -p1
+#TODO, need one for 2.0.6: patch10 -p1
 %patch11 -p1
 %patch12 -p1
 # TODO: does not apply
@@ -208,6 +207,7 @@ sed \
 # TODO: build failure
 #patch17 -p0 -F 3
 %patch18 -p1
+%patch19 -p1
 
 for f in CONTRIBUTORS HISTORY UPDATE-1.4.0 README.timer-info \
     PLUGINS/src/dvbhddevice/HISTORY; do
@@ -553,6 +553,11 @@ useradd -r -g %{vdr_group} -d %{vardir} -s /sbin/nologin -M -N \
 
 
 %changelog
+* Sat Mar 22 2014 Ville Skyttä <ville.skytta at iki.fi> - 2.0.6-1
+- Update to 2.0.6
+- Drop NALU dump (N/A for 2.0.6 at the moment) and resumereset patches
+- Bring back jumpplay patch from yavdr
+
 * Tue Jan  7 2014 Ville Skyttä <ville.skytta at iki.fi> - 2.0.5-1
 - Update to 2.0.5, starting after lirc.service is no longer needed.
 - Remove restart logic from runvdr, handle it with systemd instead.


More information about the scm-commits mailing list