Added renaming and moving recordings and folders, and editing a recording's priority and lifetime; added cutting queue

This commit is contained in:
Klaus Schmidinger 2013-10-10 13:13:30 +02:00
parent 3971cc6e88
commit 2bdb599fbc
46 changed files with 3038 additions and 184 deletions

View File

@ -1170,6 +1170,7 @@ Rolf Ahrenberg <Rolf.Ahrenberg@sci.fi>
for a patch that was used to rename the "plp id" to a more general "stream id"
and add support for DVB-S2 "Input Stream Identifier" (ISI)
for helping to debug and understand subtitle page refreshes
for a patch that was used to implement the SVDRP command RENR
Ralf Klueber <ralf.klueber@vodafone.com>
for reporting a bug in cutting a recording if there is only a single editing mark
@ -3180,3 +3181,7 @@ Manfred V
Thomas Maass <mase@setho.org>
for reporting a difference in the internal sequence of actions when pressing the Blue
and the Back key, respectively, during replay
Martin Prochnow <nordlicht@martins-kabuff.de>
for writing the "extrecmenu" plugin, which inspired the implementation of editing
recording properties

22
HISTORY
View File

@ -7920,7 +7920,7 @@ Video Disk Recorder Revision History
- Fixed cleaning up old EPG events in case no epg data file is given (reported by
Dave Pickles).
2013-09-07: Version 2.1.2
2013-10-10: Version 2.1.2
- Updated the Finnish OSD texts (thanks to Rolf Ahrenberg).
- Fixed displaying DVB subtitles (thanks to Rolf Ahrenberg for helping to debug and
@ -7966,3 +7966,23 @@ Video Disk Recorder Revision History
#define DEPRECATED_VIDEODIR
in videodir.h and recompile your plugins to see whether your code will work without
this variable. If you get a compile error, replace it with cVideoDirectory::Name().
- Added renaming and moving recordings and folders, editing a recording's priority and
lifetime, and queueing cutting jobs (inspired by the "extrecmenu" plugin from Martin
Prochnow).
+ The "Recording info" menu now has a new Blue button named "Edit", which opens a
dialog in which several properties of the selected recording can be changed. It can
be renamed or moved into another folder and its priority and lifetime can be
modified (inspired by the "extrecmenu" plugin from Martin Prochnow).
The new blue "Edit" button in the "Recordings" menu opens a dialog in which a folder
can be renamed or moved. See MANUAL, section "Managing folders".
+ In the "Edit recording" menu the Yellow button ("Delete marks") allows you to delete
all editing marks of the selected recording.
+ cCutter is no longer a static class. Cutting requests should now be invoked by
calling RecordingsHandler.Add(ruCut, FileName). See the new cRecordingsHandler
class in recording.h.
+ Cutting jobs are now placed in a queue (together with any move or copy jobs) and
are processed one by one.
+ The new SVDRP command RENR can be used to rename a recording (suggested by Rolf
Ahrenberg).
+ Note that in several places in the source code a "copy" operation is mentioned,
however there is no user interface for this, yet.

24
MANUAL
View File

@ -504,6 +504,30 @@ Version 2.0
folder, or enters a sub folder. Once a folder has been selected, the entire
path of the timer's file name will be replaced with the selected folder.
In the "Recordings" menu the folders of existing recordings can be renamed or
moved by pressing the "Blue" key ("Edit") while the cursor is positioned on
a folder. This will open a menu in which the folder's name and location (the
"parent" folder) can be edited. If such an operation will result in moving
more than one recording, you will be asked for confirmation.
The name, folder, priority and lifetime of an individual recording can be
changed by pressing the "Blue" key ("Info") while the cursor is positioned
on a recording, and in the resulting Info menu pressing the "Blue" key again
to bring up the "Edit recording" menu.
In the "Edit recording" menu the Red button ("Folder") allows you to select one
of your predefined folders. The Green button has multiple functions, depending
on what is currently going on with the recording. It can either stop or cancel
a cut, move or copy operation. If the button reads "Stop..." it means that the
respective operation is already happening, while "Cancel..." means that the
operation is still pending execution. If no operation is currently happening
and the recording has editing marks, the Button will read "Cut" and triggers
cutting the recording (same as pressing '2' while replaying the recording).
The Yellow button ("Delete marks") allows you to delete all editing marks from
the selected recording (if there are any and the recording is not currently
being cut). To directly edit the folder or name of the recording, position the
cursor to the respective line and press the Right key to start editing (press
Ok to confirm the edit, or Back to return to the previous value). Once you are
finished with editing the recording properties, press Ok to confirm the changes.
* Parameters in the "Setup" menu
Select "Setup" from the "VDR" menu to enter the setup menu. From there you can

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: cutter.c 3.3 2013/09/10 14:51:45 kls Exp $
* $Id: cutter.c 3.4 2013/10/02 13:18:02 kls Exp $
*/
#include "cutter.h"
@ -642,34 +642,47 @@ void cCuttingThread::Action(void)
// --- cCutter ---------------------------------------------------------------
cMutex cCutter::mutex;
cString cCutter::originalVersionName;
cString cCutter::editedVersionName;
cCuttingThread *cCutter::cuttingThread = NULL;
bool cCutter::error = false;
bool cCutter::ended = false;
bool cCutter::Start(const char *FileName)
cCutter::cCutter(const char *FileName)
{
cuttingThread = NULL;
error = false;
originalVersionName = FileName;
}
cCutter::~cCutter()
{
Stop();
}
cString cCutter::EditedFileName(const char *FileName)
{
cRecording Recording(FileName);
cMarks Marks;
if (Marks.Load(FileName, Recording.FramesPerSecond(), Recording.IsPesRecording())) {
if (cMark *First = Marks.GetNextBegin())
Recording.SetStartTime(Recording.Start() + (int(First->Position() / Recording.FramesPerSecond() + 30) / 60) * 60);
return Recording.PrefixFileName('%');
}
return NULL;
}
bool cCutter::Start(void)
{
cMutexLock MutexLock(&mutex);
if (!cuttingThread) {
error = false;
ended = false;
originalVersionName = FileName;
cRecording Recording(FileName);
cMarks FromMarks;
FromMarks.Load(FileName, Recording.FramesPerSecond(), Recording.IsPesRecording());
if (cMark *First = FromMarks.GetNextBegin())
Recording.SetStartTime(Recording.Start() + (int(First->Position() / Recording.FramesPerSecond() + 30) / 60) * 60);
const char *evn = Recording.PrefixFileName('%');
if (evn && cVideoDirectory::RemoveVideoFile(evn) && MakeDirs(evn, true)) {
editedVersionName = evn;
Recording.WriteInfo();
Recordings.AddByName(editedVersionName, false);
cuttingThread = new cCuttingThread(FileName, editedVersionName);
return true;
if (*originalVersionName) {
cRecording Recording(originalVersionName);
editedVersionName = EditedFileName(originalVersionName);
if (*editedVersionName) {
if (strcmp(originalVersionName, editedVersionName) != 0) { // names must be different!
if (cVideoDirectory::RemoveVideoFile(editedVersionName) && MakeDirs(editedVersionName, true)) {
Recording.WriteInfo(editedVersionName);
Recordings.AddByName(editedVersionName, false);
cuttingThread = new cCuttingThread(originalVersionName, editedVersionName);
return true;
}
}
}
}
}
return false;
@ -677,7 +690,6 @@ bool cCutter::Start(const char *FileName)
void cCutter::Stop(void)
{
cMutexLock MutexLock(&mutex);
bool Interrupted = cuttingThread && cuttingThread->Active();
const char *Error = cuttingThread ? cuttingThread->Error() : NULL;
delete cuttingThread;
@ -694,37 +706,22 @@ void cCutter::Stop(void)
}
}
bool cCutter::Active(const char *FileName)
bool cCutter::Active(void)
{
cMutexLock MutexLock(&mutex);
if (cuttingThread) {
if (cuttingThread->Active())
return !FileName || strcmp(FileName, originalVersionName) == 0 || strcmp(FileName, editedVersionName) == 0;
return true;
error = cuttingThread->Error();
Stop();
if (!error)
cRecordingUserCommand::InvokeCommand(RUC_EDITEDRECORDING, editedVersionName, originalVersionName);
originalVersionName = NULL;
editedVersionName = NULL;
ended = true;
}
return false;
}
bool cCutter::Error(void)
{
cMutexLock MutexLock(&mutex);
bool result = error;
error = false;
return result;
}
bool cCutter::Ended(void)
{
cMutexLock MutexLock(&mutex);
bool result = ended;
ended = false;
return result;
return error;
}
#define CUTTINGCHECKINTERVAL 500 // ms between checks for the active cutting process
@ -737,10 +734,13 @@ bool CutRecording(const char *FileName)
cMarks Marks;
if (Marks.Load(FileName, Recording.FramesPerSecond(), Recording.IsPesRecording()) && Marks.Count()) {
if (Marks.GetNumSequences()) {
if (cCutter::Start(FileName)) {
while (cCutter::Active())
cCutter Cutter(FileName);
if (Cutter.Start()) {
while (Cutter.Active())
cCondWait::SleepMs(CUTTINGCHECKINTERVAL);
return true;
if (!Cutter.Error())
return true;
fprintf(stderr, "error while cutting\n");
}
else
fprintf(stderr, "can't start editing process\n");

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: cutter.h 2.3 2012/02/16 12:05:33 kls Exp $
* $Id: cutter.h 3.1 2013/10/05 11:34:55 kls Exp $
*/
#ifndef __CUTTER_H
@ -17,21 +17,31 @@ class cCuttingThread;
class cCutter {
private:
static cMutex mutex;
static cString originalVersionName;
static cString editedVersionName;
static cCuttingThread *cuttingThread;
static bool error;
static bool ended;
cString originalVersionName;
cString editedVersionName;
cCuttingThread *cuttingThread;
bool error;
public:
static bool Start(const char *FileName);
static void Stop(void);
static bool Active(const char *FileName = NULL);
///< Returns true if the cutter is currently active.
///< If a FileName is given, true is only returned if either the
///< original or the edited file name is equal to FileName.
static bool Error(void);
static bool Ended(void);
cCutter(const char *FileName);
///< Sets up a new cutter for the given FileName, which must be the full path
///< name of an existing recording directory.
~cCutter();
static cString EditedFileName(const char *FileName);
///< Returns the full path name of the edited version of the recording with
///< the given FileName. This static function can be used independent of any
///< cCutter object, to determine the file name beforehand.
///< Returns NULL in case of error.
bool Start(void);
///< Starts the actual cutting process.
///< Returns true if successful.
///< If Start() is called while the cutting process is already active, nothing
///< happens and false will be returned.
void Stop(void);
///< Stops an ongoing cutting process.
bool Active(void);
///< Returns true if the cutter is currently active.
bool Error(void);
///< Returns true if an error occurred while cutting the recording.
};
bool CutRecording(const char *FileName);

387
menu.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: menu.c 3.6 2013/09/10 13:16:40 kls Exp $
* $Id: menu.c 3.7 2013/10/10 12:31:08 kls Exp $
*/
#include "menu.h"
@ -16,7 +16,6 @@
#include <string.h>
#include "channels.h"
#include "config.h"
#include "cutter.h"
#include "eitscan.h"
#include "i18n.h"
#include "interface.h"
@ -828,8 +827,7 @@ eOSState cMenuFolder::Edit(void)
eOSState cMenuFolder::SetFolder(void)
{
cMenuEditFolder *mef = (cMenuEditFolder *)SubMenu();
if (mef) {
if (cMenuEditFolder *mef = dynamic_cast<cMenuEditFolder *>(SubMenu())) {
Set(mef->GetFolder());
SetHelpKeys();
Display();
@ -843,8 +841,7 @@ cString cMenuFolder::GetFolder(void)
if (firstFolder) {
cMenuFolderItem *Folder = (cMenuFolderItem *)Get(Current());
if (Folder) {
cMenuFolder *mf = (cMenuFolder *)SubMenu();
if (mf)
if (cMenuFolder *mf = dynamic_cast<cMenuFolder *>(SubMenu()))
return cString::sprintf("%s%c%s", Folder->Folder()->Text(), FOLDERDELIMCHAR, *mf->GetFolder());
return Folder->Folder()->Text();
}
@ -930,8 +927,7 @@ void cMenuEditTimer::SetFirstDayItem(void)
eOSState cMenuEditTimer::SetFolder(void)
{
cMenuFolder *mf = (cMenuFolder *)SubMenu();
if (mf) {
if (cMenuFolder *mf = dynamic_cast<cMenuFolder *>(SubMenu())) {
cString Folder = mf->GetFolder();
char *p = strrchr(data.file, FOLDERDELIMCHAR);
if (p)
@ -2105,26 +2101,302 @@ bool CamMenuActive(void)
return CamMenuIsOpen;
}
// --- cMenuPathEdit ---------------------------------------------------------
class cMenuPathEdit : public cOsdMenu {
private:
cString path;
char folder[PATH_MAX];
char name[NAME_MAX];
cMenuEditStrItem *folderItem;
int pathIsInUse;
eOSState SetFolder(void);
eOSState Folder(void);
eOSState ApplyChanges(void);
public:
cMenuPathEdit(const char *Path);
virtual eOSState ProcessKey(eKeys Key);
};
cMenuPathEdit::cMenuPathEdit(const char *Path)
:cOsdMenu(tr("Edit path"), 12)
{
SetMenuCategory(mcRecording);
path = Path;
*folder = 0;
*name = 0;
const char *s = strrchr(path, FOLDERDELIMCHAR);
if (s) {
strn0cpy(folder, cString(path, s), sizeof(folder));
s++;
}
else
s = path;
strn0cpy(name, s, sizeof(name));
pathIsInUse = Recordings.PathIsInUse(path);
if (pathIsInUse) {
Add(new cOsdItem(tr("This folder is currently in use - no changes are possible!"), osUnknown, false));
Add(new cOsdItem("", osUnknown, false));
}
cOsdItem *p;
Add(p = folderItem = new cMenuEditStrItem(tr("Folder"), folder, sizeof(folder)));
p->SetSelectable(!pathIsInUse);
Add(p = new cMenuEditStrItem(tr("Name"), name, sizeof(name)));
p->SetSelectable(!pathIsInUse);
Display();
if (!pathIsInUse)
SetHelp(tr("Button$Folder"));
}
eOSState cMenuPathEdit::SetFolder(void)
{
if (cMenuFolder *mf = dynamic_cast<cMenuFolder *>(SubMenu())) {
strn0cpy(folder, mf->GetFolder(), sizeof(folder));
SetCurrent(folderItem);
Display();
}
return CloseSubMenu();
}
eOSState cMenuPathEdit::Folder(void)
{
return AddSubMenu(new cMenuFolder(tr("Select folder"), &Folders, path));
}
eOSState cMenuPathEdit::ApplyChanges(void)
{
if (!*name)
*name = ' '; // name must not be empty!
cString NewPath = *folder ? cString::sprintf("%s%c%s", folder, FOLDERDELIMCHAR, name) : name;
NewPath.CompactChars(FOLDERDELIMCHAR);
if (strcmp(NewPath, path)) {
int NumRecordings = Recordings.GetNumRecordingsInPath(path);
if (NumRecordings > 1 && !Interface->Confirm(cString::sprintf(tr("Move entire folder containing %d recordings?"), NumRecordings)))
return osContinue;
if (!Recordings.MoveRecordings(path, NewPath)) {
Skins.Message(mtError, tr("Error while moving folder!"));
return osContinue;
}
cMenuRecordings::SetPath(NewPath); // makes sure the Recordings menu will reposition to the new path
return osUser1;
}
return osBack;
}
eOSState cMenuPathEdit::ProcessKey(eKeys Key)
{
eOSState state = cOsdMenu::ProcessKey(Key);
if (state == osUnknown) {
if (!pathIsInUse) {
switch (Key) {
case kRed: return Folder();
case kOk: return ApplyChanges();
default: break;
}
}
else if (Key == kOk)
return osBack;
}
else if (state == osEnd && HasSubMenu())
state = SetFolder();
return state;
}
// --- cMenuRecordingEdit ----------------------------------------------------
class cMenuRecordingEdit : public cOsdMenu {
private:
cRecording *recording;
char folder[PATH_MAX];
char name[NAME_MAX];
int priority;
int lifetime;
cMenuEditStrItem *folderItem;
const char *buttonFolder;
const char *buttonAction;
const char *buttonDeleteMarks;
const char *actionCancel;
const char *doCut;
int recordingIsInUse;
void Set(void);
void SetHelpKeys(void);
eOSState SetFolder(void);
eOSState Folder(void);
eOSState Action(void);
eOSState DeleteMarks(void);
eOSState ApplyChanges(void);
public:
cMenuRecordingEdit(cRecording *Recording);
virtual eOSState ProcessKey(eKeys Key);
};
cMenuRecordingEdit::cMenuRecordingEdit(cRecording *Recording)
:cOsdMenu(tr("Edit recording"), 12)
{
SetMenuCategory(mcRecording);
recording = Recording;
strn0cpy(folder, recording->Folder(), sizeof(folder));
strn0cpy(name, recording->BaseName(), sizeof(name));
priority = recording->Priority();
lifetime = recording->Lifetime();
folderItem = NULL;
buttonFolder = NULL;
buttonAction = NULL;
buttonDeleteMarks = NULL;
actionCancel = NULL;
doCut = NULL;
recordingIsInUse = recording->IsInUse();
Set();
}
void cMenuRecordingEdit::Set(void)
{
Clear();
if (recordingIsInUse) {
Add(new cOsdItem(tr("This recording is currently in use - no changes are possible!"), osUnknown, false));
Add(new cOsdItem("", osUnknown, false));
}
cOsdItem *p;
Add(p = folderItem = new cMenuEditStrItem(tr("Folder"), folder, sizeof(folder)));
p->SetSelectable(!recordingIsInUse);
Add(p = new cMenuEditStrItem(tr("Name"), name, sizeof(name)));
p->SetSelectable(!recordingIsInUse);
Add(p = new cMenuEditIntItem(tr("Priority"), &priority, 0, MAXPRIORITY));
p->SetSelectable(!recordingIsInUse);
Add(p = new cMenuEditIntItem(tr("Lifetime"), &lifetime, 0, MAXLIFETIME));
p->SetSelectable(!recordingIsInUse);
Display();
SetHelpKeys();
}
void cMenuRecordingEdit::SetHelpKeys(void)
{
buttonFolder = !recordingIsInUse ? tr("Button$Folder") : NULL;
buttonAction = NULL;
buttonDeleteMarks = NULL;
actionCancel = NULL;
doCut = NULL;
if ((recordingIsInUse & ruCut) != 0)
buttonAction = actionCancel = ((recordingIsInUse & ruPending) != 0) ? tr("Button$Stop cutting") : tr("Button$Cancel cutting");
else if ((recordingIsInUse & ruMove) != 0)
buttonAction = actionCancel = ((recordingIsInUse & ruPending) != 0) ? tr("Button$Stop moving") : tr("Button$Cancel moving");
else if ((recordingIsInUse & ruCopy) != 0)
buttonAction = actionCancel = ((recordingIsInUse & ruPending) != 0) ? tr("Button$Stop copying") : tr("Button$Cancel copying");
else if (recording->HasMarks()) {
buttonAction = doCut = tr("Button$Cut");
buttonDeleteMarks = tr("Button$Delete marks");
}
SetHelp(buttonFolder, buttonAction, buttonDeleteMarks);
}
eOSState cMenuRecordingEdit::SetFolder(void)
{
if (cMenuFolder *mf = dynamic_cast<cMenuFolder *>(SubMenu())) {
strn0cpy(folder, mf->GetFolder(), sizeof(folder));
SetCurrent(folderItem);
Display();
}
return CloseSubMenu();
}
eOSState cMenuRecordingEdit::Folder(void)
{
return AddSubMenu(new cMenuFolder(tr("Select folder"), &Folders, recording->Name()));
}
eOSState cMenuRecordingEdit::Action(void)
{
if (actionCancel)
RecordingsHandler.Del(recording->FileName());
else if (doCut) {
if (!RecordingsHandler.Add(ruCut, recording->FileName()))
Skins.Message(mtError, tr("Error while queueing recording for cutting!"));
}
recordingIsInUse = recording->IsInUse();
SetHelpKeys();
return osContinue;
}
eOSState cMenuRecordingEdit::DeleteMarks(void)
{
if (buttonDeleteMarks && Interface->Confirm(tr("Delete editing marks for this recording?"))) {
if (recording->DeleteMarks())
SetHelpKeys();
else
Skins.Message(mtError, tr("Error while deleting editing marks!"));
}
return osContinue;
}
eOSState cMenuRecordingEdit::ApplyChanges(void)
{
bool Modified = false;
if (priority != recording->Priority() || lifetime != recording->Lifetime()) {
if (!recording->ChangePriorityLifetime(priority, lifetime)) {
Skins.Message(mtError, tr("Error while changing priority/lifetime!"));
return osContinue;
}
Modified = true;
}
if (!*name)
*name = ' '; // name must not be empty!
cString NewName = *folder ? cString::sprintf("%s%c%s", folder, FOLDERDELIMCHAR, name) : name;
NewName.CompactChars(FOLDERDELIMCHAR);
if (strcmp(NewName, recording->Name())) {
if (!recording->ChangeName(NewName)) {
Skins.Message(mtError, tr("Error while changing folder/name!"));
return osContinue;
}
Modified = true;
}
if (Modified) {
cMenuRecordings::SetRecording(recording->FileName()); // makes sure the Recordings menu will reposition to the renamed recording
return osUser1;
}
return osBack;
}
eOSState cMenuRecordingEdit::ProcessKey(eKeys Key)
{
eOSState state = cOsdMenu::ProcessKey(Key);
if (state == osUnknown) {
if (!recordingIsInUse) {
switch (Key) {
case kRed: return Folder();
case kGreen: return Action();
case kYellow: return DeleteMarks();
case kOk: return ApplyChanges();
default: break;
}
}
else if (Key == kOk)
return osBack;
}
else if (state == osEnd && HasSubMenu())
state = SetFolder();
return state;
}
// --- cMenuRecording --------------------------------------------------------
class cMenuRecording : public cOsdMenu {
private:
const cRecording *recording;
cRecording *recording;
bool withButtons;
public:
cMenuRecording(const cRecording *Recording, bool WithButtons = false);
cMenuRecording(cRecording *Recording, bool WithButtons = false);
virtual void Display(void);
virtual eOSState ProcessKey(eKeys Key);
};
cMenuRecording::cMenuRecording(const cRecording *Recording, bool WithButtons)
cMenuRecording::cMenuRecording(cRecording *Recording, bool WithButtons)
:cOsdMenu(tr("Recording info"))
{
SetMenuCategory(mcRecordingInfo);
recording = Recording;
withButtons = WithButtons;
if (withButtons)
SetHelp(tr("Button$Play"), tr("Button$Rewind"));
SetHelp(tr("Button$Play"), tr("Button$Rewind"), NULL, tr("Button$Edit"));
}
void cMenuRecording::Display(void)
@ -2137,6 +2409,12 @@ void cMenuRecording::Display(void)
eOSState cMenuRecording::ProcessKey(eKeys Key)
{
if (HasSubMenu()) {
eOSState state = cOsdMenu::ProcessKey(Key);
if (state == osUser1)
CloseSubMenu();
return state;
}
switch (int(Key)) {
case kUp|k_Repeat:
case kUp:
@ -2164,6 +2442,9 @@ eOSState cMenuRecording::ProcessKey(eKeys Key)
cRemote::Put(Key, true);
// continue with osBack to close the info menu and process the key
case kOk: return osBack;
case kBlue: if (withButtons)
return AddSubMenu(new cMenuRecordingEdit(recording));
break;
default: break;
}
}
@ -2183,6 +2464,7 @@ public:
~cMenuRecordingItem();
void IncrementCounter(bool New);
const char *Name(void) { return name; }
int Level(void) { return level; }
cRecording *Recording(void) { return recording; }
bool IsDirectory(void) { return name != NULL; }
virtual void SetMenuItem(cSkinDisplayMenu *DisplayMenu, int Index, bool Current, bool Selectable);
@ -2220,6 +2502,9 @@ void cMenuRecordingItem::SetMenuItem(cSkinDisplayMenu *DisplayMenu, int Index, b
// --- cMenuRecordings -------------------------------------------------------
cString cMenuRecordings::path;
cString cMenuRecordings::fileName;
cMenuRecordings::cMenuRecordings(const char *Base, int Level, bool OpenSubMenus)
:cOsdMenu(Base ? Base : tr("Recordings"), 9, 6, 6)
{
@ -2232,8 +2517,12 @@ cMenuRecordings::cMenuRecordings(const char *Base, int Level, bool OpenSubMenus)
Set();
if (Current() < 0)
SetCurrent(First());
else if (OpenSubMenus && cReplayControl::LastReplayed() && Open(true))
return;
else if (OpenSubMenus && (cReplayControl::LastReplayed() || *path || *fileName)) {
if (!*path || Level < strcountchr(path, FOLDERDELIMCHAR)) {
if (Open(true))
return;
}
}
Display();
SetHelpKeys();
}
@ -2251,18 +2540,14 @@ void cMenuRecordings::SetHelpKeys(void)
if (ri) {
if (ri->IsDirectory())
NewHelpKeys = 1;
else {
else
NewHelpKeys = 2;
if (ri->Recording()->Info()->Title())
NewHelpKeys = 3;
}
}
if (NewHelpKeys != helpKeys) {
switch (NewHelpKeys) {
case 0: SetHelp(NULL); break;
case 1: SetHelp(tr("Button$Open")); break;
case 2:
case 3: SetHelp(RecordingCommands.Count() ? tr("Commands") : tr("Button$Play"), tr("Button$Rewind"), tr("Button$Delete"), NewHelpKeys == 3 ? tr("Button$Info") : NULL);
case 1: SetHelp(tr("Button$Open"), NULL, NULL, tr("Button$Edit")); break;
case 2: SetHelp(RecordingCommands.Count() ? tr("Commands") : tr("Button$Play"), tr("Button$Rewind"), tr("Button$Delete"), tr("Button$Info"));
default: ;
}
helpKeys = NewHelpKeys;
@ -2271,7 +2556,7 @@ void cMenuRecordings::SetHelpKeys(void)
void cMenuRecordings::Set(bool Refresh)
{
const char *CurrentRecording = cReplayControl::LastReplayed();
const char *CurrentRecording = *fileName ? *fileName : cReplayControl::LastReplayed();
cMenuRecordingItem *LastItem = NULL;
cThreadLock RecordingsLock(&Recordings);
if (Refresh) {
@ -2303,7 +2588,11 @@ void cMenuRecordings::Set(bool Refresh)
else
delete Item;
if (LastItem || LastDir) {
if (CurrentRecording && strcmp(CurrentRecording, recording->FileName()) == 0)
if (*path) {
if (strcmp(path, recording->Folder()) == 0)
SetCurrent(LastDir ? LastDir : LastItem);
}
else if (CurrentRecording && strcmp(CurrentRecording, recording->FileName()) == 0)
SetCurrent(LastDir ? LastDir : LastItem);
}
if (LastDir)
@ -2314,6 +2603,16 @@ void cMenuRecordings::Set(bool Refresh)
Display();
}
void cMenuRecordings::SetPath(const char *Path)
{
path = Path;
}
void cMenuRecordings::SetRecording(const char *FileName)
{
fileName = FileName;
}
cString cMenuRecordings::DirectoryName(void)
{
cString d(cVideoDirectory::Name());
@ -2328,11 +2627,11 @@ cString cMenuRecordings::DirectoryName(void)
bool cMenuRecordings::Open(bool OpenSubMenus)
{
cMenuRecordingItem *ri = (cMenuRecordingItem *)Get(Current());
if (ri && ri->IsDirectory()) {
if (ri && ri->IsDirectory() && (!*path || strcountchr(path, FOLDERDELIMCHAR) > 0)) {
const char *t = ri->Name();
cString buffer;
if (base) {
buffer = cString::sprintf("%s~%s", base, t);
buffer = cString::sprintf("%s%c%s", base, FOLDERDELIMCHAR, t);
t = buffer;
}
AddSubMenu(new cMenuRecordings(t, level + 1, OpenSubMenus));
@ -2395,10 +2694,10 @@ eOSState cMenuRecordings::Delete(void)
}
cRecording *recording = ri->Recording();
cString FileName = recording->FileName();
if (cCutter::Active(ri->Recording()->FileName())) {
if (RecordingsHandler.GetUsage(FileName)) {
if (Interface->Confirm(tr("Recording is being edited - really delete?"))) {
cCutter::Stop();
recording = Recordings.GetByName(FileName); // cCutter::Stop() might have deleted it if it was the edited version
RecordingsHandler.Del(FileName);
recording = Recordings.GetByName(FileName); // RecordingsHandler.Del() might have deleted it if it was the edited version
// we continue with the code below even if recording is NULL,
// in order to have the menu updated etc.
}
@ -2428,9 +2727,12 @@ eOSState cMenuRecordings::Info(void)
{
if (HasSubMenu() || Count() == 0)
return osContinue;
cMenuRecordingItem *ri = (cMenuRecordingItem *)Get(Current());
if (ri && !ri->IsDirectory() && ri->Recording()->Info()->Title())
return AddSubMenu(new cMenuRecording(ri->Recording(), true));
if (cMenuRecordingItem *ri = (cMenuRecordingItem *)Get(Current())) {
if (ri->IsDirectory())
return AddSubMenu(new cMenuPathEdit(cString(ri->Recording()->Name(), strchrn(ri->Recording()->Name(), FOLDERDELIMCHAR, ri->Level() + 1))));
else
return AddSubMenu(new cMenuRecording(ri->Recording(), true));
}
return osContinue;
}
@ -2481,6 +2783,17 @@ eOSState cMenuRecordings::ProcessKey(eKeys Key)
default: break;
}
}
else if (state == osUser1) {
// a recording or path was renamed, so let's refresh the menu
CloseSubMenu(false);
if (base)
return state; // closes all recording menus except for the top one
Set(); // this is the top level menu, so we refresh it...
Open(true); // ...and open any necessary submenus to show the new name
Display();
path = NULL;
fileName = NULL;
}
if (Key == kYellow && HadSubMenu && !HasSubMenu()) {
// the last recording in a subdirectory was deleted, so let's go back up
cOsdMenu::Del(Current());
@ -3462,13 +3775,13 @@ bool cMenuMain::Update(bool Force)
}
// Editing control:
bool CutterActive = cCutter::Active();
if (CutterActive && !cancelEditingItem) {
bool EditingActive = RecordingsHandler.Active();
if (EditingActive && !cancelEditingItem) {
// TRANSLATORS: note the leading blank!
Add(cancelEditingItem = new cOsdItem(tr(" Cancel editing"), osCancelEdit));
result = true;
}
else if (cancelEditingItem && !CutterActive) {
else if (cancelEditingItem && !EditingActive) {
Del(cancelEditingItem->Index());
cancelEditingItem = NULL;
result = true;
@ -3518,7 +3831,7 @@ eOSState cMenuMain::ProcessKey(eKeys Key)
}
break;
case osCancelEdit: if (Interface->Confirm(tr("Cancel editing?"))) {
cCutter::Stop();
RecordingsHandler.DelAll();
return osEnd;
}
break;
@ -4853,12 +5166,12 @@ void cReplayControl::EditCut(void)
{
if (*fileName) {
Hide();
if (!cCutter::Active()) {
if (!RecordingsHandler.GetUsage(fileName)) {
if (!marks.Count())
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 (!RecordingsHandler.Add(ruCut, fileName))
Skins.Message(mtError, tr("Can't start editing process!"));
else
Skins.Message(mtInfo, tr("Editing process started"));

6
menu.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: menu.h 3.1 2013/06/01 13:44:57 kls Exp $
* $Id: menu.h 3.2 2013/09/22 10:47:32 kls Exp $
*/
#ifndef __MENU_H
@ -198,6 +198,8 @@ private:
int level;
int recordingsState;
int helpKeys;
static cString path;
static cString fileName;
void SetHelpKeys(void);
void Set(bool Refresh = false);
bool Open(bool OpenSubMenus = false);
@ -213,6 +215,8 @@ public:
cMenuRecordings(const char *Base = NULL, int Level = 0, bool OpenSubMenus = false);
~cMenuRecordings();
virtual eOSState ProcessKey(eKeys Key);
static void SetPath(const char *Path);
static void SetRecording(const char *FileName);
};
class cRecordControl {

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: osdbase.c 3.1 2013/05/24 10:19:31 kls Exp $
* $Id: osdbase.c 3.2 2013/09/22 14:01:17 kls Exp $
*/
#include "osdbase.h"
@ -502,12 +502,14 @@ eOSState cOsdMenu::AddSubMenu(cOsdMenu *SubMenu)
return osContinue; // convenience return value
}
eOSState cOsdMenu::CloseSubMenu()
eOSState cOsdMenu::CloseSubMenu(bool ReDisplay)
{
delete subMenu;
subMenu = NULL;
RefreshCurrent();
Display();
if (ReDisplay) {
RefreshCurrent();
Display();
}
return osContinue; // convenience return value
}

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: osdbase.h 2.5 2012/12/07 09:49:35 kls Exp $
* $Id: osdbase.h 3.1 2013/09/22 14:00:47 kls Exp $
*/
#ifndef __OSDBASE_H
@ -119,7 +119,7 @@ protected:
void Mark(void);
eOSState HotKey(eKeys Key);
eOSState AddSubMenu(cOsdMenu *SubMenu);
eOSState CloseSubMenu();
eOSState CloseSubMenu(bool ReDisplay = true);
bool HasSubMenu(void) { return subMenu; }
cOsdMenu *SubMenu(void) { return subMenu; }
void SetStatus(const char *s);

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-06-10 12:16+0200\n"
"POT-Creation-Date: 2013-10-10 14:32+0200\n"
"PO-Revision-Date: 2008-10-16 11:16-0400\n"
"Last-Translator: Osama Alrawab <alrawab@hotmail.com>\n"
"Language-Team: Arabic <ar@li.org>\n"
@ -727,6 +727,67 @@ msgstr "الرجاء ادخال %d رقم!"
msgid "CAM not responding!"
msgstr "الكامة لا تستجيب"
msgid "Edit path"
msgstr ""
msgid "This folder is currently in use - no changes are possible!"
msgstr ""
msgid "Folder"
msgstr ""
#, c-format
msgid "Move entire folder containing %d recordings?"
msgstr ""
msgid "Error while moving folder!"
msgstr ""
msgid "Edit recording"
msgstr ""
msgid "This recording is currently in use - no changes are possible!"
msgstr ""
msgid "Button$Stop cutting"
msgstr ""
msgid "Button$Cancel cutting"
msgstr ""
msgid "Button$Stop moving"
msgstr ""
msgid "Button$Cancel moving"
msgstr ""
msgid "Button$Stop copying"
msgstr ""
msgid "Button$Cancel copying"
msgstr ""
msgid "Button$Cut"
msgstr ""
msgid "Button$Delete marks"
msgstr ""
msgid "Error while queueing recording for cutting!"
msgstr ""
msgid "Delete editing marks for this recording?"
msgstr ""
msgid "Error while deleting editing marks!"
msgstr ""
msgid "Error while changing priority/lifetime!"
msgstr ""
msgid "Error while changing folder/name!"
msgstr ""
msgid "Recording info"
msgstr "معلومات التسجبل"

View File

@ -10,7 +10,7 @@ msgid ""
msgstr ""
"Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-06-10 12:16+0200\n"
"POT-Creation-Date: 2013-10-10 14:32+0200\n"
"PO-Revision-Date: 2008-03-02 19:02+0100\n"
"Last-Translator: Luca Olivetti <luca@ventoso.org>\n"
"Language-Team: Catalan <vdr@linuxtv.org>\n"
@ -726,6 +726,67 @@ msgstr "Si us plau introdueixi %d digitos"
msgid "CAM not responding!"
msgstr "CAM no respon"
msgid "Edit path"
msgstr ""
msgid "This folder is currently in use - no changes are possible!"
msgstr ""
msgid "Folder"
msgstr ""
#, c-format
msgid "Move entire folder containing %d recordings?"
msgstr ""
msgid "Error while moving folder!"
msgstr ""
msgid "Edit recording"
msgstr ""
msgid "This recording is currently in use - no changes are possible!"
msgstr ""
msgid "Button$Stop cutting"
msgstr ""
msgid "Button$Cancel cutting"
msgstr ""
msgid "Button$Stop moving"
msgstr ""
msgid "Button$Cancel moving"
msgstr ""
msgid "Button$Stop copying"
msgstr ""
msgid "Button$Cancel copying"
msgstr ""
msgid "Button$Cut"
msgstr ""
msgid "Button$Delete marks"
msgstr ""
msgid "Error while queueing recording for cutting!"
msgstr ""
msgid "Delete editing marks for this recording?"
msgstr ""
msgid "Error while deleting editing marks!"
msgstr ""
msgid "Error while changing priority/lifetime!"
msgstr ""
msgid "Error while changing folder/name!"
msgstr ""
msgid "Recording info"
msgstr "Informació de la gravació"

View File

@ -10,7 +10,7 @@ msgid ""
msgstr ""
"Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-06-10 12:16+0200\n"
"POT-Creation-Date: 2013-10-10 14:32+0200\n"
"PO-Revision-Date: 2010-05-06 11:00+0200\n"
"Last-Translator: Aleš Juřík <ajurik@quick.cz>\n"
"Language-Team: Czech <vdr@linuxtv.org>\n"
@ -726,6 +726,67 @@ msgstr "Prosím vložte %d znaků!"
msgid "CAM not responding!"
msgstr "CAM neodpovídá!"
msgid "Edit path"
msgstr ""
msgid "This folder is currently in use - no changes are possible!"
msgstr ""
msgid "Folder"
msgstr ""
#, c-format
msgid "Move entire folder containing %d recordings?"
msgstr ""
msgid "Error while moving folder!"
msgstr ""
msgid "Edit recording"
msgstr ""
msgid "This recording is currently in use - no changes are possible!"
msgstr ""
msgid "Button$Stop cutting"
msgstr ""
msgid "Button$Cancel cutting"
msgstr ""
msgid "Button$Stop moving"
msgstr ""
msgid "Button$Cancel moving"
msgstr ""
msgid "Button$Stop copying"
msgstr ""
msgid "Button$Cancel copying"
msgstr ""
msgid "Button$Cut"
msgstr ""
msgid "Button$Delete marks"
msgstr ""
msgid "Error while queueing recording for cutting!"
msgstr ""
msgid "Delete editing marks for this recording?"
msgstr ""
msgid "Error while deleting editing marks!"
msgstr ""
msgid "Error while changing priority/lifetime!"
msgstr ""
msgid "Error while changing folder/name!"
msgstr ""
msgid "Recording info"
msgstr "Detail nahrávky"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-06-10 12:16+0200\n"
"POT-Creation-Date: 2013-10-10 14:32+0200\n"
"PO-Revision-Date: 2007-08-12 14:17+0200\n"
"Last-Translator: Mogens Elneff <mogens@elneff.dk>\n"
"Language-Team: Danish <vdr@linuxtv.org>\n"
@ -723,6 +723,67 @@ msgstr "Indtast venligst %d cifre!"
msgid "CAM not responding!"
msgstr "CAM svarer ikke!"
msgid "Edit path"
msgstr ""
msgid "This folder is currently in use - no changes are possible!"
msgstr ""
msgid "Folder"
msgstr ""
#, c-format
msgid "Move entire folder containing %d recordings?"
msgstr ""
msgid "Error while moving folder!"
msgstr ""
msgid "Edit recording"
msgstr ""
msgid "This recording is currently in use - no changes are possible!"
msgstr ""
msgid "Button$Stop cutting"
msgstr ""
msgid "Button$Cancel cutting"
msgstr ""
msgid "Button$Stop moving"
msgstr ""
msgid "Button$Cancel moving"
msgstr ""
msgid "Button$Stop copying"
msgstr ""
msgid "Button$Cancel copying"
msgstr ""
msgid "Button$Cut"
msgstr ""
msgid "Button$Delete marks"
msgstr ""
msgid "Error while queueing recording for cutting!"
msgstr ""
msgid "Delete editing marks for this recording?"
msgstr ""
msgid "Error while deleting editing marks!"
msgstr ""
msgid "Error while changing priority/lifetime!"
msgstr ""
msgid "Error while changing folder/name!"
msgstr ""
msgid "Recording info"
msgstr "Optagelses info"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-06-10 12:16+0200\n"
"POT-Creation-Date: 2013-10-10 14:32+0200\n"
"PO-Revision-Date: 2010-01-16 16:46+0100\n"
"Last-Translator: Klaus Schmidinger <vdr@tvdr.de>\n"
"Language-Team: German <vdr@linuxtv.org>\n"
@ -723,6 +723,67 @@ msgstr "Bitte geben Sie %d Ziffern ein!"
msgid "CAM not responding!"
msgstr "CAM antwortet nicht!"
msgid "Edit path"
msgstr "Pfad editieren"
msgid "This folder is currently in use - no changes are possible!"
msgstr "Dieser Ordner ist zur Zeit in Verwendung - es sind keine Änderungen möglich!"
msgid "Folder"
msgstr "Ordner"
#, c-format
msgid "Move entire folder containing %d recordings?"
msgstr "Ganzen Ordner mit %d Aufnahmen verschieben?"
msgid "Error while moving folder!"
msgstr "Fehler beim Verschieben des Ordners!"
msgid "Edit recording"
msgstr "Aufnahme editieren"
msgid "This recording is currently in use - no changes are possible!"
msgstr "Diese Aufnahme ist zur Zeit in Verwendung - es sind keine Änderungen möglich!"
msgid "Button$Stop cutting"
msgstr "Schnitt beenden"
msgid "Button$Cancel cutting"
msgstr "Schnitt abbrechen"
msgid "Button$Stop moving"
msgstr "Verschieben beenden"
msgid "Button$Cancel moving"
msgstr "Verschieben abbrechen"
msgid "Button$Stop copying"
msgstr "Kopieren beenden"
msgid "Button$Cancel copying"
msgstr "Kopieren abbrechen"
msgid "Button$Cut"
msgstr "Schneiden"
msgid "Button$Delete marks"
msgstr "Marken löschen"
msgid "Error while queueing recording for cutting!"
msgstr "Fehler beim Hinzufügen der Aufnahme zur Schnittwarteschlange"
msgid "Delete editing marks for this recording?"
msgstr "Schnittmarken für diese Aufnahme löschen?"
msgid "Error while deleting editing marks!"
msgstr "Fehler beim Löschen der Schnittmarken!"
msgid "Error while changing priority/lifetime!"
msgstr "Fehler beim Ändern der Priorität bzw. Lebensdauer!"
msgid "Error while changing folder/name!"
msgstr "Fehler beim Ändern des Ordners bzw. Namens!"
msgid "Recording info"
msgstr "Aufzeichnung"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-06-10 12:16+0200\n"
"POT-Creation-Date: 2013-10-10 14:32+0200\n"
"PO-Revision-Date: 2007-08-12 14:17+0200\n"
"Last-Translator: Dimitrios Dimitrakos <mail@dimitrios.de>\n"
"Language-Team: Greek <vdr@linuxtv.org>\n"
@ -723,6 +723,67 @@ msgstr ""
msgid "CAM not responding!"
msgstr ""
msgid "Edit path"
msgstr ""
msgid "This folder is currently in use - no changes are possible!"
msgstr ""
msgid "Folder"
msgstr ""
#, c-format
msgid "Move entire folder containing %d recordings?"
msgstr ""
msgid "Error while moving folder!"
msgstr ""
msgid "Edit recording"
msgstr ""
msgid "This recording is currently in use - no changes are possible!"
msgstr ""
msgid "Button$Stop cutting"
msgstr ""
msgid "Button$Cancel cutting"
msgstr ""
msgid "Button$Stop moving"
msgstr ""
msgid "Button$Cancel moving"
msgstr ""
msgid "Button$Stop copying"
msgstr ""
msgid "Button$Cancel copying"
msgstr ""
msgid "Button$Cut"
msgstr ""
msgid "Button$Delete marks"
msgstr ""
msgid "Error while queueing recording for cutting!"
msgstr ""
msgid "Delete editing marks for this recording?"
msgstr ""
msgid "Error while deleting editing marks!"
msgstr ""
msgid "Error while changing priority/lifetime!"
msgstr ""
msgid "Error while changing folder/name!"
msgstr ""
msgid "Recording info"
msgstr "Ðëçñïöïñßåò EããñáöÞò"

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-06-10 12:16+0200\n"
"POT-Creation-Date: 2013-10-10 14:32+0200\n"
"PO-Revision-Date: 2008-03-02 19:02+0100\n"
"Last-Translator: Luca Olivetti <luca@ventoso.org>\n"
"Language-Team: Spanish <vdr@linuxtv.org>\n"
@ -724,6 +724,67 @@ msgstr "
msgid "CAM not responding!"
msgstr "¡CAM no responde!"
msgid "Edit path"
msgstr ""
msgid "This folder is currently in use - no changes are possible!"
msgstr ""
msgid "Folder"
msgstr ""
#, c-format
msgid "Move entire folder containing %d recordings?"
msgstr ""
msgid "Error while moving folder!"
msgstr ""
msgid "Edit recording"
msgstr ""
msgid "This recording is currently in use - no changes are possible!"
msgstr ""
msgid "Button$Stop cutting"
msgstr ""
msgid "Button$Cancel cutting"
msgstr ""
msgid "Button$Stop moving"
msgstr ""
msgid "Button$Cancel moving"
msgstr ""
msgid "Button$Stop copying"
msgstr ""
msgid "Button$Cancel copying"
msgstr ""
msgid "Button$Cut"
msgstr ""
msgid "Button$Delete marks"
msgstr ""
msgid "Error while queueing recording for cutting!"
msgstr ""
msgid "Delete editing marks for this recording?"
msgstr ""
msgid "Error while deleting editing marks!"
msgstr ""
msgid "Error while changing priority/lifetime!"
msgstr ""
msgid "Error while changing folder/name!"
msgstr ""
msgid "Recording info"
msgstr "Información de grabación"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-06-10 12:16+0200\n"
"POT-Creation-Date: 2013-10-10 14:32+0200\n"
"PO-Revision-Date: 2007-08-12 14:17+0200\n"
"Last-Translator: Arthur Konovalov <artlov@gmail.com>\n"
"Language-Team: Estonian <vdr@linuxtv.org>\n"
@ -723,6 +723,67 @@ msgstr "Palun sisestada %d numbrit!"
msgid "CAM not responding!"
msgstr "CAM ei vasta"
msgid "Edit path"
msgstr ""
msgid "This folder is currently in use - no changes are possible!"
msgstr ""
msgid "Folder"
msgstr ""
#, c-format
msgid "Move entire folder containing %d recordings?"
msgstr ""
msgid "Error while moving folder!"
msgstr ""
msgid "Edit recording"
msgstr ""
msgid "This recording is currently in use - no changes are possible!"
msgstr ""
msgid "Button$Stop cutting"
msgstr ""
msgid "Button$Cancel cutting"
msgstr ""
msgid "Button$Stop moving"
msgstr ""
msgid "Button$Cancel moving"
msgstr ""
msgid "Button$Stop copying"
msgstr ""
msgid "Button$Cancel copying"
msgstr ""
msgid "Button$Cut"
msgstr ""
msgid "Button$Delete marks"
msgstr ""
msgid "Error while queueing recording for cutting!"
msgstr ""
msgid "Delete editing marks for this recording?"
msgstr ""
msgid "Error while deleting editing marks!"
msgstr ""
msgid "Error while changing priority/lifetime!"
msgstr ""
msgid "Error while changing folder/name!"
msgstr ""
msgid "Recording info"
msgstr "Salvestuse info"

View File

@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-06-10 12:16+0200\n"
"POT-Creation-Date: 2013-10-10 14:32+0200\n"
"PO-Revision-Date: 2007-08-15 15:52+0200\n"
"Last-Translator: Matti Lehtimäki <matti.lehtimaki@gmail.com>\n"
"Language-Team: Finnish <vdr@linuxtv.org>\n"
@ -727,6 +727,67 @@ msgstr "Syötä %d numeroa!"
msgid "CAM not responding!"
msgstr "CA-moduuli ei vastaa!"
msgid "Edit path"
msgstr ""
msgid "This folder is currently in use - no changes are possible!"
msgstr ""
msgid "Folder"
msgstr ""
#, c-format
msgid "Move entire folder containing %d recordings?"
msgstr ""
msgid "Error while moving folder!"
msgstr ""
msgid "Edit recording"
msgstr ""
msgid "This recording is currently in use - no changes are possible!"
msgstr ""
msgid "Button$Stop cutting"
msgstr ""
msgid "Button$Cancel cutting"
msgstr ""
msgid "Button$Stop moving"
msgstr ""
msgid "Button$Cancel moving"
msgstr ""
msgid "Button$Stop copying"
msgstr ""
msgid "Button$Cancel copying"
msgstr ""
msgid "Button$Cut"
msgstr ""
msgid "Button$Delete marks"
msgstr ""
msgid "Error while queueing recording for cutting!"
msgstr ""
msgid "Delete editing marks for this recording?"
msgstr ""
msgid "Error while deleting editing marks!"
msgstr ""
msgid "Error while changing priority/lifetime!"
msgstr ""
msgid "Error while changing folder/name!"
msgstr ""
msgid "Recording info"
msgstr "Tallenteen tiedot"

View File

@ -17,7 +17,7 @@ msgid ""
msgstr ""
"Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-06-10 12:16+0200\n"
"POT-Creation-Date: 2013-10-10 14:32+0200\n"
"PO-Revision-Date: 2013-02-24 12:56+0100\n"
"Last-Translator: Dominique Plu <dplu@free.fr>\n"
"Language-Team: French <vdr@linuxtv.org>\n"
@ -733,6 +733,67 @@ msgstr "Veuillez entrer %d chiffres !"
msgid "CAM not responding!"
msgstr "Pas de réponse du CAM"
msgid "Edit path"
msgstr ""
msgid "This folder is currently in use - no changes are possible!"
msgstr ""
msgid "Folder"
msgstr ""
#, c-format
msgid "Move entire folder containing %d recordings?"
msgstr ""
msgid "Error while moving folder!"
msgstr ""
msgid "Edit recording"
msgstr ""
msgid "This recording is currently in use - no changes are possible!"
msgstr ""
msgid "Button$Stop cutting"
msgstr ""
msgid "Button$Cancel cutting"
msgstr ""
msgid "Button$Stop moving"
msgstr ""
msgid "Button$Cancel moving"
msgstr ""
msgid "Button$Stop copying"
msgstr ""
msgid "Button$Cancel copying"
msgstr ""
msgid "Button$Cut"
msgstr ""
msgid "Button$Delete marks"
msgstr ""
msgid "Error while queueing recording for cutting!"
msgstr ""
msgid "Delete editing marks for this recording?"
msgstr ""
msgid "Error while deleting editing marks!"
msgstr ""
msgid "Error while changing priority/lifetime!"
msgstr ""
msgid "Error while changing folder/name!"
msgstr ""
msgid "Recording info"
msgstr "Infos sur l'enregistrement"

View File

@ -9,7 +9,7 @@ msgid ""
msgstr ""
"Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-06-10 12:16+0200\n"
"POT-Creation-Date: 2013-10-10 14:32+0200\n"
"PO-Revision-Date: 2008-03-17 19:00+0100\n"
"Last-Translator: Adrian Caval <anrxc@sysphere.org>\n"
"Language-Team: Croatian <vdr@linuxtv.org>\n"
@ -725,6 +725,67 @@ msgstr "Molim unesite %d znamenki!"
msgid "CAM not responding!"
msgstr "CAM ne odgovara!"
msgid "Edit path"
msgstr ""
msgid "This folder is currently in use - no changes are possible!"
msgstr ""
msgid "Folder"
msgstr ""
#, c-format
msgid "Move entire folder containing %d recordings?"
msgstr ""
msgid "Error while moving folder!"
msgstr ""
msgid "Edit recording"
msgstr ""
msgid "This recording is currently in use - no changes are possible!"
msgstr ""
msgid "Button$Stop cutting"
msgstr ""
msgid "Button$Cancel cutting"
msgstr ""
msgid "Button$Stop moving"
msgstr ""
msgid "Button$Cancel moving"
msgstr ""
msgid "Button$Stop copying"
msgstr ""
msgid "Button$Cancel copying"
msgstr ""
msgid "Button$Cut"
msgstr ""
msgid "Button$Delete marks"
msgstr ""
msgid "Error while queueing recording for cutting!"
msgstr ""
msgid "Delete editing marks for this recording?"
msgstr ""
msgid "Error while deleting editing marks!"
msgstr ""
msgid "Error while changing priority/lifetime!"
msgstr ""
msgid "Error while changing folder/name!"
msgstr ""
msgid "Recording info"
msgstr "Detalji snimanja"

View File

@ -10,7 +10,7 @@ msgid ""
msgstr ""
"Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-06-10 12:16+0200\n"
"POT-Creation-Date: 2013-10-10 14:32+0200\n"
"PO-Revision-Date: 2013-03-01 19:22+0200\n"
"Last-Translator: István Füley <ifuley@tigercomp.ro>\n"
"Language-Team: Hungarian <vdr@linuxtv.org>\n"
@ -727,6 +727,67 @@ msgstr "Üssön be %d számot!"
msgid "CAM not responding!"
msgstr "A CAM nem válaszol!"
msgid "Edit path"
msgstr ""
msgid "This folder is currently in use - no changes are possible!"
msgstr ""
msgid "Folder"
msgstr ""
#, c-format
msgid "Move entire folder containing %d recordings?"
msgstr ""
msgid "Error while moving folder!"
msgstr ""
msgid "Edit recording"
msgstr ""
msgid "This recording is currently in use - no changes are possible!"
msgstr ""
msgid "Button$Stop cutting"
msgstr ""
msgid "Button$Cancel cutting"
msgstr ""
msgid "Button$Stop moving"
msgstr ""
msgid "Button$Cancel moving"
msgstr ""
msgid "Button$Stop copying"
msgstr ""
msgid "Button$Cancel copying"
msgstr ""
msgid "Button$Cut"
msgstr ""
msgid "Button$Delete marks"
msgstr ""
msgid "Error while queueing recording for cutting!"
msgstr ""
msgid "Delete editing marks for this recording?"
msgstr ""
msgid "Error while deleting editing marks!"
msgstr ""
msgid "Error while changing priority/lifetime!"
msgstr ""
msgid "Error while changing folder/name!"
msgstr ""
msgid "Recording info"
msgstr "Felvétel infó"

View File

@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-06-10 12:16+0200\n"
"POT-Creation-Date: 2013-10-10 14:32+0200\n"
"PO-Revision-Date: 2013-02-11 23:46+0100\n"
"Last-Translator: Diego Pierotto <vdr-italian@tiscali.it>\n"
"Language-Team: Italian <vdr@linuxtv.org>\n"
@ -730,6 +730,67 @@ msgstr "Inserisci %d cifre!"
msgid "CAM not responding!"
msgstr "La CAM non risponde!"
msgid "Edit path"
msgstr ""
msgid "This folder is currently in use - no changes are possible!"
msgstr ""
msgid "Folder"
msgstr ""
#, c-format
msgid "Move entire folder containing %d recordings?"
msgstr ""
msgid "Error while moving folder!"
msgstr ""
msgid "Edit recording"
msgstr ""
msgid "This recording is currently in use - no changes are possible!"
msgstr ""
msgid "Button$Stop cutting"
msgstr ""
msgid "Button$Cancel cutting"
msgstr ""
msgid "Button$Stop moving"
msgstr ""
msgid "Button$Cancel moving"
msgstr ""
msgid "Button$Stop copying"
msgstr ""
msgid "Button$Cancel copying"
msgstr ""
msgid "Button$Cut"
msgstr ""
msgid "Button$Delete marks"
msgstr ""
msgid "Error while queueing recording for cutting!"
msgstr ""
msgid "Delete editing marks for this recording?"
msgstr ""
msgid "Error while deleting editing marks!"
msgstr ""
msgid "Error while changing priority/lifetime!"
msgstr ""
msgid "Error while changing folder/name!"
msgstr ""
msgid "Recording info"
msgstr "Info registrazione"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-06-10 12:16+0200\n"
"POT-Creation-Date: 2013-10-10 14:32+0200\n"
"PO-Revision-Date: 2010-10-30 11:55+0200\n"
"Last-Translator: Valdemaras Pipiras <varas@ambernet.lt>\n"
"Language-Team: Lithuanian <vdr@linuxtv.org>\n"
@ -723,6 +723,67 @@ msgstr "Įveskite %d skaičius!"
msgid "CAM not responding!"
msgstr "Dekodavimo modulis (CAM) neveikia!"
msgid "Edit path"
msgstr ""
msgid "This folder is currently in use - no changes are possible!"
msgstr ""
msgid "Folder"
msgstr ""
#, c-format
msgid "Move entire folder containing %d recordings?"
msgstr ""
msgid "Error while moving folder!"
msgstr ""
msgid "Edit recording"
msgstr ""
msgid "This recording is currently in use - no changes are possible!"
msgstr ""
msgid "Button$Stop cutting"
msgstr ""
msgid "Button$Cancel cutting"
msgstr ""
msgid "Button$Stop moving"
msgstr ""
msgid "Button$Cancel moving"
msgstr ""
msgid "Button$Stop copying"
msgstr ""
msgid "Button$Cancel copying"
msgstr ""
msgid "Button$Cut"
msgstr ""
msgid "Button$Delete marks"
msgstr ""
msgid "Error while queueing recording for cutting!"
msgstr ""
msgid "Delete editing marks for this recording?"
msgstr ""
msgid "Error while deleting editing marks!"
msgstr ""
msgid "Error while changing priority/lifetime!"
msgstr ""
msgid "Error while changing folder/name!"
msgstr ""
msgid "Recording info"
msgstr "Informacija apie įrašus"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-06-10 12:16+0200\n"
"POT-Creation-Date: 2013-10-10 14:32+0200\n"
"PO-Revision-Date: 2012-11-19 15:18+0100\n"
"Last-Translator: Dimitar Petrovski <dimeptr@gmail.com>\n"
"Language-Team: Macedonian <en@li.org>\n"
@ -724,6 +724,67 @@ msgstr "Внеси %d цифри!"
msgid "CAM not responding!"
msgstr "CAM не одговара!"
msgid "Edit path"
msgstr ""
msgid "This folder is currently in use - no changes are possible!"
msgstr ""
msgid "Folder"
msgstr ""
#, c-format
msgid "Move entire folder containing %d recordings?"
msgstr ""
msgid "Error while moving folder!"
msgstr ""
msgid "Edit recording"
msgstr ""
msgid "This recording is currently in use - no changes are possible!"
msgstr ""
msgid "Button$Stop cutting"
msgstr ""
msgid "Button$Cancel cutting"
msgstr ""
msgid "Button$Stop moving"
msgstr ""
msgid "Button$Cancel moving"
msgstr ""
msgid "Button$Stop copying"
msgstr ""
msgid "Button$Cancel copying"
msgstr ""
msgid "Button$Cut"
msgstr ""
msgid "Button$Delete marks"
msgstr ""
msgid "Error while queueing recording for cutting!"
msgstr ""
msgid "Delete editing marks for this recording?"
msgstr ""
msgid "Error while deleting editing marks!"
msgstr ""
msgid "Error while changing priority/lifetime!"
msgstr ""
msgid "Error while changing folder/name!"
msgstr ""
msgid "Recording info"
msgstr "Детали на снимката"

View File

@ -12,7 +12,7 @@ msgid ""
msgstr ""
"Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-06-10 12:16+0200\n"
"POT-Creation-Date: 2013-10-10 14:32+0200\n"
"PO-Revision-Date: 2008-02-26 17:20+0100\n"
"Last-Translator: Cedric Dewijs <cedric.dewijs@telfort.nl>\n"
"Language-Team: Dutch <vdr@linuxtv.org>\n"
@ -728,6 +728,67 @@ msgstr "Vul %d cijfers in!"
msgid "CAM not responding!"
msgstr "CAM reageert niet!"
msgid "Edit path"
msgstr ""
msgid "This folder is currently in use - no changes are possible!"
msgstr ""
msgid "Folder"
msgstr ""
#, c-format
msgid "Move entire folder containing %d recordings?"
msgstr ""
msgid "Error while moving folder!"
msgstr ""
msgid "Edit recording"
msgstr ""
msgid "This recording is currently in use - no changes are possible!"
msgstr ""
msgid "Button$Stop cutting"
msgstr ""
msgid "Button$Cancel cutting"
msgstr ""
msgid "Button$Stop moving"
msgstr ""
msgid "Button$Cancel moving"
msgstr ""
msgid "Button$Stop copying"
msgstr ""
msgid "Button$Cancel copying"
msgstr ""
msgid "Button$Cut"
msgstr ""
msgid "Button$Delete marks"
msgstr ""
msgid "Error while queueing recording for cutting!"
msgstr ""
msgid "Delete editing marks for this recording?"
msgstr ""
msgid "Error while deleting editing marks!"
msgstr ""
msgid "Error while changing priority/lifetime!"
msgstr ""
msgid "Error while changing folder/name!"
msgstr ""
msgid "Recording info"
msgstr "Opname info"

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-06-10 12:16+0200\n"
"POT-Creation-Date: 2013-10-10 14:32+0200\n"
"PO-Revision-Date: 2007-08-12 14:17+0200\n"
"Last-Translator: Truls Slevigen <truls@slevigen.no>\n"
"Language-Team: Norwegian Nynorsk <vdr@linuxtv.org>\n"
@ -724,6 +724,67 @@ msgstr ""
msgid "CAM not responding!"
msgstr ""
msgid "Edit path"
msgstr ""
msgid "This folder is currently in use - no changes are possible!"
msgstr ""
msgid "Folder"
msgstr ""
#, c-format
msgid "Move entire folder containing %d recordings?"
msgstr ""
msgid "Error while moving folder!"
msgstr ""
msgid "Edit recording"
msgstr ""
msgid "This recording is currently in use - no changes are possible!"
msgstr ""
msgid "Button$Stop cutting"
msgstr ""
msgid "Button$Cancel cutting"
msgstr ""
msgid "Button$Stop moving"
msgstr ""
msgid "Button$Cancel moving"
msgstr ""
msgid "Button$Stop copying"
msgstr ""
msgid "Button$Cancel copying"
msgstr ""
msgid "Button$Cut"
msgstr ""
msgid "Button$Delete marks"
msgstr ""
msgid "Error while queueing recording for cutting!"
msgstr ""
msgid "Delete editing marks for this recording?"
msgstr ""
msgid "Error while deleting editing marks!"
msgstr ""
msgid "Error while changing priority/lifetime!"
msgstr ""
msgid "Error while changing folder/name!"
msgstr ""
msgid "Recording info"
msgstr ""

View File

@ -9,7 +9,7 @@ msgid ""
msgstr ""
"Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-06-10 12:16+0200\n"
"POT-Creation-Date: 2013-10-10 14:32+0200\n"
"PO-Revision-Date: 2008-03-09 12:59+0100\n"
"Last-Translator: Marek Nazarko <mnazarko@gmail.com>\n"
"Language-Team: Polish <vdr@linuxtv.org>\n"
@ -725,6 +725,67 @@ msgstr "Prosz
msgid "CAM not responding!"
msgstr "CAM nie reaguje!"
msgid "Edit path"
msgstr ""
msgid "This folder is currently in use - no changes are possible!"
msgstr ""
msgid "Folder"
msgstr ""
#, c-format
msgid "Move entire folder containing %d recordings?"
msgstr ""
msgid "Error while moving folder!"
msgstr ""
msgid "Edit recording"
msgstr ""
msgid "This recording is currently in use - no changes are possible!"
msgstr ""
msgid "Button$Stop cutting"
msgstr ""
msgid "Button$Cancel cutting"
msgstr ""
msgid "Button$Stop moving"
msgstr ""
msgid "Button$Cancel moving"
msgstr ""
msgid "Button$Stop copying"
msgstr ""
msgid "Button$Cancel copying"
msgstr ""
msgid "Button$Cut"
msgstr ""
msgid "Button$Delete marks"
msgstr ""
msgid "Error while queueing recording for cutting!"
msgstr ""
msgid "Delete editing marks for this recording?"
msgstr ""
msgid "Error while deleting editing marks!"
msgstr ""
msgid "Error while changing priority/lifetime!"
msgstr ""
msgid "Error while changing folder/name!"
msgstr ""
msgid "Recording info"
msgstr "Informacje o nagraniu"

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-06-10 12:16+0200\n"
"POT-Creation-Date: 2013-10-10 14:32+0200\n"
"PO-Revision-Date: 2010-03-28 22:49+0100\n"
"Last-Translator: Cris Silva <hudokkow@gmail.com>\n"
"Language-Team: Portuguese <vdr@linuxtv.org>\n"
@ -724,6 +724,67 @@ msgstr "Por favor introduza %d d
msgid "CAM not responding!"
msgstr "A CAM não responde!"
msgid "Edit path"
msgstr ""
msgid "This folder is currently in use - no changes are possible!"
msgstr ""
msgid "Folder"
msgstr ""
#, c-format
msgid "Move entire folder containing %d recordings?"
msgstr ""
msgid "Error while moving folder!"
msgstr ""
msgid "Edit recording"
msgstr ""
msgid "This recording is currently in use - no changes are possible!"
msgstr ""
msgid "Button$Stop cutting"
msgstr ""
msgid "Button$Cancel cutting"
msgstr ""
msgid "Button$Stop moving"
msgstr ""
msgid "Button$Cancel moving"
msgstr ""
msgid "Button$Stop copying"
msgstr ""
msgid "Button$Cancel copying"
msgstr ""
msgid "Button$Cut"
msgstr ""
msgid "Button$Delete marks"
msgstr ""
msgid "Error while queueing recording for cutting!"
msgstr ""
msgid "Delete editing marks for this recording?"
msgstr ""
msgid "Error while deleting editing marks!"
msgstr ""
msgid "Error while changing priority/lifetime!"
msgstr ""
msgid "Error while changing folder/name!"
msgstr ""
msgid "Recording info"
msgstr "Informação da gravação"

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-06-10 12:16+0200\n"
"POT-Creation-Date: 2013-10-10 14:32+0200\n"
"PO-Revision-Date: 2013-02-09 23:01+0100\n"
"Last-Translator: Lucian Muresan <lucianm@users.sorceforge.net>\n"
"Language-Team: Romanian <vdr@linuxtv.org>\n"
@ -725,6 +725,67 @@ msgstr "Vă rog introduceţi %d cifre!"
msgid "CAM not responding!"
msgstr "CAM-ul nu reacţionează!"
msgid "Edit path"
msgstr ""
msgid "This folder is currently in use - no changes are possible!"
msgstr ""
msgid "Folder"
msgstr ""
#, c-format
msgid "Move entire folder containing %d recordings?"
msgstr ""
msgid "Error while moving folder!"
msgstr ""
msgid "Edit recording"
msgstr ""
msgid "This recording is currently in use - no changes are possible!"
msgstr ""
msgid "Button$Stop cutting"
msgstr ""
msgid "Button$Cancel cutting"
msgstr ""
msgid "Button$Stop moving"
msgstr ""
msgid "Button$Cancel moving"
msgstr ""
msgid "Button$Stop copying"
msgstr ""
msgid "Button$Cancel copying"
msgstr ""
msgid "Button$Cut"
msgstr ""
msgid "Button$Delete marks"
msgstr ""
msgid "Error while queueing recording for cutting!"
msgstr ""
msgid "Delete editing marks for this recording?"
msgstr ""
msgid "Error while deleting editing marks!"
msgstr ""
msgid "Error while changing priority/lifetime!"
msgstr ""
msgid "Error while changing folder/name!"
msgstr ""
msgid "Recording info"
msgstr "Detaliile înregistrării"

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-06-10 12:16+0200\n"
"POT-Creation-Date: 2013-10-10 14:32+0200\n"
"PO-Revision-Date: 2013-03-10 17:13+0100\n"
"Last-Translator: Oleg Roitburd <oroitburd@gmail.com>\n"
"Language-Team: Russian <vdr@linuxtv.org>\n"
@ -724,6 +724,67 @@ msgstr "
msgid "CAM not responding!"
msgstr "CAM ÝÕ ÞâÒÕçÐÕâ"
msgid "Edit path"
msgstr ""
msgid "This folder is currently in use - no changes are possible!"
msgstr ""
msgid "Folder"
msgstr ""
#, c-format
msgid "Move entire folder containing %d recordings?"
msgstr ""
msgid "Error while moving folder!"
msgstr ""
msgid "Edit recording"
msgstr ""
msgid "This recording is currently in use - no changes are possible!"
msgstr ""
msgid "Button$Stop cutting"
msgstr ""
msgid "Button$Cancel cutting"
msgstr ""
msgid "Button$Stop moving"
msgstr ""
msgid "Button$Cancel moving"
msgstr ""
msgid "Button$Stop copying"
msgstr ""
msgid "Button$Cancel copying"
msgstr ""
msgid "Button$Cut"
msgstr ""
msgid "Button$Delete marks"
msgstr ""
msgid "Error while queueing recording for cutting!"
msgstr ""
msgid "Delete editing marks for this recording?"
msgstr ""
msgid "Error while deleting editing marks!"
msgstr ""
msgid "Error while changing priority/lifetime!"
msgstr ""
msgid "Error while changing folder/name!"
msgstr ""
msgid "Recording info"
msgstr "¸ÝäÞ Þ ×ÐßØáØ"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-06-10 12:16+0200\n"
"POT-Creation-Date: 2013-10-10 14:32+0200\n"
"PO-Revision-Date: 2013-03-04 21:24+0100\n"
"Last-Translator: Milan Hrala <hrala.milan@gmail.com>\n"
"Language-Team: Slovak <vdr@linuxtv.org>\n"
@ -723,6 +723,67 @@ msgstr "Pros
msgid "CAM not responding!"
msgstr "CAM neodpovedá!"
msgid "Edit path"
msgstr ""
msgid "This folder is currently in use - no changes are possible!"
msgstr ""
msgid "Folder"
msgstr ""
#, c-format
msgid "Move entire folder containing %d recordings?"
msgstr ""
msgid "Error while moving folder!"
msgstr ""
msgid "Edit recording"
msgstr ""
msgid "This recording is currently in use - no changes are possible!"
msgstr ""
msgid "Button$Stop cutting"
msgstr ""
msgid "Button$Cancel cutting"
msgstr ""
msgid "Button$Stop moving"
msgstr ""
msgid "Button$Cancel moving"
msgstr ""
msgid "Button$Stop copying"
msgstr ""
msgid "Button$Cancel copying"
msgstr ""
msgid "Button$Cut"
msgstr ""
msgid "Button$Delete marks"
msgstr ""
msgid "Error while queueing recording for cutting!"
msgstr ""
msgid "Delete editing marks for this recording?"
msgstr ""
msgid "Error while deleting editing marks!"
msgstr ""
msgid "Error while changing priority/lifetime!"
msgstr ""
msgid "Error while changing folder/name!"
msgstr ""
msgid "Recording info"
msgstr "Podrobnosti nahrávky"

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-06-10 12:16+0200\n"
"POT-Creation-Date: 2013-10-10 14:32+0200\n"
"PO-Revision-Date: 2013-03-04 12:46+0100\n"
"Last-Translator: Matjaz Thaler <matjaz.thaler@guest.arnes.si>\n"
"Language-Team: Slovenian <vdr@linuxtv.org>\n"
@ -724,6 +724,67 @@ msgstr "Prosim vnesite %d
msgid "CAM not responding!"
msgstr "CAM se ne odziva!"
msgid "Edit path"
msgstr ""
msgid "This folder is currently in use - no changes are possible!"
msgstr ""
msgid "Folder"
msgstr ""
#, c-format
msgid "Move entire folder containing %d recordings?"
msgstr ""
msgid "Error while moving folder!"
msgstr ""
msgid "Edit recording"
msgstr ""
msgid "This recording is currently in use - no changes are possible!"
msgstr ""
msgid "Button$Stop cutting"
msgstr ""
msgid "Button$Cancel cutting"
msgstr ""
msgid "Button$Stop moving"
msgstr ""
msgid "Button$Cancel moving"
msgstr ""
msgid "Button$Stop copying"
msgstr ""
msgid "Button$Cancel copying"
msgstr ""
msgid "Button$Cut"
msgstr ""
msgid "Button$Delete marks"
msgstr ""
msgid "Error while queueing recording for cutting!"
msgstr ""
msgid "Delete editing marks for this recording?"
msgstr ""
msgid "Error while deleting editing marks!"
msgstr ""
msgid "Error while changing priority/lifetime!"
msgstr ""
msgid "Error while changing folder/name!"
msgstr ""
msgid "Recording info"
msgstr "Podatki o snemanju"

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-06-10 12:16+0200\n"
"POT-Creation-Date: 2013-10-10 14:32+0200\n"
"PO-Revision-Date: 2013-03-16 15:05+0100\n"
"Last-Translator: Zoran Turalija <zoran.turalija@gmail.com>\n"
"Language-Team: Serbian <vdr@linuxtv.org>\n"
@ -724,6 +724,67 @@ msgstr "Molimo unesite %d brojeve!"
msgid "CAM not responding!"
msgstr "CAM ne reaguje!"
msgid "Edit path"
msgstr ""
msgid "This folder is currently in use - no changes are possible!"
msgstr ""
msgid "Folder"
msgstr ""
#, c-format
msgid "Move entire folder containing %d recordings?"
msgstr ""
msgid "Error while moving folder!"
msgstr ""
msgid "Edit recording"
msgstr ""
msgid "This recording is currently in use - no changes are possible!"
msgstr ""
msgid "Button$Stop cutting"
msgstr ""
msgid "Button$Cancel cutting"
msgstr ""
msgid "Button$Stop moving"
msgstr ""
msgid "Button$Cancel moving"
msgstr ""
msgid "Button$Stop copying"
msgstr ""
msgid "Button$Cancel copying"
msgstr ""
msgid "Button$Cut"
msgstr ""
msgid "Button$Delete marks"
msgstr ""
msgid "Error while queueing recording for cutting!"
msgstr ""
msgid "Delete editing marks for this recording?"
msgstr ""
msgid "Error while deleting editing marks!"
msgstr ""
msgid "Error while changing priority/lifetime!"
msgstr ""
msgid "Error while changing folder/name!"
msgstr ""
msgid "Recording info"
msgstr "Detalji snimanja"

View File

@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-06-10 12:16+0200\n"
"POT-Creation-Date: 2013-10-10 14:32+0200\n"
"PO-Revision-Date: 2013-02-18 17:04+0100\n"
"Last-Translator: Richard Lithvall <r-vdr@boomer.se>\n"
"Language-Team: Swedish <vdr@linuxtv.org>\n"
@ -727,6 +727,67 @@ msgstr "Mata in %d siffror!"
msgid "CAM not responding!"
msgstr "CAM svarar inte!"
msgid "Edit path"
msgstr ""
msgid "This folder is currently in use - no changes are possible!"
msgstr ""
msgid "Folder"
msgstr ""
#, c-format
msgid "Move entire folder containing %d recordings?"
msgstr ""
msgid "Error while moving folder!"
msgstr ""
msgid "Edit recording"
msgstr ""
msgid "This recording is currently in use - no changes are possible!"
msgstr ""
msgid "Button$Stop cutting"
msgstr ""
msgid "Button$Cancel cutting"
msgstr ""
msgid "Button$Stop moving"
msgstr ""
msgid "Button$Cancel moving"
msgstr ""
msgid "Button$Stop copying"
msgstr ""
msgid "Button$Cancel copying"
msgstr ""
msgid "Button$Cut"
msgstr ""
msgid "Button$Delete marks"
msgstr ""
msgid "Error while queueing recording for cutting!"
msgstr ""
msgid "Delete editing marks for this recording?"
msgstr ""
msgid "Error while deleting editing marks!"
msgstr ""
msgid "Error while changing priority/lifetime!"
msgstr ""
msgid "Error while changing folder/name!"
msgstr ""
msgid "Recording info"
msgstr "Inspelningsinformation"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-06-10 12:16+0200\n"
"POT-Creation-Date: 2013-10-10 14:32+0200\n"
"PO-Revision-Date: 2008-02-28 00:33+0100\n"
"Last-Translator: Oktay Yolgeçen <oktay_73@yahoo.de>\n"
"Language-Team: Turkish <vdr@linuxtv.org>\n"
@ -723,6 +723,67 @@ msgstr "L
msgid "CAM not responding!"
msgstr "CAM yanýt vermiyor!"
msgid "Edit path"
msgstr ""
msgid "This folder is currently in use - no changes are possible!"
msgstr ""
msgid "Folder"
msgstr ""
#, c-format
msgid "Move entire folder containing %d recordings?"
msgstr ""
msgid "Error while moving folder!"
msgstr ""
msgid "Edit recording"
msgstr ""
msgid "This recording is currently in use - no changes are possible!"
msgstr ""
msgid "Button$Stop cutting"
msgstr ""
msgid "Button$Cancel cutting"
msgstr ""
msgid "Button$Stop moving"
msgstr ""
msgid "Button$Cancel moving"
msgstr ""
msgid "Button$Stop copying"
msgstr ""
msgid "Button$Cancel copying"
msgstr ""
msgid "Button$Cut"
msgstr ""
msgid "Button$Delete marks"
msgstr ""
msgid "Error while queueing recording for cutting!"
msgstr ""
msgid "Delete editing marks for this recording?"
msgstr ""
msgid "Error while deleting editing marks!"
msgstr ""
msgid "Error while changing priority/lifetime!"
msgstr ""
msgid "Error while changing folder/name!"
msgstr ""
msgid "Recording info"
msgstr "Kayýt bilgisi"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-06-10 12:16+0200\n"
"POT-Creation-Date: 2013-10-10 14:32+0200\n"
"PO-Revision-Date: 2013-02-09 16:00+0100\n"
"Last-Translator: Yarema aka Knedlyk <yupadmin@gmail.com>\n"
"Language-Team: Ukrainian <vdr@linuxtv.org>\n"
@ -724,6 +724,67 @@ msgstr "Введіть %d цифри!"
msgid "CAM not responding!"
msgstr "CAM не відповідає!"
msgid "Edit path"
msgstr ""
msgid "This folder is currently in use - no changes are possible!"
msgstr ""
msgid "Folder"
msgstr ""
#, c-format
msgid "Move entire folder containing %d recordings?"
msgstr ""
msgid "Error while moving folder!"
msgstr ""
msgid "Edit recording"
msgstr ""
msgid "This recording is currently in use - no changes are possible!"
msgstr ""
msgid "Button$Stop cutting"
msgstr ""
msgid "Button$Cancel cutting"
msgstr ""
msgid "Button$Stop moving"
msgstr ""
msgid "Button$Cancel moving"
msgstr ""
msgid "Button$Stop copying"
msgstr ""
msgid "Button$Cancel copying"
msgstr ""
msgid "Button$Cut"
msgstr ""
msgid "Button$Delete marks"
msgstr ""
msgid "Error while queueing recording for cutting!"
msgstr ""
msgid "Delete editing marks for this recording?"
msgstr ""
msgid "Error while deleting editing marks!"
msgstr ""
msgid "Error while changing priority/lifetime!"
msgstr ""
msgid "Error while changing folder/name!"
msgstr ""
msgid "Recording info"
msgstr "Про запис"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-06-10 12:16+0200\n"
"POT-Creation-Date: 2013-10-10 14:32+0200\n"
"PO-Revision-Date: 2013-03-04 14:52+0800\n"
"Last-Translator: NFVDR <nfvdr@live.com>\n"
"Language-Team: Chinese (simplified) <nfvdr@live.com>\n"
@ -725,6 +725,67 @@ msgstr "请输入 %d 数字!"
msgid "CAM not responding!"
msgstr "CAM 没有响应!"
msgid "Edit path"
msgstr ""
msgid "This folder is currently in use - no changes are possible!"
msgstr ""
msgid "Folder"
msgstr ""
#, c-format
msgid "Move entire folder containing %d recordings?"
msgstr ""
msgid "Error while moving folder!"
msgstr ""
msgid "Edit recording"
msgstr ""
msgid "This recording is currently in use - no changes are possible!"
msgstr ""
msgid "Button$Stop cutting"
msgstr ""
msgid "Button$Cancel cutting"
msgstr ""
msgid "Button$Stop moving"
msgstr ""
msgid "Button$Cancel moving"
msgstr ""
msgid "Button$Stop copying"
msgstr ""
msgid "Button$Cancel copying"
msgstr ""
msgid "Button$Cut"
msgstr ""
msgid "Button$Delete marks"
msgstr ""
msgid "Error while queueing recording for cutting!"
msgstr ""
msgid "Delete editing marks for this recording?"
msgstr ""
msgid "Error while deleting editing marks!"
msgstr ""
msgid "Error while changing priority/lifetime!"
msgstr ""
msgid "Error while changing folder/name!"
msgstr ""
msgid "Recording info"
msgstr "录像信息"

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: recording.c 3.3 2013/09/11 08:28:27 kls Exp $
* $Id: recording.c 3.4 2013/10/09 11:53:37 kls Exp $
*/
#include "recording.h"
@ -20,8 +20,10 @@
#include <sys/stat.h>
#include <unistd.h>
#include "channels.h"
#include "cutter.h"
#include "i18n.h"
#include "interface.h"
#include "menu.h"
#include "remux.h"
#include "ringbuffer.h"
#include "skins.h"
@ -422,6 +424,13 @@ void cRecordingInfo::SetFramesPerSecond(double FramesPerSecond)
framesPerSecond = FramesPerSecond;
}
void cRecordingInfo::SetFileName(const char *FileName)
{
bool IsPesRecording = fileName && endswith(fileName, ".vdr");
free(fileName);
fileName = strdup(cString::sprintf("%s%s", FileName, IsPesRecording ? INFOFILESUFFIX ".vdr" : INFOFILESUFFIX));
}
bool cRecordingInfo::Read(FILE *f)
{
if (ownEvent) {
@ -769,7 +778,7 @@ cRecording::cRecording(cTimer *Timer, const cEvent *Event)
else if (Timer->IsSingleEvent() || !Setup.UseSubtitle)
name = strdup(Timer->File());
else
name = strdup(cString::sprintf("%s~%s", Timer->File(), Subtitle));
name = strdup(cString::sprintf("%s%c%s", Timer->File(), FOLDERDELIMCHAR, Subtitle));
// substitute characters that would cause problems in file names:
strreplace(name, '\n', ' ');
start = Timer->StartTime();
@ -963,8 +972,9 @@ char *cRecording::SortName(void) const
void cRecording::ClearSortName(void)
{
DELETENULL(sortBufferName);
DELETENULL(sortBufferTime);
free(sortBufferName);
free(sortBufferTime);
sortBufferName = sortBufferTime = NULL;
}
int cRecording::GetResume(void) const
@ -982,6 +992,28 @@ int cRecording::Compare(const cListObject &ListObject) const
return strcasecmp(SortName(), r->SortName());
}
bool cRecording::IsInPath(const char *Path)
{
if (isempty(Path))
return true;
int l = strlen(Path);
return strncmp(Path, name, l) == 0 && (name[l] == FOLDERDELIMCHAR);
}
cString cRecording::Folder(void) const
{
if (char *s = strrchr(name, FOLDERDELIMCHAR))
return cString(name, s);
return "";
}
cString cRecording::BaseName(void) const
{
if (char *s = strrchr(name, FOLDERDELIMCHAR))
return cString(s + 1);
return name;
}
const char *cRecording::FileName(void) const
{
if (!fileName) {
@ -1097,6 +1129,22 @@ bool cRecording::IsOnVideoDirectoryFileSystem(void) const
return isOnVideoDirectoryFileSystem;
}
bool cRecording::HasMarks(void)
{
return access(cMarks::MarksFileName(this), F_OK) == 0;
}
bool cRecording::DeleteMarks(void)
{
if (remove(cMarks::MarksFileName(this)) < 0) {
if (errno != ENOENT) {
LOG_ERROR_STR(fileName);
return false;
}
}
return true;
}
void cRecording::ReadInfo(void)
{
info->Read();
@ -1105,13 +1153,13 @@ void cRecording::ReadInfo(void)
framesPerSecond = info->framesPerSecond;
}
bool cRecording::WriteInfo(void)
bool cRecording::WriteInfo(const char *OtherFileName)
{
cString InfoFileName = cString::sprintf("%s%s", fileName, isPesRecording ? INFOFILESUFFIX ".vdr" : INFOFILESUFFIX);
FILE *f = fopen(InfoFileName, "w");
if (f) {
cString InfoFileName = cString::sprintf("%s%s", OtherFileName ? OtherFileName : FileName(), isPesRecording ? INFOFILESUFFIX ".vdr" : INFOFILESUFFIX);
cSafeFile f(InfoFileName);
if (f.Open()) {
info->Write(f);
fclose(f);
f.Close();
}
else
LOG_ERROR_STR(*InfoFileName);
@ -1125,6 +1173,58 @@ void cRecording::SetStartTime(time_t Start)
fileName = NULL;
}
bool cRecording::ChangePriorityLifetime(int NewPriority, int NewLifetime)
{
if (NewPriority != Priority() || NewLifetime != Lifetime()) {
dsyslog("changing priority/lifetime of '%s' to %d/%d", Name(), NewPriority, NewLifetime);
if (IsPesRecording()) {
cString OldFileName = FileName();
priority = NewPriority;
lifetime = NewLifetime;
free(fileName);
fileName = NULL;
cString NewFileName = FileName();
if (!cVideoDirectory::RenameVideoFile(OldFileName, NewFileName))
return false;
info->SetFileName(NewFileName);
}
else {
priority = info->priority = NewPriority;
lifetime = info->lifetime = NewLifetime;
if (!WriteInfo())
return false;
}
Recordings.ChangeState();
Recordings.TouchUpdate();
}
return true;
}
bool cRecording::ChangeName(const char *NewName)
{
if (strcmp(NewName, Name())) {
dsyslog("changing name of '%s' to '%s'", Name(), NewName);
cString OldName = Name();
cString OldFileName = FileName();
free(fileName);
fileName = NULL;
free(name);
name = strdup(NewName);
cString NewFileName = FileName();
if (!(MakeDirs(NewFileName, true) && cVideoDirectory::MoveVideoFile(OldFileName, NewFileName))) {
free(name);
name = strdup(OldName);
free(fileName);
fileName = strdup(OldFileName);
return false;
}
ClearSortName();
Recordings.ChangeState();
Recordings.TouchUpdate();
}
return true;
}
bool cRecording::Delete(void)
{
bool result = true;
@ -1188,6 +1288,17 @@ bool cRecording::Undelete(void)
return result;
}
int cRecording::IsInUse(void) const
{
int Use = ruNone;
if (cRecordControls::GetRecordControl(FileName()))
Use |= ruTimer;
if (cReplayControl::NowReplaying() && strcmp(cReplayControl::NowReplaying(), FileName()) == 0)
Use |= ruReplay;
Use |= RecordingsHandler.GetUsage(FileName());
return Use;
}
void cRecording::ResetResume(void) const
{
resume = RESUME_NOT_INITIALIZED;
@ -1426,6 +1537,46 @@ double cRecordings::MBperMinute(void)
return (size && length) ? double(size) * 60 / length : -1;
}
int cRecordings::PathIsInUse(const char *Path)
{
LOCK_THREAD;
int Use = ruNone;
for (cRecording *recording = First(); recording; recording = Next(recording)) {
if (recording->IsInPath(Path))
Use |= recording->IsInUse();
}
return Use;
}
int cRecordings::GetNumRecordingsInPath(const char *Path)
{
LOCK_THREAD;
int n = 0;
for (cRecording *recording = First(); recording; recording = Next(recording)) {
if (recording->IsInPath(Path))
n++;
}
return n;
}
bool cRecordings::MoveRecordings(const char *OldPath, const char *NewPath)
{
if (OldPath && NewPath && strcmp(OldPath, NewPath)) {
LOCK_THREAD;
dsyslog("moving '%s' to '%s'", OldPath, NewPath);
for (cRecording *recording = First(); recording; recording = Next(recording)) {
if (recording->IsInPath(OldPath)) {
const char *p = recording->Name() + strlen(OldPath);
cString NewName = cString::sprintf("%s%s", NewPath, p);
if (!recording->ChangeName(NewName))
return false;
ChangeState();
}
}
}
return true;
}
void cRecordings::ResetResume(const char *ResumeFileName)
{
LOCK_THREAD;
@ -1443,6 +1594,356 @@ void cRecordings::ClearSortNames(void)
recording->ClearSortName();
}
// --- cDirCopier ------------------------------------------------------------
class cDirCopier : public cThread {
private:
cString dirNameSrc;
cString dirNameDst;
bool error;
bool suspensionLogged;
bool Throttled(void);
virtual void Action(void);
public:
cDirCopier(const char *DirNameSrc, const char *DirNameDst);
virtual ~cDirCopier();
void Stop(void);
bool Error(void) { return error; }
};
cDirCopier::cDirCopier(const char *DirNameSrc, const char *DirNameDst)
:cThread("file copier", true)
{
dirNameSrc = DirNameSrc;
dirNameDst = DirNameDst;
error = false;
suspensionLogged = false;
}
cDirCopier::~cDirCopier()
{
Stop();
}
bool cDirCopier::Throttled(void)
{
if (cIoThrottle::Engaged()) {
if (!suspensionLogged) {
dsyslog("suspending copy thread");
suspensionLogged = true;
}
return true;
}
else if (suspensionLogged) {
dsyslog("resuming copy thread");
suspensionLogged = false;
}
return false;
}
void cDirCopier::Action(void)
{
if (DirectoryOk(dirNameDst, true)) {
cReadDir d(dirNameSrc);
if (d.Ok()) {
dsyslog("copying directory '%s' to '%s'", *dirNameSrc, *dirNameDst);
dirent *e = NULL;
cString FileNameSrc;
cString FileNameDst;
int From = -1;
int To = -1;
size_t BufferSize = BUFSIZ;
while (Running()) {
// Suspend cutting if we have severe throughput problems:
if (Throttled()) {
cCondWait::SleepMs(100);
continue;
}
// Copy all files in the source directory to the destination directory:
if (e) {
// We're currently copying a file:
uchar Buffer[BufferSize];
size_t Read = safe_read(From, Buffer, sizeof(Buffer));
if (Read > 0) {
size_t Written = safe_write(To, Buffer, Read);
if (Written != Read) {
esyslog("ERROR: can't write to destination file '%s': %m", *FileNameDst);
break;
}
}
else if (Read == 0) { // EOF on From
e = NULL; // triggers switch to next entry
if (fsync(To) < 0) {
esyslog("ERROR: can't sync destination file '%s': %m", *FileNameDst);
break;
}
if (close(From) < 0) {
esyslog("ERROR: can't close source file '%s': %m", *FileNameSrc);
break;
}
if (close(To) < 0) {
esyslog("ERROR: can't close destination file '%s': %m", *FileNameDst);
break;
}
// Plausibility check:
off_t FileSizeSrc = FileSize(FileNameSrc);
off_t FileSizeDst = FileSize(FileNameDst);
if (FileSizeSrc != FileSizeDst) {
esyslog("ERROR: file size discrepancy: %lld != %lld", FileSizeSrc, FileSizeDst);
break;
}
}
else {
esyslog("ERROR: can't read from source file '%s': %m", *FileNameSrc);
break;
}
}
else if ((e = d.Next()) != NULL) {
// We're switching to the next directory entry:
FileNameSrc = AddDirectory(dirNameSrc, e->d_name);
FileNameDst = AddDirectory(dirNameDst, e->d_name);
struct stat st;
if (stat(FileNameSrc, &st) < 0) {
esyslog("ERROR: can't access source file '%s': %m", *FileNameSrc);
break;
}
if (!(S_ISREG(st.st_mode) || S_ISLNK(st.st_mode))) {
esyslog("ERROR: source file '%s' is neither a regular file nor a symbolic link", *FileNameSrc);
break;
}
dsyslog("copying file '%s' to '%s'", *FileNameSrc, *FileNameDst);
BufferSize = max(size_t(st.st_blksize * 10), size_t(BUFSIZ));
if (access(FileNameDst, F_OK) == 0) {
esyslog("ERROR: destination file '%s' already exists", *FileNameDst);
break;
}
if ((From = open(FileNameSrc, O_RDONLY)) < 0) {
esyslog("ERROR: can't open source file '%s': %m", *FileNameSrc);
break;
}
if ((To = open(FileNameDst, O_WRONLY | O_CREAT | O_EXCL, DEFFILEMODE)) < 0) {
esyslog("ERROR: can't open destination file '%s': %m", *FileNameDst);
close(From);
break;
}
}
else {
// We're done:
dsyslog("done copying directory '%s' to '%s'", *dirNameSrc, *dirNameDst);
return;
}
}
close(From); // just to be absolutely sure
close(To);
esyslog("ERROR: copying directory '%s' to '%s' ended prematurely", *dirNameSrc, *dirNameDst);
}
else
esyslog("ERROR: can't open '%s'", *dirNameSrc);
}
else
esyslog("ERROR: can't access '%s'", *dirNameDst);
error = true;
}
void cDirCopier::Stop(void)
{
Cancel(3);
if (error) {
cVideoDirectory::RemoveVideoFile(dirNameDst);
Recordings.DelByName(dirNameDst);
}
}
// --- cRecordingsHandlerEntry -----------------------------------------------
class cRecordingsHandlerEntry : public cListObject {
private:
int usage;
cString fileNameSrc;
cString fileNameDst;
cCutter *cutter;
cDirCopier *copier;
void ClearPending(void) { usage &= ~ruPending; }
public:
cRecordingsHandlerEntry(int Usage, const char *FileNameSrc, const char *FileNameDst);
~cRecordingsHandlerEntry();
int Usage(const char *FileName = NULL) const;
const char *FileNameSrc(void) const { return fileNameSrc; }
const char *FileNameDst(void) const { return fileNameDst; }
bool Active(bool &Error);
};
cRecordingsHandlerEntry::cRecordingsHandlerEntry(int Usage, const char *FileNameSrc, const char *FileNameDst)
{
usage = Usage;
fileNameSrc = FileNameSrc;
fileNameDst = FileNameDst;
cutter = NULL;
copier = NULL;
}
cRecordingsHandlerEntry::~cRecordingsHandlerEntry()
{
delete cutter;
delete copier;
}
int cRecordingsHandlerEntry::Usage(const char *FileName) const
{
int u = usage;
if (FileName && *FileName) {
if (strcmp(FileName, fileNameSrc) == 0)
u |= ruSrc;
else if (strcmp(FileName, fileNameDst) == 0)
u |= ruDst;
}
return u;
}
bool cRecordingsHandlerEntry::Active(bool &Error)
{
bool CopierFinishedOk = false;
// First test whether there is an ongoing operation:
if (cutter) {
if (cutter->Active())
return true;
Error |= cutter->Error();
delete cutter;
cutter = NULL;
}
else if (copier) {
if (copier->Active())
return true;
Error |= copier->Error();
CopierFinishedOk = !copier->Error();
delete copier;
copier = NULL;
}
// Now check if there is something to start:
if ((Usage() & ruPending) != 0) {
if ((Usage() & ruCut) != 0) {
cutter = new cCutter(FileNameSrc());
cutter->Start();
}
else if ((Usage() & (ruMove | ruCopy)) != 0) {
copier = new cDirCopier(FileNameSrc(), FileNameDst());
copier->Start();
}
ClearPending();
return true;
}
else {
if (CopierFinishedOk && (Usage() & ruMove) != 0) {
cRecording Recording(FileNameSrc());
Recording.Delete();
Recordings.ChangeState();
Recordings.TouchUpdate();
}
}
return false;
}
// --- cRecordingsHandler ----------------------------------------------------
cRecordingsHandler RecordingsHandler;
cRecordingsHandler::cRecordingsHandler(void)
{
finished = true;
error = false;
}
cRecordingsHandler::~cRecordingsHandler()
{
}
cRecordingsHandlerEntry *cRecordingsHandler::Get(const char *FileName)
{
if (FileName && *FileName) {
for (cRecordingsHandlerEntry *r = operations.First(); r; r = operations.Next(r)) {
if (strcmp(FileName, r->FileNameSrc()) == 0 || strcmp(FileName, r->FileNameDst()) == 0)
return r;
}
}
return NULL;
}
bool cRecordingsHandler::Add(int Usage, const char *FileNameSrc, const char *FileNameDst)
{
dsyslog("recordings handler add %d '%s' '%s'", Usage, FileNameSrc, FileNameDst);
cMutexLock MutexLock(&mutex);
if (Usage == ruCut || Usage == ruMove || Usage == ruCopy) {
if (FileNameSrc && *FileNameSrc) {
if (Usage == ruCut || FileNameDst && *FileNameDst) {
cString fnd;
if (Usage == ruCut && !FileNameDst)
FileNameDst = fnd = cCutter::EditedFileName(FileNameSrc);
if (!Get(FileNameSrc) && !Get(FileNameDst)) {
Usage |= ruPending;
operations.Add(new cRecordingsHandlerEntry(Usage, FileNameSrc, FileNameDst));
finished = false;
Active(); // start it right away if possible
return true;
}
else
esyslog("ERROR: file name already present in recordings handler add %d '%s' '%s'", Usage, FileNameSrc, FileNameDst);
}
else
esyslog("ERROR: missing dst file name in recordings handler add %d '%s' '%s'", Usage, FileNameSrc, FileNameDst);
}
else
esyslog("ERROR: missing src file name in recordings handler add %d '%s' '%s'", Usage, FileNameSrc, FileNameDst);
}
else
esyslog("ERROR: invalid usage in recordings handler add %d '%s' '%s'", Usage, FileNameSrc, FileNameDst);
return false;
}
void cRecordingsHandler::Del(const char *FileName)
{
cMutexLock MutexLock(&mutex);
if (cRecordingsHandlerEntry *r = Get(FileName))
operations.Del(r);
}
void cRecordingsHandler::DelAll(void)
{
cMutexLock MutexLock(&mutex);
operations.Clear();
}
int cRecordingsHandler::GetUsage(const char *FileName)
{
cMutexLock MutexLock(&mutex);
if (cRecordingsHandlerEntry *r = Get(FileName))
return r->Usage(FileName);
return ruNone;
}
bool cRecordingsHandler::Active(void)
{
cMutexLock MutexLock(&mutex);
while (cRecordingsHandlerEntry *r = operations.First()) {
if (r->Active(error))
return true;
else
operations.Del(r);
}
return false;
}
bool cRecordingsHandler::Finished(bool &Error)
{
cMutexLock MutexLock(&mutex);
if (!finished && operations.Count() == 0) {
finished = true;
Error = error;
error = false;
return true;
}
return false;
}
// --- cMark -----------------------------------------------------------------
double MarkFramesPerSecond = DEFAULTFRAMESPERSECOND;
@ -1485,6 +1986,11 @@ bool cMark::Save(FILE *f)
// --- cMarks ----------------------------------------------------------------
cString cMarks::MarksFileName(const cRecording *Recording)
{
return AddDirectory(Recording->FileName(), Recording->IsPesRecording() ? MARKSFILESUFFIX ".vdr" : MARKSFILESUFFIX);
}
bool cMarks::Load(const char *RecordingFileName, double FramesPerSecond, bool IsPesRecording)
{
recordingFileName = RecordingFileName;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: recording.h 2.46 2013/03/04 14:01:23 kls Exp $
* $Id: recording.h 3.1 2013/10/10 12:08:15 kls Exp $
*/
#ifndef __RECORDING_H
@ -25,6 +25,21 @@ extern int DirectoryNameMax;
extern bool DirectoryEncoding;
extern int InstanceId;
enum eRecordingUsage {
ruNone = 0x0000, // the recording is currently unused
ruTimer = 0x0001, // the recording is currently written to by a timer
ruReplay = 0x0002, // the recording is being replayed
// mutually exclusive:
ruCut = 0x0004, // the recording is being cut
ruMove = 0x0008, // the recording is being moved
ruCopy = 0x0010, // the recording is being copied
// mutually exclusive:
ruSrc = 0x0020, // the recording is the source of a cut, move or copy process
ruDst = 0x0040, // the recording is the destination of a cut, move or copy process
//
ruPending = 0x0080, // the recording is pending a cut, move or copy process
};
void RemoveDeletedRecordings(void);
void AssertFreeDiskSpace(int Priority = 0, bool Force = false);
///< The special Priority value -1 means that we shall get rid of any
@ -73,6 +88,7 @@ public:
const char *Aux(void) const { return aux; }
double FramesPerSecond(void) const { return framesPerSecond; }
void SetFramesPerSecond(double FramesPerSecond);
void SetFileName(const char *FileName);
bool Write(FILE *f, const char *Prefix = "") const;
bool Read(void);
bool Write(void) const;
@ -114,8 +130,21 @@ public:
int Lifetime(void) const { return lifetime; }
time_t Deleted(void) const { return deleted; }
virtual int Compare(const cListObject &ListObject) const;
bool IsInPath(const char *Path);
///< Returns true if this recording is stored anywhere under the given Path.
///< If Path is NULL or an empty string, the entire video directory is checked.
cString Folder(void) const;
///< Returns the name of the folder this recording is stored in (without the
///< video directory). For use in menus etc.
cString BaseName(void) const;
///< Returns the base name of this recording (without the
///< video directory and folder). For use in menus etc.
const char *Name(void) const { return name; }
///< Returns the full name of the recording (without the video directory.
///< For use in menus etc.
const char *FileName(void) const;
///< Returns the full path name to the recording directory, including the
///< video directory and the actual '*.rec'. For disk file access use.
const char *Title(char Delimiter = ' ', bool NewIndicator = false, int Level = -1) const;
const cRecordingInfo *Info(void) const { return info; }
const char *PrefixFileName(char Prefix);
@ -134,8 +163,17 @@ public:
bool IsEdited(void) const;
bool IsPesRecording(void) const { return isPesRecording; }
bool IsOnVideoDirectoryFileSystem(void) const;
bool HasMarks(void);
///< Returns true if this recording has any editing marks.
bool DeleteMarks(void);
///< Deletes the editing marks from this recording (if any).
///< Returns true if the operation was successful. If there is no marks file
///< for this recording, it also returns true.
void ReadInfo(void);
bool WriteInfo(void);
bool WriteInfo(const char *OtherFileName = NULL);
///< Writes in info file of this recording. If OtherFileName is given, the info
///< file will be written under that recording file name instead of this
///< recording's file name.
void SetStartTime(time_t Start);
///< Sets the start time of this recording to the given value.
///< If a filename has already been set for this recording, it will be
@ -144,6 +182,17 @@ public:
///< Use this function with care - it does not check whether a recording with
///< this new name already exists, and if there is one, results may be
///< unexpected!
bool ChangePriorityLifetime(int NewPriority, int NewLifetime);
///< Changes the priority and lifetime of this recording to the given values.
///< If the new values are the same as the old ones, nothing happens.
///< Returns false in case of error.
bool ChangeName(const char *NewName);
///< Changes the name of this recording to the given value. NewName is in the
///< same format as the one returned by Name(), i.e. without the video directory
///< and the actual '*.rec' part, and using FOLDERDELIMCHAR as the directory
///< delimiter.
///< If the new name is the same as the old one, nothing happens.
///< Returns false in case of error.
bool Delete(void);
///< Changes the file name so that it will no longer be visible in the "Recordings" menu
///< Returns false in case of error
@ -154,6 +203,14 @@ public:
///< 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
int IsInUse(void) const;
///< Checks whether this recording is currently in use and therefore shall not
///< be tampered with. Returns 0 (ruNone) if the recording is not in use.
///< The return value may consist of several or'd eRecordingUsage flags. If the
///< caller is just interested in whether the recording is in use or not, the
///< return value can be used like a boolean value.
///< A recording may be in use for several reasons (like being recorded and replayed,
///< as in time-shift).
};
class cRecordings : public cList<cRecording>, public cThread {
@ -197,11 +254,76 @@ public:
double MBperMinute(void);
///< Returns the average data rate (in MB/min) of all recordings, or -1 if
///< this value is unknown.
int PathIsInUse(const char *Path);
///< Checks whether any recording in the given Path is currently in use and therefore
///< the whole Path shall not be tampered with. Returns 0 (ruNone) if no recording
///< is in use.
///< See cRecording::IsInUse() for details about the possible non-zero return values.
///< If several recordings in the Path are currently in use, the return value will
///< be the combination of all individual recordings' flags.
///< If Path is NULL or an empty string, the entire video directory is checked.
int GetNumRecordingsInPath(const char *Path);
///< Returns the total number of recordings in the given Path, including all
///< sub-folders of Path.
///< If Path is NULL or an empty string, the entire video directory is checked.
bool MoveRecordings(const char *OldPath, const char *NewPath);
///< Moves all recordings in OldPath to NewPath.
///< Returns true if all recordings were successfully moved.
///< As soon as the operation fails for one recording, the whole
///< action is aborted and false will be returned. Any recordings that
///< have been successfully moved thus far will keep their new name.
///< If OldPath and NewPath are on different file systems, the recordings
///< will be moved in a background process and this function returns true
///< if all recordings have been successfully added to the RecordingsHandler.
};
extern cRecordings Recordings;
extern cRecordings DeletedRecordings;
class cRecordingsHandlerEntry;
class cRecordingsHandler {
private:
cMutex mutex;
cList<cRecordingsHandlerEntry> operations;
bool finished;
bool error;
cRecordingsHandlerEntry *Get(const char *FileName);
public:
cRecordingsHandler(void);
~cRecordingsHandler();
bool Add(int Usage, const char *FileNameSrc, const char *FileNameDst = NULL);
///< Adds the given FileNameSrc to the recordings handler for (later)
///< processing. Usage can be either ruCut, ruMove or ruCopy. FileNameDst
///< is only applicable for ruMove and ruCopy.
///< At any given time there can be only one operation for any FileNameSrc
///< or FileNameDst in the list. An attempt to add a file name twice will
///< result in an error.
///< Returns true if the operation was successfully added to the list.
void Del(const char *FileName);
///< Deletes the given FileName from the list of operations.
///< If an action is already in progress, it will be terminated.
///< FileName can be either the FileNameSrc or FileNameDst (if applicable)
///< that was given when the operation was added with Add().
void DelAll(void);
///< Deletes/terminates all operations.
int GetUsage(const char *FileName);
///< Returns the usage type for the given FileName.
bool Active(void);
///< Checks whether there is currently any operation running and starts
///> the next one form the list if the previous one has finished.
///< This function must be called regularly to trigger switching to the
///< next operation in the list.
///< Returns true if there are any operations in the list.
bool Finished(bool &Error);
///< Returns true if all operations in the list have been finished.
///< If there have been any errors, Errors will be set to true.
///< This function will only return true once if the list of operations
///< has actually become empty since the last call.
};
extern cRecordingsHandler RecordingsHandler;
#define DEFAULTFRAMESPERSECOND 25.0
class cMark : public cListObject {
@ -232,6 +354,9 @@ private:
time_t lastFileTime;
time_t lastChange;
public:
static cString MarksFileName(const cRecording *Recording);
///< Returns the marks file name for the given Recording (regardless whether such
///< a file actually exists).
bool Load(const char *RecordingFileName, double FramesPerSecond = DEFAULTFRAMESPERSECOND, bool IsPesRecording = false);
bool Update(void);
bool Save(void);

View File

@ -6,7 +6,7 @@
*
* Original version written by Udo Richter <udo_richter@gmx.de>.
*
* $Id: shutdown.c 2.1 2013/02/18 10:33:26 kls Exp $
* $Id: shutdown.c 3.1 2013/10/02 09:02:01 kls Exp $
*/
#include "shutdown.h"
@ -16,11 +16,11 @@
#include <sys/wait.h>
#include "channels.h"
#include "config.h"
#include "cutter.h"
#include "i18n.h"
#include "interface.h"
#include "menu.h"
#include "plugin.h"
#include "recording.h"
#include "timers.h"
#include "tools.h"
@ -167,7 +167,7 @@ bool cShutdownHandler::ConfirmShutdown(bool Interactive)
Skins.Message(mtError, tr("Can't shutdown - option '-s' not given!"));
return false;
}
if (cCutter::Active()) {
if (RecordingsHandler.Active()) {
if (!Interactive || !Interface->Confirm(tr("Editing - shut down anyway?")))
return false;
}
@ -210,7 +210,7 @@ bool cShutdownHandler::ConfirmShutdown(bool Interactive)
bool cShutdownHandler::ConfirmRestart(bool Interactive)
{
if (cCutter::Active()) {
if (RecordingsHandler.Active()) {
if (!Interactive || !Interface->Confirm(tr("Editing - restart anyway?")))
return false;
}

94
svdrp.c
View File

@ -10,7 +10,7 @@
* and interact with the Video Disk Recorder - or write a full featured
* graphical interface that sits on top of an SVDRP connection.
*
* $Id: svdrp.c 3.1 2013/09/10 13:21:38 kls Exp $
* $Id: svdrp.c 3.2 2013/10/10 12:18:12 kls Exp $
*/
#include "svdrp.h"
@ -28,7 +28,6 @@
#include <unistd.h>
#include "channels.h"
#include "config.h"
#include "cutter.h"
#include "device.h"
#include "eitscan.h"
#include "keys.h"
@ -305,6 +304,11 @@ const char *HelpPages[] = {
"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 the recording with the given number. Before a recording can be\n"
" renamed, an LSTR command must have been executed in order to retrieve\n"
" the recording numbers. The numbers don't change during subsequent RENR\n"
" commands.n",
"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.",
@ -659,27 +663,38 @@ void cSVDRP::CmdDELC(const char *Option)
Reply(501, "Missing channel number");
}
static cString RecordingInUseMessage(int Reason, const char *RecordingId, cRecording *Recording)
{
cRecordControl *rc;
if ((Reason & ruTimer) != 0 && (rc = cRecordControls::GetRecordControl(Recording->FileName())) != NULL)
return cString::sprintf("Recording \"%s\" is in use by timer %d", RecordingId, rc->Timer()->Index() + 1);
else if ((Reason & ruReplay) != 0)
return cString::sprintf("Recording \"%s\" is being replayed", RecordingId);
else if ((Reason & ruCut) != 0)
return cString::sprintf("Recording \"%s\" is being edited", RecordingId);
else if ((Reason & (ruMove | ruCopy)) != 0)
return cString::sprintf("Recording \"%s\" is being copied/moved", RecordingId);
else if (Reason)
return cString::sprintf("Recording \"%s\" is in use", RecordingId);
return NULL;
}
void cSVDRP::CmdDELR(const char *Option)
{
if (*Option) {
if (isnumber(Option)) {
cRecording *recording = recordings.Get(strtol(Option, NULL, 10) - 1);
if (recording) {
cRecordControl *rc = cRecordControls::GetRecordControl(recording->FileName());
if (!rc) {
if (!cCutter::Active(recording->FileName())) {
if (recording->Delete()) {
Reply(250, "Recording \"%s\" deleted", Option);
Recordings.DelByName(recording->FileName());
}
else
Reply(554, "Error while deleting recording!");
if (int RecordingInUse = recording->IsInUse())
Reply(550, RecordingInUseMessage(RecordingInUse, Option, recording));
else {
if (recording->Delete()) {
Reply(250, "Recording \"%s\" deleted", Option);
Recordings.DelByName(recording->FileName());
}
else
Reply(550, "Recording \"%s\" is being edited", Option);
Reply(554, "Error while deleting recording!");
}
else
Reply(550, "Recording \"%s\" is in use by timer %d", Option, rc->Timer()->Index() + 1);
}
else
Reply(550, "Recording \"%s\" not found%s", Option, recordings.Count() ? "" : " (use LSTR before deleting)");
@ -728,14 +743,10 @@ void cSVDRP::CmdEDIT(const char *Option)
if (recording) {
cMarks Marks;
if (Marks.Load(recording->FileName(), recording->FramesPerSecond(), recording->IsPesRecording()) && Marks.Count()) {
if (!cCutter::Active()) {
if (cCutter::Start(recording->FileName()))
Reply(250, "Editing recording \"%s\" [%s]", Option, recording->Title());
else
Reply(554, "Can't start editing process");
}
if (RecordingsHandler.Add(ruCut, recording->FileName()))
Reply(250, "Editing recording \"%s\" [%s]", Option, recording->Title());
else
Reply(554, "Editing process already active");
Reply(554, "Can't start editing process");
}
else
Reply(554, "No editing marks defined");
@ -1539,6 +1550,46 @@ void cSVDRP::CmdREMO(const char *Option)
Reply(250, "Remote control is %s", cRemote::Enabled() ? "enabled" : "disabled");
}
void cSVDRP::CmdRENR(const char *Option)
{
if (*Option) {
char *opt = strdup(Option);
char *num = skipspace(opt);
char *option = num;
while (*option && !isspace(*option))
option++;
char c = *option;
*option = 0;
if (isnumber(num)) {
cRecording *recording = recordings.Get(strtol(num, NULL, 10) - 1);
if (recording) {
if (int RecordingInUse = recording->IsInUse())
Reply(550, RecordingInUseMessage(RecordingInUse, Option, recording));
else {
if (c)
option = skipspace(++option);
if (*option) {
cString oldName = recording->Name();
if (recording->ChangeName(option))
Reply(250, "Recording \"%s\" renamed to \"%s\"", *oldName, recording->Name());
else
Reply(554, "Error while renaming recording \"%s\" to \"%s\"!", *oldName, option);
}
else
Reply(501, "Missing new recording name");
}
}
else
Reply(550, "Recording \"%s\" not found%s", num, recordings.Count() ? "" : " (use LSTR before renaming)");
}
else
Reply(501, "Error in recording number \"%s\"", num);
free(opt);
}
else
Reply(501, "Missing recording number");
}
void cSVDRP::CmdSCAN(const char *Option)
{
EITScanner.ForceScan();
@ -1666,6 +1717,7 @@ void cSVDRP::Execute(char *Cmd)
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("UPDR")) CmdUPDR(s);

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: svdrp.h 2.3 2012/04/26 10:30:06 kls Exp $
* $Id: svdrp.h 3.1 2013/09/14 13:24:50 kls Exp $
*/
#ifndef __SVDRP_H
@ -78,6 +78,7 @@ private:
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);

71
tools.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: tools.c 3.1 2013/05/23 10:10:00 kls Exp $
* $Id: tools.c 3.2 2013/09/22 13:19:19 kls Exp $
*/
#include "tools.h"
@ -173,6 +173,31 @@ char *strreplace(char *s, const char *s1, const char *s2)
return s;
}
const char *strchrn(const char *s, char c, size_t n)
{
if (n == 0)
return s;
if (s) {
for ( ; *s; s++) {
if (*s == c && --n == 0)
return s;
}
}
return NULL;
}
int strcountchr(const char *s, char c)
{
int n = 0;
if (s && c) {
for ( ; *s; s++) {
if (*s == c)
n++;
}
}
return n;
}
char *stripspace(char *s)
{
if (s && *s) {
@ -202,6 +227,30 @@ char *compactspace(char *s)
return s;
}
char *compactchars(char *s, char c)
{
if (s && *s && c) {
char *t = s;
char *p = s;
int n = 0;
while (*p) {
if (*p != c) {
*t++ = *p;
n = 0;
}
else if (t != s && n == 0) {
*t++ = *p;
n++;
}
p++;
}
if (n)
t--; // the last character was c
*t = 0;
}
return s;
}
cString strescape(const char *s, const char *chars)
{
char *buffer;
@ -970,6 +1019,20 @@ cString::cString(const char *S, bool TakePointer)
s = TakePointer ? (char *)S : S ? strdup(S) : NULL;
}
cString::cString(const char *S, const char *To)
{
if (!S)
s = NULL;
else if (!To)
s = strdup(S);
else {
int l = To - S;
s = MALLOC(char, l + 1);
strncpy(s, S, l);
s[l] = 0;
}
}
cString::cString(const cString &String)
{
s = String.s ? strdup(String.s) : NULL;
@ -1008,6 +1071,12 @@ cString &cString::Truncate(int Index)
return *this;
}
cString &cString::CompactChars(char c)
{
compactchars(s, c);
return *this;
}
cString cString::sprintf(const char *fmt, ...)
{
va_list ap;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: tools.h 3.2 2013/08/23 10:32:51 kls Exp $
* $Id: tools.h 3.3 2013/09/22 13:30:14 kls Exp $
*/
#ifndef __TOOLS_H
@ -170,6 +170,7 @@ private:
char *s;
public:
cString(const char *S = NULL, bool TakePointer = false);
cString(const char *S, const char *To); ///< Copies S up to To (exclusive). To must be a valid pointer into S. If To is NULL, everything is copied.
cString(const cString &String);
virtual ~cString();
operator const void * () const { return s; } // to catch cases where operator*() should be used
@ -178,6 +179,7 @@ public:
cString &operator=(const cString &String);
cString &operator=(const char *String);
cString &Truncate(int Index); ///< Truncate the string at the given Index (if Index is < 0 it is counted from the end of the string).
cString &CompactChars(char c); ///< Compact any sequence of characters 'c' to a single character, and strip all of them from the beginning and end of this string.
static cString sprintf(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
static cString vsprintf(const char *fmt, va_list &ap);
};
@ -193,6 +195,8 @@ char *strcpyrealloc(char *dest, const char *src);
char *strn0cpy(char *dest, const char *src, size_t n);
char *strreplace(char *s, char c1, char c2);
char *strreplace(char *s, const char *s1, const char *s2); ///< re-allocates 's' and deletes the original string if necessary!
const char *strchrn(const char *s, char c, size_t n); ///< returns a pointer to the n'th occurrence (counting from 1) of c in s, or NULL if no such character was found. If n is 0, s is returned.
int strcountchr(const char *s, char c); ///< returns the number of occurrences of 'c' in 's'.
inline char *skipspace(const char *s)
{
if ((uchar)*s > ' ') // most strings don't have any leading space, so handle this case as fast as possible
@ -203,6 +207,7 @@ inline char *skipspace(const char *s)
}
char *stripspace(char *s);
char *compactspace(char *s);
char *compactchars(char *s, char c); ///< removes all occurrences of 'c' from the beginning an end of 's' and replaces sequences of multiple 'c's with a single 'c'.
cString strescape(const char *s, const char *chars);
bool startswith(const char *s, const char *p);
bool endswith(const char *s, const char *p);

14
vdr.c
View File

@ -22,7 +22,7 @@
*
* The project's page is at http://www.tvdr.de
*
* $Id: vdr.c 3.2 2013/09/10 13:58:34 kls Exp $
* $Id: vdr.c 3.3 2013/10/10 12:25:03 kls Exp $
*/
#include <getopt.h>
@ -1320,8 +1320,9 @@ int main(int argc, char *argv[])
if (!Menu) {
if (!InhibitEpgScan)
EITScanner.Process();
if (!cCutter::Active() && cCutter::Ended()) {
if (cCutter::Error())
bool Error = false;
if (RecordingsHandler.Finished(Error)) {
if (Error)
Skins.Message(mtError, tr("Editing process failed!"));
else
Skins.Message(mtInfo, tr("Editing process finished"));
@ -1341,7 +1342,10 @@ int main(int argc, char *argv[])
ShutdownHandler.countdown.Cancel();
}
if ((Now - LastInteract) > ACTIVITYTIMEOUT && !cRecordControls::Active() && !cCutter::Active() && !Interface->HasSVDRPConnection() && (Now - cRemote::LastActivity()) > ACTIVITYTIMEOUT) {
// Keep the recordings handler alive:
RecordingsHandler.Active();
if ((Now - LastInteract) > ACTIVITYTIMEOUT && !cRecordControls::Active() && !RecordingsHandler.Active() && !Interface->HasSVDRPConnection() && (Now - cRemote::LastActivity()) > ACTIVITYTIMEOUT) {
// Handle housekeeping tasks
// Shutdown:
@ -1390,7 +1394,7 @@ Exit:
PluginManager.StopPlugins();
cRecordControls::Shutdown();
cCutter::Stop();
RecordingsHandler.DelAll();
delete Menu;
cControl::Shutdown();
delete Interface;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: videodir.c 3.2 2013/09/11 12:20:37 kls Exp $
* $Id: videodir.c 3.3 2013/10/08 13:26:41 kls Exp $
*/
#include "videodir.h"
@ -79,6 +79,7 @@ bool cVideoDirectory::Register(const char *FileName)
bool cVideoDirectory::Rename(const char *OldName, const char *NewName)
{
dsyslog("renaming '%s' to '%s'", OldName, NewName);
if (rename(OldName, NewName) == -1) {
LOG_ERROR_STR(NewName);
return false;
@ -88,10 +89,15 @@ bool cVideoDirectory::Rename(const char *OldName, const char *NewName)
bool cVideoDirectory::Move(const char *FromName, const char *ToName)
{
if (rename(FromName, ToName) == -1) {
LOG_ERROR_STR(ToName);
return false;
dsyslog("moving '%s' to '%s'", FromName, ToName);
if (EntriesOnSameFileSystem(FromName, ToName)) {
if (rename(FromName, ToName) == -1) {
LOG_ERROR_STR(ToName);
return false;
}
}
else
return RecordingsHandler.Add(ruMove, FromName, ToName);
return true;
}