Sisyphus repository
Last update: 1 october 2023 | SRPMs: 18631 | Visits: 37837653
en ru br
ALT Linux repos
S:2.2.0-alt12
D:1.6.0-alt1
3.0: 1.3.15-alt1

Group :: Video
RPM: vdr

 Main   Changelog   Spec   Patches   Sources   Download   Gear   Bugs and FR  Repocop 

Patch: vdr-1.6.0-liemikuutio-1.21.diff
Download


diff -Nru vdr-1.6.0-vanilla/HISTORY-liemikuutio vdr-1.6.0-liemikuutio/HISTORY-liemikuutio
--- vdr-1.6.0-vanilla/HISTORY-liemikuutio	1970-01-01 02:00:00.000000000 +0200
+++ vdr-1.6.0-liemikuutio/HISTORY-liemikuutio	2008-05-08 22:47:59.000000000 +0300
@@ -0,0 +1,108 @@
+-----------------------------------
+Liemikuutio for Video Disc Recorder
+
+Maintainer: Rolf Ahrenberg
+-----------------------------------
+
+2006-01-08: Version 1.0
+
+- Based on enAIO with these original patches:
+  Simple recordings sorting by Walter@VDRPortal
+  Alternate rename recordings by Ralf Müller
+  Menu selection by Peter Dittmann
+  Recording length by Tobias Faust
+
+2006-01-15: Version 1.1
+
+- Removed patches already found in vdr-1.3.39.
+
+2006-01-25: Version 1.2
+
+- Added "Main menu command position" feature.
+
+2006-02-05: Version 1.3
+
+- Improved menu selection response.
+
+2006-04-18: Version 1.4
+
+- Added Estonian translation (Thanks to Arthur Konovalov).
+
+2006-04-30: Version 1.5
+
+- Added progress bar view into "What's on now?" menu.
+
+2006-06-06: Version 1.6
+
+- Added French translation (Thanks to ECLiPSE).
+
+2006-06-14: Version 1.7
+
+- Fixed RENR crash.
+
+2006-07-14: Version 1.8
+
+- Fixed RENR/OSD bug.
+
+2006-08-27: Version 1.9
+
+- Some modifications to the recording length and rename recordings
+  patches (Thanks to Firefly).
+- Added k1_k3_jumps_20s patch by Petri Hintukainen.
+
+2006-08-29: Version 1.10
+
+- The cRecording:Title() method now defaults to original formatting.
+
+2006-09-04: Version 1.11
+
+- Removed unused variable from cRecording::Title() method (Thanks to
+  C.Y.M.).
+- Some modifications to the rename recordings patch (Thanks to Firefly).
+
+2006-09-13: Version 1.12
+
+- More modifications to the rename recordings patch (Thanks to Firefly).
+
+2006-10-01: Version 1.13
+
+- Removed unnecessary syslog printing (Thanks to Firefly).
+
+2007-08-14: Version 1.14
+
+- Updated for vdr-1.5.7.
+
+2007-10-16: Version 1.15
+
+- Added recmenu play patch (Thanks to Ville Skyttä).
+- Updated French translation (Thanks to ECLiPSE).
+
+2007-11-04: Version 1.16
+
+- Updated for vdr-1.5.11.
+
+2007-12-08: Version 1.17
+
+- Added binary skip patch.
+- Removed k1_k3_jumps_20s patch.
+
+2008-02-17: Version 1.18
+
+- Updated for vdr-1.5.15.
+
+2008-03-02: Version 1.19
+
+- Modified binary skip to use kPrev and kNext keys and the skip is now
+  always shortened after a direction change (Thanks to Timo Eskola).
+- Readded k1_k3_jumps_20s patch.
+
+2008-04-04: Version 1.20
+
+- Added bitrate information into rename menu.
+- Readded the path editing support of rename recordings patch (Thanks
+  to Firefly).
+
+2008-05-08: Version 1.21
+
+- Fixed rename recordings (Thanks to Firefly).
+- Added a DVB subtitles hack for old recordings (Thanks to Anssi Hannula).
diff -Nru vdr-1.6.0-vanilla/config.c vdr-1.6.0-liemikuutio/config.c
--- vdr-1.6.0-vanilla/config.c	2008-03-27 21:43:25.000000000 +0200
+++ vdr-1.6.0-liemikuutio/config.c	2008-03-27 21:47:57.000000000 +0200
@@ -289,6 +289,11 @@
   InitialChannel = 0;
   InitialVolume = -1;
   EmergencyExit = 1;
+  ShowRecDate = 1;
+  ShowRecTime = 1;
+  ShowRecLength = 0;
+  ShowProgressBar = 0;
+  MenuCmdPosition = 0;
 }
 
 cSetup& cSetup::operator= (const cSetup &s)
@@ -462,6 +467,11 @@
   else if (!strcasecmp(Name, "InitialChannel"))      InitialChannel     = atoi(Value);
   else if (!strcasecmp(Name, "InitialVolume"))       InitialVolume      = atoi(Value);
   else if (!strcasecmp(Name, "EmergencyExit"))       EmergencyExit      = atoi(Value);
+  else if (!strcasecmp(Name, "ShowRecDate"))         ShowRecDate        = atoi(Value);
+  else if (!strcasecmp(Name, "ShowRecTime"))         ShowRecTime        = atoi(Value);
+  else if (!strcasecmp(Name, "ShowRecLength"))       ShowRecLength      = atoi(Value);
+  else if (!strcasecmp(Name, "ShowProgressBar"))     ShowProgressBar    = atoi(Value);
+  else if (!strcasecmp(Name, "MenuCmdPosition"))     MenuCmdPosition    = atoi(Value);
   else
      return false;
   return true;
@@ -545,6 +555,11 @@
   Store("InitialChannel",     InitialChannel);
   Store("InitialVolume",      InitialVolume);
   Store("EmergencyExit",      EmergencyExit);
+  Store("ShowRecDate",        ShowRecDate);
+  Store("ShowRecTime",        ShowRecTime);
+  Store("ShowRecLength",      ShowRecLength);
+  Store("ShowProgressBar",    ShowProgressBar);
+  Store("MenuCmdPosition",    MenuCmdPosition);
 
   Sort();
 
diff -Nru vdr-1.6.0-vanilla/config.h vdr-1.6.0-liemikuutio/config.h
--- vdr-1.6.0-vanilla/config.h	2008-03-27 21:43:25.000000000 +0200
+++ vdr-1.6.0-liemikuutio/config.h	2008-04-26 23:23:40.000000000 +0300
@@ -36,6 +36,8 @@
 // plugins to work with newer versions of the core VDR as long as no
 // VDR header files have changed.
 
+#define LIEMIKUUTIO  121
+
 #define MAXPRIORITY 99
 #define MAXLIFETIME 99
 
@@ -267,6 +269,7 @@
   int InitialChannel;
   int InitialVolume;
   int EmergencyExit;
+  int ShowRecDate, ShowRecTime, ShowRecLength, ShowProgressBar, MenuCmdPosition;
   int __EndData__;
   cSetup(void);
   cSetup& operator= (const cSetup &s);
diff -Nru vdr-1.6.0-vanilla/device.c vdr-1.6.0-liemikuutio/device.c
--- vdr-1.6.0-vanilla/device.c	2008-03-27 21:43:25.000000000 +0200
+++ vdr-1.6.0-liemikuutio/device.c	2008-05-08 22:50:10.000000000 +0300
@@ -1100,7 +1100,8 @@
      int LanguagePreference = INT_MAX; // higher than the maximum possible value
      for (int i = ttSubtitleFirst; i <= ttSubtitleLast; i++) {
          const tTrackId *TrackId = GetTrack(eTrackType(i));
-         if (TrackId && TrackId->id && I18nIsPreferredLanguage(Setup.SubtitleLanguages, TrackId->language, LanguagePreference))
+         if (TrackId && TrackId->id && (I18nIsPreferredLanguage(Setup.SubtitleLanguages, TrackId->language, LanguagePreference) ||
+             ((i == ttSubtitleFirst + 8) && !(*TrackId->language) && (LanguagePreference == INT_MAX))))
             PreferredTrack = eTrackType(i);
          }
      // Make sure we're set to an available subtitle track:
diff -Nru vdr-1.6.0-vanilla/menu.c vdr-1.6.0-liemikuutio/menu.c
--- vdr-1.6.0-vanilla/menu.c	2008-03-27 21:43:25.000000000 +0200
+++ vdr-1.6.0-liemikuutio/menu.c	2008-04-04 00:23:09.000000000 +0300
@@ -13,6 +13,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <math.h>
 #include "channels.h"
 #include "config.h"
 #include "cutter.h"
@@ -705,7 +706,22 @@
      Add(new cMenuEditBitItem( tr("VPS"),          &data.flags, tfVps));
      Add(new cMenuEditIntItem( tr("Priority"),     &data.priority, 0, MAXPRIORITY));
      Add(new cMenuEditIntItem( tr("Lifetime"),     &data.lifetime, 0, MAXLIFETIME));
-     Add(new cMenuEditStrItem( tr("File"),          data.file, sizeof(data.file)));
+
+     char* p = strrchr(data.file, '~');
+     if (p) {
+        p++;
+        Utf8Strn0Cpy(name, p, sizeof(name));
+        Utf8Strn0Cpy(path, data.file, sizeof(path));
+        p = strrchr(path, '~');
+        if (p)
+           p[0] = 0;
+        }
+     else {
+        Utf8Strn0Cpy(name, data.file, sizeof(name));
+        Utf8Strn0Cpy(path, "", sizeof(path));
+        }
+     Add(new cMenuEditStrItem( tr("File"),          name, sizeof(name), tr(FileNameChars)));
+     Add(new cMenuEditRecPathItem(tr("Path"),       path, sizeof(path)));
      SetFirstDayItem();
      }
   Timers.IncBeingEdited();
@@ -745,6 +761,10 @@
                           Skins.Message(mtError, tr("*** Invalid Channel ***"));
                           break;
                           }
+                       if(strlen(path))
+                          snprintf(data.file, sizeof(data.file), "%s~%s", path, name);
+                       else
+                          snprintf(data.file, sizeof(data.file), "%s", name);
                        if (!*data.file)
                           strcpy(data.file, data.Channel()->ShortName(true));
                        if (timer) {
@@ -1048,7 +1068,8 @@
   const cChannel *channel;
   bool withDate;
   int timerMatch;
-  cMenuScheduleItem(const cEvent *Event, cChannel *Channel = NULL, bool WithDate = false);
+  bool withBar;
+  cMenuScheduleItem(const cEvent *Event, cChannel *Channel = NULL, bool WithDate = false, bool WithBar = false);
   static void SetSortMode(eScheduleSortMode SortMode) { sortMode = SortMode; }
   static void IncSortMode(void) { sortMode = eScheduleSortMode((sortMode == ssmAllAll) ? ssmAllThis : sortMode + 1); }
   static eScheduleSortMode SortMode(void) { return sortMode; }
@@ -1058,12 +1079,13 @@
 
 cMenuScheduleItem::eScheduleSortMode cMenuScheduleItem::sortMode = ssmAllThis;
 
-cMenuScheduleItem::cMenuScheduleItem(const cEvent *Event, cChannel *Channel, bool WithDate)
+cMenuScheduleItem::cMenuScheduleItem(const cEvent *Event, cChannel *Channel, bool WithDate, bool WithBar)
 {
   event = Event;
   channel = Channel;
   withDate = WithDate;
   timerMatch = tmNone;
+  withBar = WithBar;
   Update(true);
 }
 
@@ -1080,6 +1102,17 @@
 
 static const char *TimerMatchChars = " tT";
 
+static const char * const ProgressBar[7] =
+{
+  "[      ]",
+  "[|     ]",
+  "[||    ]",
+  "[|||   ]",
+  "[||||  ]",
+  "[||||| ]",
+  "[||||||]"
+};
+
 bool cMenuScheduleItem::Update(bool Force)
 {
   bool result = false;
@@ -1095,7 +1128,14 @@
      if (channel && withDate)
         buffer = cString::sprintf("%d\t%.*s\t%.*s\t%s\t%c%c%c\t%s", channel->Number(), Utf8SymChars(csn, 6), csn, Utf8SymChars(eds, 6), *eds, *event->GetTimeString(), t, v, r, event->Title());
      else if (channel)
-        buffer = cString::sprintf("%d\t%.*s\t%s\t%c%c%c\t%s", channel->Number(), Utf8SymChars(csn, 6), csn, *event->GetTimeString(), t, v, r, event->Title());
+        if (Setup.ShowProgressBar && withBar) {
+           int progress = (int)roundf( (float)(time(NULL) - event->StartTime()) / (float)(event->Duration()) * 6.0 );
+           if (progress < 0) progress = 0;
+           else if (progress > 6) progress = 6;
+           buffer = cString::sprintf("%d\t%.*s\t%s\t%s\t%c%c%c\t%s", channel->Number(), Utf8SymChars(csn, 6), csn, *event->GetTimeString(), ProgressBar[progress], t, v, r, event->Title());
+           }
+        else
+           buffer = cString::sprintf("%d\t%.*s\t%s\t%c%c%c\t%s", channel->Number(), Utf8SymChars(csn, 6), csn, *event->GetTimeString(), t, v, r, event->Title());
      else
         buffer = cString::sprintf("%.*s\t%s\t%c%c%c\t%s", Utf8SymChars(eds, 6), *eds, *event->GetTimeString(), t, v, r, event->Title());
      SetText(buffer);
@@ -1129,7 +1169,7 @@
 const cEvent *cMenuWhatsOn::scheduleEvent = NULL;
 
 cMenuWhatsOn::cMenuWhatsOn(const cSchedules *Schedules, bool Now, int CurrentChannelNr)
-:cOsdMenu(Now ? tr("What's on now?") : tr("What's on next?"), CHNUMWIDTH, 7, 6, 4)
+:cOsdMenu(Now ? tr("What's on now?") : tr("What's on next?"), CHNUMWIDTH, 7, 6, 4, 4)
 {
   now = Now;
   helpKeys = -1;
@@ -1141,7 +1181,7 @@
          if (Schedule) {
             const cEvent *Event = Now ? Schedule->GetPresentEvent() : Schedule->GetFollowingEvent();
             if (Event)
-               Add(new cMenuScheduleItem(Event, Channel), Channel->Number() == CurrentChannelNr);
+               Add(new cMenuScheduleItem(Event, Channel, false, Now), Channel->Number() == CurrentChannelNr);
             }
          }
       }
@@ -1883,7 +1923,7 @@
   fileName = strdup(Recording->FileName());
   name = NULL;
   totalEntries = newEntries = 0;
-  SetText(Recording->Title('\t', true, Level));
+  SetText(Recording->Title('\t', true, Level, false));
   if (*Text() == '\t')
      name = strdup(Text() + 2); // 'Text() + 2' to skip the two '\t'
 }
@@ -1899,13 +1939,155 @@
   totalEntries++;
   if (New)
      newEntries++;
-  SetText(cString::sprintf("%d\t%d\t%s", totalEntries, newEntries, name));
+  switch (Setup.ShowRecTime + Setup.ShowRecDate + Setup.ShowRecLength) {
+     case 0:
+          SetText(cString::sprintf("%s", name));
+          break;
+     case 1:
+          SetText(cString::sprintf("%d\t%s", totalEntries, name));
+          break;
+     case 2:
+     default:
+          SetText(cString::sprintf("%d\t%d\t%s", totalEntries, newEntries, name));
+          break;
+     case 3:
+          SetText(cString::sprintf("%d\t%d\t\t%s", totalEntries, newEntries, name));
+          break;
+     }
+}
+
+// --- cMenuRenameRecording --------------------------------------------------
+
+class cMenuRenameRecording : public cOsdMenu {
+private:
+  int lifetime;
+  int priority;
+  char name[MaxFileName];
+  char path[MaxFileName];
+  cOsdItem *marksItem, *resumeItem;
+  bool isResume, isMarks;
+  cRecording *recording;
+public:
+  cMenuRenameRecording(cRecording *Recording);
+  virtual eOSState ProcessKey(eKeys Key);
+};
+
+cMenuRenameRecording::cMenuRenameRecording(cRecording *Recording)
+:cOsdMenu(tr("Rename recording"), 12)
+{
+  cMarks marks;
+
+  recording = Recording;
+  priority = recording->priority;
+  lifetime = recording->lifetime;
+
+  char* p = strrchr(recording->Name(), '~');
+  if (p) {
+     p++;
+     Utf8Strn0Cpy(name, p, sizeof(name));
+     Utf8Strn0Cpy(path, recording->Name(), sizeof(path));
+     p = strrchr(path, '~');
+     if (p)
+        p[0] = 0;
+     }
+  else {
+     Utf8Strn0Cpy(name, recording->Name(), sizeof(name));
+     Utf8Strn0Cpy(path, "", sizeof(path));
+     }
+  Add(new cMenuEditStrItem(tr("Name"),      name,     sizeof(name), tr(FileNameChars)));
+  Add(new cMenuEditRecPathItem(tr("Path"),  path,     sizeof(path)                   ));
+  Add(new cMenuEditIntItem(tr("Priority"), &priority, 0,            MAXPRIORITY      ));
+  Add(new cMenuEditIntItem(tr("Lifetime"), &lifetime, 0,            MAXLIFETIME      ));
+
+  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));
+
+  cIndexFile *index = new cIndexFile(recording->FileName(), false);
+  int recLen = 0;
+  if (index) {
+     recLen = index->Last() / FRAMESPERSEC;
+     Add(new cOsdItem(cString::sprintf("%s:\t%s", tr("Length"), *IndexToHMSF(index->Last())), osUnknown, false));
+     delete index;
+     }
+
+  int dirSize = DirSizeMB(recording->FileName());
+  cString bitRate = recLen ? cString::sprintf(" (%.2f MBit/s)", 8.0 * dirSize / recLen) : cString("");
+  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()) && marks.Count();
+  marksItem = new cOsdItem(tr("Delete marks information?"), osUser1, isMarks);
+  Add(marksItem);
+
+  cResumeFile ResumeFile(recording->FileName());
+  isResume = (ResumeFile.Read() != -1);
+  resumeItem = new cOsdItem(tr("Delete resume information?"), osUser2, isResume);
+  Add(resumeItem);
+}
+
+eOSState cMenuRenameRecording::ProcessKey(eKeys Key)
+{
+  eOSState state = cOsdMenu::ProcessKey(Key);
+
+  if (state == osUnknown) {
+     if (Key == kOk) {
+        char buffer[MaxFileName];
+        if (Utf8StrLen(path))
+           snprintf(buffer, sizeof(buffer), "%s~%s", path, name);
+        else
+           snprintf(buffer, sizeof(buffer), "%s", name);
+        if (recording->Rename(buffer, &priority, &lifetime)) {
+           Recordings.ChangeState();
+           Recordings.TouchUpdate();
+           return osRecordings;
+           }
+        else
+           Skins.Message(mtError, tr("Error while accessing recording!"));
+        }
+     return osContinue;
+     }
+  else if (state == osUser1) {
+     if (isMarks && Interface->Confirm(tr("Delete marks information?"))) {
+        cMarks marks;
+        marks.Load(recording->FileName());
+        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());
+        ResumeFile.Delete();
+        isResume = false;
+        resumeItem->SetSelectable(isResume);
+        SetCurrent(First());
+        Display();
+        }
+     return osContinue;
+     }
+  return state;
 }
 
 // --- cMenuRecordings -------------------------------------------------------
 
 cMenuRecordings::cMenuRecordings(const char *Base, int Level, bool OpenSubMenus)
-:cOsdMenu(Base ? Base : tr("Recordings"), 9, 7)
+:cOsdMenu(Base ? Base : tr("Recordings"), 9, 7, 7)
 {
   base = Base ? strdup(Base) : NULL;
   level = Setup.RecordingDirs ? Level : -1;
@@ -2136,6 +2318,19 @@
   return osContinue;
 }
 
+eOSState cMenuRecordings::Rename(void)
+{
+  if (HasSubMenu() || Count() == 0)
+     return osContinue;
+  cMenuRecordingItem *ri = (cMenuRecordingItem *)Get(Current());
+  if (ri && !ri->IsDirectory()) {
+     cRecording *recording = GetRecording(ri);
+     if (recording)
+        return AddSubMenu(new cMenuRenameRecording(recording));
+     }
+  return osContinue;
+}
+
 eOSState cMenuRecordings::ProcessKey(eKeys Key)
 {
   bool HadSubMenu = HasSubMenu();
@@ -2150,7 +2345,12 @@
        case kYellow: return Delete();
        case kInfo:
        case kBlue:   return Info();
-       case k1...k9: return Commands(Key);
+       case k0:      DirOrderState = !DirOrderState;
+                     Set(true);
+                     return osContinue;
+       case k8:      return Rename();
+       case k9:
+       case k1...k7: return Commands(Key);
        case kNone:   if (Recordings.StateChanged(recordingsState))
                         Set(true);
                      break;
@@ -2276,6 +2476,7 @@
   Add(new cMenuEditBoolItem(tr("Setup.OSD$Scroll wraps"),           &data.MenuScrollWrap));
   Add(new cMenuEditBoolItem(tr("Setup.OSD$Menu key closes"),        &data.MenuKeyCloses));
   Add(new cMenuEditBoolItem(tr("Setup.OSD$Recording directories"),  &data.RecordingDirs));
+  Add(new cMenuEditBoolItem(tr("Setup.OSD$Main menu command position"), &data.MenuCmdPosition, tr("bottom"), tr("top")));
   SetCurrent(Get(current));
   Display();
 }
@@ -2380,6 +2581,7 @@
   Add(new cMenuEditIntItem( tr("Setup.EPG$EPG scan timeout (h)"),      &data.EPGScanTimeout));
   Add(new cMenuEditIntItem( tr("Setup.EPG$EPG bugfix level"),          &data.EPGBugfixLevel, 0, MAXEPGBUGFIXLEVEL));
   Add(new cMenuEditIntItem( tr("Setup.EPG$EPG linger time (min)"),     &data.EPGLinger, 0));
+  Add(new cMenuEditBoolItem(tr("Setup.EPG$Show progress bar"),         &data.ShowProgressBar));
   Add(new cMenuEditBoolItem(tr("Setup.EPG$Set system time"),           &data.SetSystemTime));
   if (data.SetSystemTime)
      Add(new cMenuEditTranItem(tr("Setup.EPG$Use time from transponder"), &data.TimeTransponder, &data.TimeSource));
@@ -2758,6 +2960,9 @@
   Add(new cMenuEditIntItem( tr("Setup.Recording$Instant rec. time (min)"),   &data.InstantRecordTime, 1, MAXINSTANTRECTIME));
   Add(new cMenuEditIntItem( tr("Setup.Recording$Max. video file size (MB)"), &data.MaxVideoFileSize, MINVIDEOFILESIZE, MAXVIDEOFILESIZE));
   Add(new cMenuEditBoolItem(tr("Setup.Recording$Split edited files"),        &data.SplitEditedFiles));
+  Add(new cMenuEditBoolItem(tr("Setup.Recording$Show date"),                 &data.ShowRecDate));
+  Add(new cMenuEditBoolItem(tr("Setup.Recording$Show time"),                 &data.ShowRecTime));
+  Add(new cMenuEditBoolItem(tr("Setup.Recording$Show length"),               &data.ShowRecLength));
 }
 
 // --- cMenuSetupReplay ------------------------------------------------------
@@ -3045,6 +3250,7 @@
      // Replay control:
      if (replaying && !stopReplayItem)
         // TRANSLATORS: note the leading blank!
+        if (Setup.MenuCmdPosition) Ins(stopReplayItem = new cOsdItem(tr(" Stop replaying"), osStopReplay)); else
         Add(stopReplayItem = new cOsdItem(tr(" Stop replaying"), osStopReplay));
      else if (stopReplayItem && !replaying) {
         Del(stopReplayItem->Index());
@@ -3059,6 +3265,7 @@
   bool CutterActive = cCutter::Active();
   if (CutterActive && !cancelEditingItem) {
      // TRANSLATORS: note the leading blank!
+     if (Setup.MenuCmdPosition) Ins(cancelEditingItem = new cOsdItem(tr(" Cancel editing"), osCancelEdit)); else
      Add(cancelEditingItem = new cOsdItem(tr(" Cancel editing"), osCancelEdit));
      result = true;
      }
@@ -3079,6 +3286,7 @@
      while ((s = cRecordControls::GetInstantId(s)) != NULL) {
            cOsdItem *item = new cOsdItem(osStopRecord);
            item->SetText(cString::sprintf("%s%s", tr(STOP_RECORDING), s));
+           if (Setup.MenuCmdPosition) Ins(item); else
            Add(item);
            if (!stopRecordingItem)
               stopRecordingItem = item;
@@ -4059,6 +4267,10 @@
 
 // --- cReplayControl --------------------------------------------------------
 
+#define REPLAYCONTROLSKIPLIMIT   9    // s
+#define REPLAYCONTROLSKIPSECONDS 90   // s
+#define REPLAYCONTROLSKIPTIMEOUT 5000 // ms
+
 cReplayControl *cReplayControl::currentReplayControl = NULL;
 char *cReplayControl::fileName = NULL;
 char *cReplayControl::title = NULL;
@@ -4072,6 +4284,9 @@
   lastCurrent = lastTotal = -1;
   lastPlay = lastForward = false;
   lastSpeed = -2; // an invalid value
+  lastSkipKey = kNone;
+  lastSkipSeconds = REPLAYCONTROLSKIPSECONDS;
+  lastSkipTimeout.Set(0);
   timeoutShow = 0;
   timeSearchActive = false;
   marks.Load(fileName);
@@ -4435,6 +4650,32 @@
     case kGreen:   SkipSeconds(-60); break;
     case kYellow|k_Repeat:
     case kYellow:  SkipSeconds( 60); break;
+    case k1|k_Repeat:
+    case k1:       SkipSeconds(-20); break;
+    case k3|k_Repeat:
+    case k3:       SkipSeconds( 20); break;
+    case kPrev|k_Repeat:
+    case kPrev:    if (lastSkipTimeout.TimedOut()) {
+                      lastSkipSeconds = REPLAYCONTROLSKIPSECONDS;
+                      lastSkipKey = kPrev;
+                   }
+                   else if (RAWKEY(lastSkipKey) != kPrev && lastSkipSeconds > (2 * REPLAYCONTROLSKIPLIMIT)) {
+                      lastSkipSeconds /= 2;
+                      lastSkipKey = kNone;
+                   }
+                   lastSkipTimeout.Set(REPLAYCONTROLSKIPTIMEOUT);
+                   SkipSeconds(-lastSkipSeconds); break;
+    case kNext|k_Repeat:
+    case kNext:    if (lastSkipTimeout.TimedOut()) {
+                      lastSkipSeconds = REPLAYCONTROLSKIPSECONDS;
+                      lastSkipKey = kNext;	
+                   }
+                   else if (RAWKEY(lastSkipKey) != kNext && lastSkipSeconds > (2 * REPLAYCONTROLSKIPLIMIT)) {
+                      lastSkipSeconds /= 2;
+                      lastSkipKey = kNone;
+                   }
+                   lastSkipTimeout.Set(REPLAYCONTROLSKIPTIMEOUT);
+                   SkipSeconds(lastSkipSeconds); break;
     case kStop:
     case kBlue:    Hide();
                    Stop();
@@ -4444,12 +4685,8 @@
       switch (Key) {
         // Editing:
         case kMarkToggle:      MarkToggle(); break;
-        case kPrev|k_Repeat:
-        case kPrev:
         case kMarkJumpBack|k_Repeat:
         case kMarkJumpBack:    MarkJump(false); break;
-        case kNext|k_Repeat:
-        case kNext:
         case kMarkJumpForward|k_Repeat:
         case kMarkJumpForward: MarkJump(true); break;
         case kMarkMoveBack|k_Repeat:
diff -Nru vdr-1.6.0-vanilla/menu.h vdr-1.6.0-liemikuutio/menu.h
--- vdr-1.6.0-vanilla/menu.h	2008-03-27 21:43:25.000000000 +0200
+++ vdr-1.6.0-liemikuutio/menu.h	2008-04-03 23:24:39.000000000 +0300
@@ -35,6 +35,8 @@
 private:
   cTimer *timer;
   cTimer data;
+  char name[MaxFileName];
+  char path[MaxFileName];
   int channel;
   bool addIfConfirmed;
   cMenuEditDateItem *firstday;
@@ -163,6 +165,7 @@
   eOSState Delete(void);
   eOSState Info(void);
   eOSState Commands(eKeys Key = kNone);
+  eOSState Rename(void);
 protected:
   cRecording *GetRecording(cMenuRecordingItem *Item);
 public:
@@ -217,6 +220,9 @@
   int lastCurrent, lastTotal;
   bool lastPlay, lastForward;
   int lastSpeed;
+  int lastSkipSeconds;
+  eKeys lastSkipKey;
+  cTimeMs lastSkipTimeout;
   time_t timeoutShow;
   bool timeSearchActive, timeSearchHide;
   int timeSearchTime, timeSearchPos;
diff -Nru vdr-1.6.0-vanilla/menuitems.c vdr-1.6.0-liemikuutio/menuitems.c
--- vdr-1.6.0-vanilla/menuitems.c	2008-03-27 21:43:25.000000000 +0200
+++ vdr-1.6.0-liemikuutio/menuitems.c	2008-04-26 23:23:31.000000000 +0300
@@ -619,6 +619,168 @@
   return osContinue;
 }
 
+// --- cMenuEditRecPathItem --------------------------------------------------
+
+cMenuEditRecPathItem::cMenuEditRecPathItem(const char* Name, char* Path,
+   int Length): cMenuEditStrItem(Name, Path, Length, tr(FileNameChars))
+{
+  SetBase(Path);
+}
+
+cMenuEditRecPathItem::~cMenuEditRecPathItem()
+{
+}
+
+void cMenuEditRecPathItem::SetBase(const char* Path)
+{
+  if (!Path)
+      base[0] = 0;
+  Utf8Strn0Cpy(base, Path, sizeof(base));
+  char* p = strrchr(base, '~');
+  if (p)
+     p[0] = 0;
+  else
+     base[0] = 0;
+}
+
+void cMenuEditRecPathItem::FindNextLevel()
+{
+  char item[MaxFileName];
+
+  for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording))
+  {
+     char* p;
+     Utf8Strn0Cpy(item, recording->Name(), sizeof(item));
+     stripspace(value);
+     lengthUtf8 = Utf8ToArray(value, valueUtf8, length);
+     if (!lengthUtf8)
+        p = strchr(item, '~');
+     else {
+        if (strstr(item, value) != item)
+           continue;
+        if (item[strlen(value)] != '~')
+           continue;
+        p = strchr(item + strlen(value) + 1, '~');
+        }
+     if (!p)
+        continue;
+     p[0] = 0;
+     Utf8Strn0Cpy(base, value, length);
+     Utf8Strn0Cpy(value, item, length);
+     lengthUtf8 = Utf8ToArray(value, valueUtf8, length);
+     return;
+     }
+}
+
+void cMenuEditRecPathItem::Find(bool Next)
+{
+  char item[MaxFileName];
+  char lastItem[MaxFileName] = "";
+
+  for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording))
+  {
+     const char* recName = recording->Name();
+     if (Utf8StrLen(base) && strstr(recName, base) != recName)
+        continue;
+     if (strlen(base) && recName[strlen(base)] != '~')
+        continue;
+     Utf8Strn0Cpy(item, recName, sizeof(item));
+     char* p = strchr(item + strlen(base) + 1, '~');
+     if (!p)
+        continue;
+     p[0] = 0;
+     if (!Next && (strcmp(item, value) == 0)) {
+        if (strlen(lastItem))
+           Utf8Strn0Cpy(value, lastItem, length);
+        lengthUtf8 = Utf8ToArray(value, valueUtf8, length);
+        return;
+        }
+     if (strcmp(lastItem, item) != 0) {
+        if(Next && Utf8StrLen(lastItem) && strcmp(lastItem, value) == 0) {
+           Utf8Strn0Cpy(value, item, length);
+           lengthUtf8 = Utf8ToArray(value, valueUtf8, length);
+           return;
+           }
+        Utf8Strn0Cpy(lastItem, item, sizeof(lastItem));
+        }
+     }
+}
+
+void cMenuEditRecPathItem::SetHelpKeys(void)
+{
+  cSkinDisplay::Current()->SetButtons(tr("Rename$Up"), tr("Rename$Down"), tr("Rename$Previous"), tr("Rename$Next"));
+}
+
+eOSState cMenuEditRecPathItem::ProcessKey(eKeys Key)
+{
+  switch (Key) {
+    case kLeft:
+    case kRed:    // one level up
+                  if (!InEditMode())
+                     return cMenuEditItem::ProcessKey(Key);
+                  Utf8Strn0Cpy(value, base, lengthUtf8);
+                  lengthUtf8 = Utf8ToArray(value, valueUtf8, length);
+                  SetBase(base);
+                  pos = Utf8StrLen(base);
+                  if (pos)
+                     pos++;
+                  if (!lengthUtf8) {
+                     Utf8Strn0Cpy(value, " ", length);
+                     lengthUtf8 = Utf8ToArray(value, valueUtf8, length);
+                     }
+                  break;
+    case kRight:
+    case kGreen:  // one level down
+                  if (InEditMode())
+                     FindNextLevel();
+                  else
+                     EnterEditMode();
+                  if (!lengthUtf8) {
+                     Utf8Strn0Cpy(value, " ", length);
+                     lengthUtf8 = Utf8ToArray(value, valueUtf8, length);
+                     }
+                  pos = Utf8StrLen(base);
+                  if (pos)
+                     pos++;
+                  SetHelpKeys();
+                  break;
+    case kUp|k_Repeat:
+    case kUp:
+    case kYellow|k_Repeat:
+    case kYellow: // previous directory in list
+                  if (!InEditMode())
+                     return cMenuEditItem::ProcessKey(Key);
+                  Find(false);
+                  pos = Utf8StrLen(base);
+                  if (pos)
+                     pos++;
+                  break;
+    case kDown|k_Repeat:
+    case kDown:
+    case kBlue|k_Repeat:
+    case kBlue:   // next directory in list
+                  if (!InEditMode())
+                     return cMenuEditItem::ProcessKey(Key);
+                  Find(true);
+                  pos = Utf8StrLen(base);
+                  if (pos)
+                     pos++;
+                  break;
+    case kOk:     // done
+                  if (!InEditMode())
+                     return cMenuEditItem::ProcessKey(Key);
+                  stripspace(value);
+                  lengthUtf8 = Utf8ToArray(value, valueUtf8, length);
+                  cSkinDisplay::Current()->SetButtons(NULL);
+                  LeaveEditMode(Key == kOk);
+                  break;
+    default:
+                  return cMenuEditItem::ProcessKey(Key);
+    }
+  Set();
+  return osContinue;
+}
+
 // --- cMenuEditStraItem -----------------------------------------------------
 
 cMenuEditStraItem::cMenuEditStraItem(const char *Name, int *Value, int NumStrings, const char * const *Strings)
diff -Nru vdr-1.6.0-vanilla/menuitems.h vdr-1.6.0-liemikuutio/menuitems.h
--- vdr-1.6.0-vanilla/menuitems.h	2008-03-27 21:43:25.000000000 +0200
+++ vdr-1.6.0-liemikuutio/menuitems.h	2008-04-03 23:24:39.000000000 +0300
@@ -78,26 +78,27 @@
 
 class cMenuEditStrItem : public cMenuEditItem {
 private:
-  char *value;
-  int length;
-  const char *allowed;
-  int pos, offset;
+  int offset;
   bool insert, newchar, uppercase;
-  int lengthUtf8;
-  uint *valueUtf8;
   uint *allowedUtf8;
   uint *charMapUtf8;
   uint *currentCharUtf8;
   eKeys lastKey;
   cTimeMs autoAdvanceTimeout;
-  void SetHelpKeys(void);
   uint *IsAllowed(uint c);
   void AdvancePos(void);
-  virtual void Set(void);
   uint Inc(uint c, bool Up);
   void Insert(void);
   void Delete(void);
 protected:
+  char *value;
+  int length;
+  uint *valueUtf8;
+  int lengthUtf8;
+  const char *allowed;
+  int pos;
+  void SetHelpKeys(void);
+  virtual void Set(void);
   void EnterEditMode(void);
   void LeaveEditMode(bool SaveValue = false);
   bool InEditMode(void) { return valueUtf8 != NULL; }
@@ -107,6 +108,19 @@
   virtual eOSState ProcessKey(eKeys Key);
   };
 
+class cMenuEditRecPathItem : public cMenuEditStrItem {
+protected:
+  char base[MaxFileName];
+  virtual void SetHelpKeys(void);
+  void SetBase(const char* Path);
+  void FindNextLevel();
+  void Find(bool Next);
+public:
+  cMenuEditRecPathItem(const char* Name, char* Path, int Length);
+  ~cMenuEditRecPathItem();
+  virtual eOSState ProcessKey(eKeys Key);
+  };
+
 class cMenuEditStraItem : public cMenuEditIntItem {
 private:
   const char * const *strings;
diff -Nru vdr-1.6.0-vanilla/osdbase.c vdr-1.6.0-liemikuutio/osdbase.c
--- vdr-1.6.0-vanilla/osdbase.c	2008-03-27 21:43:25.000000000 +0200
+++ vdr-1.6.0-liemikuutio/osdbase.c	2008-03-27 21:47:56.000000000 +0200
@@ -77,6 +77,7 @@
 {
   isMenu = true;
   digit = 0;
+  key_nr = -1;
   hasHotkeys = false;
   title = NULL;
   SetTitle(Title);
@@ -119,7 +120,7 @@
         digit = -1; // prevents automatic hotkeys - input already has them
      if (digit >= 0) {
         digit++;
-        buffer = cString::sprintf(" %c %s", (digit < 10) ? '0' + digit : ' ' , s);
+        buffer = cString::sprintf(" %2d%s %s", digit, (digit > 9) ? "" : " ", s);
         s = buffer;
         }
      }
@@ -448,20 +449,62 @@
      }
 }
 
+#define MENUKEY_TIMEOUT 1500
+
 eOSState cOsdMenu::HotKey(eKeys Key)
 {
-  for (cOsdItem *item = First(); item; item = Next(item)) {
+  bool match = false;
+  bool highlight = false;
+  int  item_nr;
+  int  i;
+
+  if (Key == kNone) {
+     if (lastActivity.TimedOut())
+        Key = kOk;
+     else
+        return osContinue;
+     }
+  else {
+     lastActivity.Set(MENUKEY_TIMEOUT);
+     }
+  for (cOsdItem *item = Last(); item; item = Prev(item)) {
       const char *s = item->Text();
-      if (s && (s = skipspace(s)) != NULL) {
-         if (*s == Key - k1 + '1') {
+      i = 0;
+      item_nr = 0;
+      if (s && (s = skipspace(s)) != '\0' && '0' <= s[i] && s[i] <= '9') {
+         do {
+            item_nr = item_nr * 10 + (s[i] - '0');
+            }
+         while ( !((s[++i] == '\t')||(s[i] == ' ')) && (s[i] != '\0') && ('0' <= s[i]) && (s[i] <= '9'));
+         if ((Key == kOk) && (item_nr == key_nr)) {
             current = item->Index();
             RefreshCurrent();
             Display();
             cRemote::Put(kOk, true);
+            key_nr = -1;
             break;
             }
+         else if (Key != kOk) {
+            if (!highlight && (item_nr == (Key - k0))) {
+               highlight = true;
+               current = item->Index();
+               }
+            if (!match && (key_nr == -1) && ((item_nr / 10) == (Key - k0))) {
+               match = true;
+               key_nr = (Key - k0);
+               }
+            else if (((key_nr == -1) && (item_nr == (Key - k0))) || (!match && (key_nr >= 0) && (item_nr == (10 * key_nr + Key - k0)))) {
+               current = item->Index();
+               cRemote::Put(kOk, true);
+               key_nr = -1;
+               break;
+               }
+            }
          }
       }
+  if ((!match) && (Key != kNone)) {
+     key_nr = -1;
+     }
   return osContinue;
 }
 
@@ -500,8 +543,8 @@
         }
      }
   switch (Key) {
-    case k0:      return osUnknown;
-    case k1...k9: return hasHotkeys ? HotKey(Key) : osUnknown;
+    case kNone:
+    case k0...k9: return hasHotkeys ? HotKey(Key) : osUnknown;
     case kUp|k_Repeat:
     case kUp:   CursorUp();   break;
     case kDown|k_Repeat:
diff -Nru vdr-1.6.0-vanilla/osdbase.h vdr-1.6.0-liemikuutio/osdbase.h
--- vdr-1.6.0-vanilla/osdbase.h	2008-03-27 21:43:25.000000000 +0200
+++ vdr-1.6.0-liemikuutio/osdbase.h	2008-03-27 21:47:56.000000000 +0200
@@ -95,6 +95,8 @@
   char *status;
   int digit;
   bool hasHotkeys;
+  int key_nr;
+  cTimeMs lastActivity;
 protected:
   void SetDisplayMenu(void);
   cSkinDisplayMenu *DisplayMenu(void) { return displayMenu; }
diff -Nru vdr-1.6.0-vanilla/po/de_DE.po vdr-1.6.0-liemikuutio/po/de_DE.po
--- vdr-1.6.0-vanilla/po/de_DE.po	2008-03-27 21:43:25.000000000 +0200
+++ vdr-1.6.0-liemikuutio/po/de_DE.po	2008-04-03 23:31:27.000000000 +0300
@@ -998,3 +998,51 @@
 #, c-format
 msgid "VDR will shut down in %s minutes"
 msgstr "VDR wird in %s Minuten ausschalten"
+
+msgid "Rename recording"
+msgstr "Aufzeichnung umbenennen"
+
+msgid "Date"
+msgstr "Datum"
+
+msgid "Length"
+msgstr "Länge"
+
+msgid "Size"
+msgstr "Größe"
+
+msgid "Path"
+msgstr "Pfad"
+
+msgid "Rename$Up"
+msgstr "Höher"
+
+msgid "Rename$Down"
+msgstr "Tiefer"
+
+msgid "Rename$Previous"
+msgstr "Vorheriger"
+
+msgid "Rename$Next"
+msgstr "Nächster"
+
+msgid "Delete marks information?"
+msgstr "Marks löschen?"
+
+msgid "Delete resume information?"
+msgstr "Resume löschen?"
+
+msgid "Setup.OSD$Main menu command position"
+msgstr "Befehle Position im Hauptmenü"
+
+msgid "Setup.EPG$Show progress bar"
+msgstr "Zeitbalken anzeigen"
+
+msgid "Setup.Recording$Show date"
+msgstr "Aufnahmedatum anzeigen"
+
+msgid "Setup.Recording$Show time"
+msgstr "AufnahmeZeit anzeigen"
+
+msgid "Setup.Recording$Show length"
+msgstr "Länge der Aufnahme anzeigen"
diff -Nru vdr-1.6.0-vanilla/po/et_EE.po vdr-1.6.0-liemikuutio/po/et_EE.po
--- vdr-1.6.0-vanilla/po/et_EE.po	2008-03-27 21:43:25.000000000 +0200
+++ vdr-1.6.0-liemikuutio/po/et_EE.po	2008-04-03 23:38:43.000000000 +0300
@@ -998,3 +998,51 @@
 #, c-format
 msgid "VDR will shut down in %s minutes"
 msgstr "VDR lülitub välja %s minuti pärast"
+
+msgid "Rename recording"
+msgstr "Ümbernimetamine"
+
+msgid "Date"
+msgstr ""
+
+msgid "Length"
+msgstr ""
+
+msgid "Size"
+msgstr ""
+
+msgid "Path"
+msgstr ""
+
+msgid "Rename$Up"
+msgstr "Üles"
+
+msgid "Rename$Down"
+msgstr "Alla"
+
+msgid "Rename$Previous"
+msgstr "Eelmine"
+
+msgid "Rename$Next"
+msgstr "Järgmine"
+
+msgid "Delete marks information?"
+msgstr ""
+
+msgid "Delete resume information?"
+msgstr ""
+
+msgid "Setup.OSD$Main menu command position"
+msgstr "Käsu asukoht peamenüüs"
+
+msgid "Setup.EPG$Show progress bar"
+msgstr "Edenemisriba"
+
+msgid "Setup.Recording$Show date"
+msgstr "Salvestuse kuupäev"
+
+msgid "Setup.Recording$Show time"
+msgstr "Salvestuse kellaaeg"
+
+msgid "Setup.Recording$Show length"
+msgstr "Salvestuse pikkus"
diff -Nru vdr-1.6.0-vanilla/po/fi_FI.po vdr-1.6.0-liemikuutio/po/fi_FI.po
--- vdr-1.6.0-vanilla/po/fi_FI.po	2008-03-27 21:43:25.000000000 +0200
+++ vdr-1.6.0-liemikuutio/po/fi_FI.po	2008-04-03 23:34:26.000000000 +0300
@@ -1001,3 +1001,51 @@
 #, c-format
 msgid "VDR will shut down in %s minutes"
 msgstr "VDR sammuu %s minuutin kuluttua"
+
+msgid "Rename recording"
+msgstr "Nimeä tallenne"
+
+msgid "Date"
+msgstr "Päiväys"
+
+msgid "Length"
+msgstr "Pituus"
+
+msgid "Size"
+msgstr "Koko"
+
+msgid "Path"
+msgstr "Polku"
+
+msgid "Rename$Up"
+msgstr "Ylemmäs"
+
+msgid "Rename$Down"
+msgstr "Alemmas"
+
+msgid "Rename$Previous"
+msgstr "Edellinen"
+
+msgid "Rename$Next"
+msgstr "Seuraava"
+
+msgid "Delete marks information?"
+msgstr "Poista tallenteen merkinnät?"
+
+msgid "Delete resume information?"
+msgstr "Poista tallenteen paluutiedot?"
+
+msgid "Setup.OSD$Main menu command position"
+msgstr "Komentojen sijainti päävalikossa"
+
+msgid "Setup.EPG$Show progress bar"
+msgstr "Näytä aikajana"
+
+msgid "Setup.Recording$Show date"
+msgstr "Näytä tallenteen päiväys"
+
+msgid "Setup.Recording$Show time"
+msgstr "Näytä tallenteen ajankohta"
+
+msgid "Setup.Recording$Show length"
+msgstr "Näytä tallenteen kesto"
diff -Nru vdr-1.6.0-vanilla/po/fr_FR.po vdr-1.6.0-liemikuutio/po/fr_FR.po
--- vdr-1.6.0-vanilla/po/fr_FR.po	2008-03-27 21:43:25.000000000 +0200
+++ vdr-1.6.0-liemikuutio/po/fr_FR.po	2008-04-03 23:36:49.000000000 +0300
@@ -1004,3 +1004,51 @@
 #, c-format
 msgid "VDR will shut down in %s minutes"
 msgstr "VDR s'arrêtera dans %s minutes"
+
+msgid "Rename recording"
+msgstr "Renommer l'enregistrement"
+
+msgid "Date"
+msgstr "Date"
+
+msgid "Length"
+msgstr "Longueur"
+
+msgid "Size"
+msgstr "Taille"
+
+msgid "Path"
+msgstr ""
+
+msgid "Rename$Up"
+msgstr "Haut"
+
+msgid "Rename$Down"
+msgstr "Bas"
+
+msgid "Rename$Previous"
+msgstr "Précédent"
+
+msgid "Rename$Next"
+msgstr "Suivant"
+
+msgid "Delete marks information?"
+msgstr "Effacer les informations de marquage"
+
+msgid "Delete resume information?"
+msgstr "Effacer les informations de reprise"
+
+msgid "Setup.OSD$Main menu command position"
+msgstr "Position des commandes dans le menu"
+
+msgid "Setup.EPG$Show progress bar"
+msgstr "Montrer la barre de progression"
+
+msgid "Setup.Recording$Show date"
+msgstr "Montrer la date d'enregistrement"
+
+msgid "Setup.Recording$Show time"
+msgstr "Montrer l'heure d'enregistrement"
+
+msgid "Setup.Recording$Show length"
+msgstr "Monter la longueur de l'enregistrement"
diff -Nru vdr-1.6.0-vanilla/po/ru_RU.po vdr-1.6.0-liemikuutio/po/ru_RU.po
--- vdr-1.6.0-vanilla/po/ru_RU.po	2008-03-27 21:43:25.000000000 +0200
+++ vdr-1.6.0-liemikuutio/po/ru_RU.po	2008-03-27 21:47:57.000000000 +0200
@@ -999,3 +999,36 @@
 #, c-format
 msgid "VDR will shut down in %s minutes"
 msgstr "VDR ÒëÚÛîçØâáï çÕàÕ× %s ÜØÝãâ"
+
+msgid "Rename recording"
+msgstr "¿ÕàÕØÜÕÝÞÒÐâì ×ÐßØáì"
+
+msgid "Date"
+msgstr ""
+
+msgid "Length"
+msgstr ""
+
+msgid "Size"
+msgstr ""
+
+msgid "Delete marks information?"
+msgstr ""
+
+msgid "Delete resume information?"
+msgstr ""
+
+msgid "Setup.OSD$Main menu command position"
+msgstr "ÀÐ×ÜÕéÕÝØÕ ÚÞÜÐÝÔ Ò ÓÛÐÒÝÞÜ ÜÕÝî"
+
+msgid "Setup.EPG$Show progress bar"
+msgstr ""
+
+msgid "Setup.Recording$Show date"
+msgstr "¿ÞÚÐ×ëÒÐâì ÔÐâã"
+
+msgid "Setup.Recording$Show time"
+msgstr "¿ÞÚÐ×ëÒÐâì ÒàÕÜï ×ÐßØáØ"
+
+msgid "Setup.Recording$Show length"
+msgstr "¿ÞÚÐ×ëÒÐâì ßàÞÔÞÛÖØâÕÛìÝÞáâì ×ÐßØáØ"
diff -Nru vdr-1.6.0-vanilla/recording.c vdr-1.6.0-liemikuutio/recording.c
--- vdr-1.6.0-vanilla/recording.c	2008-03-27 21:43:25.000000000 +0200
+++ vdr-1.6.0-liemikuutio/recording.c	2008-03-27 21:47:56.000000000 +0200
@@ -46,6 +46,7 @@
 #endif
 #define INFOFILESUFFIX    "/info.vdr"
 #define MARKSFILESUFFIX   "/marks.vdr"
+#define INDEXFILESUFFIX   "/index.vdr"
 
 #define MINDISKSPACE 1024 // MB
 
@@ -62,6 +63,7 @@
 #define MAX_LINK_LEVEL  6
 
 bool VfatFileSystem = false;
+bool DirOrderState = false;
 
 cRecordings DeletedRecordings(true);
 
@@ -690,6 +692,8 @@
 int cRecording::Compare(const cListObject &ListObject) const
 {
   cRecording *r = (cRecording *)&ListObject;
+  if (DirOrderState)
+     return strcasecmp(FileName(), r->FileName());
   return strcasecmp(SortName(), r->SortName());
 }
 
@@ -705,7 +709,7 @@
   return fileName;
 }
 
-const char *cRecording::Title(char Delimiter, bool NewIndicator, int Level) const
+const char *cRecording::Title(char Delimiter, bool NewIndicator, int Level, bool Original) const
 {
   char New = NewIndicator && IsNew() ? '*' : ' ';
   free(titleBuffer);
@@ -718,6 +722,7 @@
         s++;
      else
         s = name;
+     if (Original) {
      titleBuffer = strdup(cString::sprintf("%02d.%02d.%02d%c%02d:%02d%c%c%s",
                             t->tm_mday,
                             t->tm_mon + 1,
@@ -728,6 +733,39 @@
                             New,
                             Delimiter,
                             s));
+        }
+     else {
+        cString RecLength("---");
+        if (Setup.ShowRecLength && FileName()) {
+           cString filename = cString::sprintf("%s%s", FileName(), INDEXFILESUFFIX);
+           if (*filename) {
+              if (access(filename, R_OK) == 0) {
+                 struct stat buf;
+                 if (stat(filename, &buf) == 0) {
+                    struct tIndex { int offset; uchar type; uchar number; short reserved; };
+                    int delta = buf.st_size % sizeof(tIndex);
+                    if (delta) {
+                       delta = sizeof(tIndex) - delta;
+                       esyslog("ERROR: invalid file size (%ld) in '%s'", buf.st_size, *filename);
+                       }
+                    RecLength = cString::sprintf("%ld'", (buf.st_size + delta) / sizeof(tIndex) / SecondsToFrames(60));
+                    }
+                 }
+              }
+           }
+        cString RecDate = cString::sprintf("%02d.%02d.%02d", t->tm_mday, t->tm_mon + 1, t->tm_year % 100);
+        cString RecTime = cString::sprintf("%02d:%02d", t->tm_hour, t->tm_min);
+        cString RecDelimiter = cString::sprintf("%c", Delimiter);
+        titleBuffer = strdup(cString::sprintf("%s%s%s%c%s%s%s%s",
+                               (Setup.ShowRecDate ? *RecDate        : ""),
+                               (Setup.ShowRecDate && Setup.ShowRecTime ? *RecDelimiter : ""),
+                               (Setup.ShowRecTime ? *RecTime        : ""),
+                               New,
+                               (Setup.ShowRecTime || Setup.ShowRecDate ? *RecDelimiter : ""),
+                               (Setup.ShowRecLength ? *RecLength    : ""),
+                               (Setup.ShowRecLength ? *RecDelimiter : ""),
+                               s));
+        }
      // let's not display a trailing '~':
      if (!NewIndicator)
         stripspace(titleBuffer);
@@ -864,6 +902,41 @@
   resume = RESUME_NOT_INITIALIZED;
 }
 
+bool cRecording::Rename(const char *newName, int *newPriority, int *newLifetime)
+{
+  bool result = false;
+  struct tm tm_r;
+  struct tm *t = localtime_r(&start, &tm_r);
+  char *localNewName = ExchangeChars(strdup(newName), true);
+  char *newFileName = strdup(cString::sprintf(NAMEFORMAT, VideoDirectory, localNewName, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, *newPriority, *newLifetime));
+  free(localNewName);
+  if (strcmp(FileName(), newFileName)) {
+     if (access(newFileName, F_OK) == 0) {
+        isyslog("recording %s already exists", newFileName);
+        }
+     else {
+        isyslog("renaming recording %s to %s", FileName(), newFileName);
+        result = MakeDirs(newFileName, true);
+        if (result)
+           result = RenameVideoFile(FileName(), newFileName);
+        if (result) {
+           priority = *newPriority;
+           lifetime = *newLifetime;
+           free(fileName);
+           fileName = strdup(newFileName);
+           free(name);
+           name = strdup(newName);
+           free(sortBuffer);
+           sortBuffer = NULL;
+           free(titleBuffer);
+           titleBuffer = NULL;
+           }
+        }
+     }
+  free(newFileName);
+  return result;
+}
+
 // --- cRecordings -----------------------------------------------------------
 
 cRecordings Recordings;
@@ -1172,8 +1245,6 @@
 //XXX+ somewhere else???
 // --- cIndexFile ------------------------------------------------------------
 
-#define INDEXFILESUFFIX     "/index.vdr"
-
 // The number of frames to stay off the end in case of time shift:
 #define INDEXSAFETYLIMIT 150 // frames
 
diff -Nru vdr-1.6.0-vanilla/recording.h vdr-1.6.0-liemikuutio/recording.h
--- vdr-1.6.0-vanilla/recording.h	2008-03-27 21:43:25.000000000 +0200
+++ vdr-1.6.0-liemikuutio/recording.h	2008-03-27 21:47:57.000000000 +0200
@@ -19,6 +19,7 @@
 #include "tools.h"
 
 extern bool VfatFileSystem;
+extern bool DirOrderState;
 
 void RemoveDeletedRecordings(void);
 void AssertFreeDiskSpace(int Priority = 0, bool Force = false);
@@ -88,7 +89,7 @@
   virtual int Compare(const cListObject &ListObject) const;
   const char *Name(void) const { return name; }
   const char *FileName(void) const;
-  const char *Title(char Delimiter = ' ', bool NewIndicator = false, int Level = -1) const;
+  const char *Title(char Delimiter = ' ', bool NewIndicator = false, int Level = -1, bool Original = true) const;
   const cRecordingInfo *Info(void) const { return info; }
   const char *PrefixFileName(char Prefix);
   int HierarchyLevels(void) const;
@@ -106,6 +107,9 @@
        // Changes the file name so that it will be visible in the "Recordings" menu again and
        // not processed by cRemoveDeletedRecordingsThread.
        // Returns false in case of error
+  bool Rename(const char *newName, int *newPriority, int *newLifetime);
+       // Changes the file name
+       // Returns false in case of error
   };
 
 class cRecordings : public cList<cRecording>, public cThread {
diff -Nru vdr-1.6.0-vanilla/svdrp.c vdr-1.6.0-liemikuutio/svdrp.c
--- vdr-1.6.0-vanilla/svdrp.c	2008-03-27 21:43:25.000000000 +0200
+++ vdr-1.6.0-liemikuutio/svdrp.c	2008-03-27 21:47:56.000000000 +0200
@@ -296,6 +296,8 @@
   "REMO [ on | off ]\n"
   "    Turns the remote control on or off. Without a parameter, the current\n"
   "    status of the remote control is reported.",
+  "RENR <number> <new name>\n"
+  "    Rename recording. Number must be the Number as returned by LSTR command.",
   "SCAN\n"
   "    Forces an EPG scan. If this is a single DVB device system, the scan\n"
   "    will be done on the primary device unless it is currently recording.",
@@ -1472,6 +1474,38 @@
   Reply(250, "EPG scan triggered");
 }
 
+void cSVDRP::CmdRENR(const char *Option)
+{
+  bool recordings = Recordings.Update(true);
+  if (recordings) {
+     if (*Option) {
+        char *tail;
+        int n = strtol(Option, &tail, 10);
+        cRecording *recording = Recordings.Get(n - 1);
+        if (recording && tail && tail != Option) {
+           int priority = recording->priority;
+           int lifetime = recording->lifetime;
+           char *oldName = strdup(recording->Name());
+           tail = skipspace(tail);
+           if (recording->Rename(tail, &priority, &lifetime)) {
+              Reply(250, "Renamed \"%s\" to \"%s\"", oldName, recording->Name());
+              Recordings.ChangeState();
+              Recordings.TouchUpdate();
+              }
+           else
+              Reply(501, "Renaming \"%s\" to \"%s\" failed", oldName, tail);
+           free(oldName);
+           }
+        else
+          Reply(501, "Recording not found or wrong syntax");
+        }
+     else
+        Reply(501, "Missing Input settings");
+     }
+  else
+     Reply(550, "No recordings available");
+}
+						
 void cSVDRP::CmdSTAT(const char *Option)
 {
   if (*Option) {
@@ -1587,6 +1621,7 @@
   else if (CMD("PLUG"))  CmdPLUG(s);
   else if (CMD("PUTE"))  CmdPUTE(s);
   else if (CMD("REMO"))  CmdREMO(s);
+  else if (CMD("RENR"))  CmdRENR(s);
   else if (CMD("SCAN"))  CmdSCAN(s);
   else if (CMD("STAT"))  CmdSTAT(s);
   else if (CMD("UPDT"))  CmdUPDT(s);
diff -Nru vdr-1.6.0-vanilla/svdrp.h vdr-1.6.0-liemikuutio/svdrp.h
--- vdr-1.6.0-vanilla/svdrp.h	2008-03-27 21:43:25.000000000 +0200
+++ vdr-1.6.0-liemikuutio/svdrp.h	2008-03-27 21:47:56.000000000 +0200
@@ -79,6 +79,7 @@
   void CmdPLUG(const char *Option);
   void CmdPUTE(const char *Option);
   void CmdREMO(const char *Option);
+  void CmdRENR(const char *Option);
   void CmdSCAN(const char *Option);
   void CmdSTAT(const char *Option);
   void CmdUPDT(const char *Option);
 
design & coding: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
current maintainer: Michael Shigorin