summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Prochnow <nordlicht@martins-kabuff.de>2007-10-08 20:36:03 +0200
committerAndreas Mair <andreas@vdr-developer.org>2007-10-08 20:36:03 +0200
commit57e0533f20b14e208e41e56f80fd15b3d18f90f1 (patch)
tree2e75d86377b4fbc29c9fd76fabd2a5e291a9f204
parent8adfaaf81b104b8e981026da593e40f9d780c251 (diff)
downloadvdr-plugin-extrecmenu-57e0533f20b14e208e41e56f80fd15b3d18f90f1.tar.gz
vdr-plugin-extrecmenu-57e0533f20b14e208e41e56f80fd15b3d18f90f1.tar.bz2
Version 1.0v1.0
- it is now possible to cancel a moving-between-filesystems-process - applied changes for MainMenuHooksPatch - added MainMenuHooksPatch to contrib/-dir; removed old one, which is now obsolete - free disk space is shown for the filesystem of the current directory (can be switched of in plugin's setup menu) - added support for hidding PIN-protected recordings in co-work with PIN-Plugin - added queue for moving recordings between filesystems - added cutter queue - added #ifdef's to switch of font patching for vdr >= 1.5.3 - added setup option to switch of font patching
-rw-r--r--HISTORY22
-rw-r--r--Makefile7
-rw-r--r--README50
-rw-r--r--contrib/MainMenuHooks-v1_0.patch155
-rw-r--r--contrib/vdr-1.3.43-extrecmenu.diff31
-rw-r--r--extrecmenu.c149
-rw-r--r--i18n.c253
-rw-r--r--mymenueditrecording.c126
-rw-r--r--mymenurecordings.c944
-rw-r--r--mymenurecordings.h13
-rw-r--r--mymenusetup.c115
-rw-r--r--mymenusetup.h4
-rw-r--r--myreplaycontrol.c58
-rw-r--r--myreplaycontrol.h9
-rw-r--r--patchfont.c84
-rw-r--r--tools.c727
-rw-r--r--tools.h95
17 files changed, 1856 insertions, 986 deletions
diff --git a/HISTORY b/HISTORY
index c2bbeaf..715ef78 100644
--- a/HISTORY
+++ b/HISTORY
@@ -1,11 +1,24 @@
VDR Plugin 'extrecmenu' Revision History
----------------------------------------
-2007-01-??: Version 0.13
+2007-10-07: Version 1.0
+- it is now possible to cancel a moving-between-filesystems-process
+- applied changes for MainMenuHooksPatch
+- added MainMenuHooksPatch to contrib/-dir; removed old one, which is now
+ obsolete
+- free disk space is shown for the filesystem of the current directory (can be
+ switched of in plugin's setup menu)
+- added support for hidding PIN-protected recordings in co-work with PIN-Plugin
+- added queue for moving recordings between filesystems
+- added cutter queue
+- added #ifdef's to switch of font patching for vdr >= 1.5.3
+- added setup option to switch of font patching
+
+2007-02-04: Version 0.13
- added two setup option to adjust the plugin behaviour to whose of VDR's
recording menu (jumping to last replayed recording, call plugin after
replay ends)
-- only editing of cutting recordings is prevented now
+- only editing of recordings, that are cutted, is prevented now
- moving recordings between filesystems is now possible; includes:
* check for enough free disk space on target filesystem
* switch to limit bandwith (a.t.m. 2MBytes/sec)
@@ -23,7 +36,7 @@ VDR Plugin 'extrecmenu' Revision History
2006-12-31: Version 0.12c
- dvd id for archive dvd would be first read out when the corresponding entry
is selected; this should prevent delays while opening the plugin
-- because of this the setup option "show dvd id" is removed
+- removed the setup option "show dvd id" because of this
2006-12-04: Version 0.12b
- type of sorting (ascending/descending) selectable at the setup menu of the
@@ -188,4 +201,5 @@ VDR Plugin 'extrecmenu' Revision History
- details (date and time) for recordings are shown now
2006-03-09: Version 0.1
-- Initial revision.
+- Initial revision
+
diff --git a/Makefile b/Makefile
index b48bb38..cf2413a 100644
--- a/Makefile
+++ b/Makefile
@@ -1,9 +1,10 @@
+###############################################################################
#
-# Makefile for a Video Disk Recorder plugin
-#
-
# uncomment if you use the pin-plugin and want to protect your recordings
#WITHPINPLUGIN=1
+#
+###############################################################################
+
# The official name of this plugin.
# This name will be used in the '-P...' option of VDR to load the plugin.
diff --git a/README b/README
index 0997126..8fb52a5 100644
--- a/README
+++ b/README
@@ -3,14 +3,13 @@ This is a "plugin" for the Video Disk Recorder (VDR).
Written by: Martin Prochnow (nordlicht@martins-kabuff.de)
Project's homepage: http://martins-kabuff.de/extrecmenu_en.html
-See the file COPYING for license information. See top of *.c for additional
-copyright information.
+See the file COPYING for license information.
I want to thank to following contributors:
-- Mike Constabel for the skript dvdarchive.sh
-- Rolf Ahrenberg for the finnish translation
-- Patrice Staudt for the frensh translation
-- Vladimír Bárta for the czech translation
+- Mike Constabel <mike@constabel.net> for the skript dvdarchive.sh
+- Rolf Ahrenberg <rahrenbe@cc.hut.fi> for the finnish translation
+- Patrice Staudt <staudt@engsystem.net> for the frensh translation
+- Vladimír Bárta <vladimir.barta@k2atmitec.cz> for the czech translation
-------------------------------------------------------------------------------
Description
@@ -20,18 +19,21 @@ recordings menu:
* renaming recordings and directories
* moving recordings and directories, also between different filesystems
-* functionality of the DVDArchiv-patch (see below)
* adjustable display of recording's length, date and size
* directories are always shown on top of the list
* reworked layout using icons for showing the status of list entries
- (directory, new recording, moving recording, cutting recording, dvd archiv
- entry)
-* sorting by name or date, adjustable for each directory
-* ascending/descending sorting
-* extends VDR's '-r'-option commands with 'move' and 'rename'
+ (directory, new recording, moving recording/directory, cutting recording,
+ dvd archiv entry)
* extended recordings info menu, shows name, path, channel, size, lifetime and
priority of the recording
-* protects recordings in co-work with the PIN-plugin
+* free disk space is shown for the filesystem of the current directory
+* sorting by name or date, adjustable for each directory; type of sorting will
+ be stored
+* ascending/descending sorting
+* extends VDR's '-r'-option commands with 'move' and 'rename'
+* functionality of the DVDArchive-patch (see below)
+* protecting recordings in co-work with the PIN-plugin
+* a cutter queue
-------------------------------------------------------------------------------
Installation
@@ -51,11 +53,6 @@ There is a patch for VDR in contrib/ for replacing VDR's recordings menu with
this plugin. You have to set the corresponding option at the setup menu of the
plugin!
-There ist a patched TTF-Font for Enigma containing the dvd and alternative new
-symbols. See this posts at vdr-portal.de:
-http://www.vdr-portal.de/board/thread.php?postid=483800#post483800
-http://www.vdr-portal.de/board/thread.php?postid=483988#post483988
-
-------------------------------------------------------------------------------
Handling
-------------------------------------------------------------------------------
@@ -67,15 +64,23 @@ renaming will be executed.
Moving: Press 'Yellow', then 'Green'. Now you are at the base directory of the
/video-directory-hierarchy. 'Ok' opens sub-directories, with 'Yellow' you can
-create new dirs. With 'Blue' moving to the selected dir will be executed. At
-the moment it is only possible to move one recording or directory to another
-filesystem.
+create new dirs. With 'Blue' moving to the selected dir will be executed.
Details: Select a recording, press 'Yellow', then 'Blue'. In this menu you can
edit the lifetime and priority of the selected recording. Editing the details
of archive dvd entries is not possible, because this would change the name by
which the recording is found on the disc.
+Cutter queue
+-------------------------------------------------------------------------------
+With the build-in cutter queue you don't have to wait until an editing process
+ended before you can start a new one. It only works, if you start the editing
+process from a replay that was started in the plugin.
+
+Canceling of editing or move processes
+-------------------------------------------------------------------------------
+Mark the entry, press 'Yellow'.
+
Sort recordings
-------------------------------------------------------------------------------
All directories are sorted by date by default. To change the sorting, simply
@@ -83,7 +88,7 @@ press '0'. Ascending or descending sorting is selectable at plugin's setup
menu.
-------------------------------------------------------------------------------
-Archiv-DVD-functionality
+DVDArchive-patch functionality
-------------------------------------------------------------------------------
Burn the entire directory, that contains the recording, to a dvd and label it
with an identifier (a number or anything else). At least the *.rec-folder has
@@ -118,3 +123,4 @@ is started to play the video dvd.
Do you like this plugin? Support the developer! Go to the project homepage and
make a donation over the PayPal button.
-------------------------------------------------------------------------------
+
diff --git a/contrib/MainMenuHooks-v1_0.patch b/contrib/MainMenuHooks-v1_0.patch
new file mode 100644
index 0000000..70a72a3
--- /dev/null
+++ b/contrib/MainMenuHooks-v1_0.patch
@@ -0,0 +1,155 @@
+This is a "patch" for the Video Disk Recorder (VDR).
+
+* Authors:
+Tobias Grimm <tobias (dot) grimm (at) e-tobi (dot) net>
+Martin Prochnow <nordlicht (at) martins-kabuff (dot) de>
+Frank Schmirler <vdrdev (at) schmirler (dot) de>
+Christian Wieninger <cwieninger (at) gmx (dot) de>
+
+* Description:
+This patch allows plugins to replace the VDR mainmenus "Schedule",
+"Channels", "Timers" and "Recordings" by a different implementation.
+
+The patch is based on a suggestion of Christian Wieninger back in 2006
+(http://www.linuxtv.org/pipermail/vdr/2006-March/008234.html). It is
+meant to be an interim solution for VDR 1.4 until (maybe) VDR 1.5
+introduces an official API for this purpose.
+
+* Installation
+Change into the VDR source directory, then issue
+ patch -p1 < path/to/MainMenuHooks-v1_0.patch
+and recompile.
+
+* Notes for plugin authors
+The following code sample shows the required plugin code for replacing
+the original Schedule menu:
+
+bool cMyPlugin::Service(const char *Id, void *Data)
+{
+ cOsdMenu **menu = (cOsdMenu**) Data;
+ if (MySetup.replaceSchedule &&
+ strcmp(Id, "MainMenuHooksPatch-v1.0::osSchedule") == 0) {
+ if (menu)
+ *menu = (cOsdMenu*) MainMenuAction();
+ return true;
+ }
+ return false;
+}
+
+A plugin can replace more than one menu at a time. Simply replace the
+call to MainMenuAction() in the sample above by appropriate code.
+
+Note that a plugin *should* offer a setup option which allows the user
+to enable or disable the replacement. "Disabled" would be a reasonable
+default setting. By testing for define MAINMENUHOOKSVERSNUM, a plugin
+can leave the setup option out at compiletime.
+
+In case there is an internal problem when trying to open the replacement
+menu, it is safe to return true even though Data is NULL. However an
+OSD message should indicate the problem to the user.
+
+Feel free to ship this patch along with your plugin. However if you
+think you need to modify the patch, we'd encourage you to contact the
+authors first or at least use a service id which differs in more than
+just the version number.
+
+--- vdr-1.4.5/menu.c.orig 2007-02-07 08:23:49.000000000 +0100
++++ vdr-1.4.5/menu.c 2007-02-20 11:05:34.000000000 +0100
+@@ -2792,15 +2792,30 @@
+
+ // Initial submenus:
+
++ cOsdMenu *menu = NULL;
+ switch (State) {
+- case osSchedule: AddSubMenu(new cMenuSchedule); break;
+- case osChannels: AddSubMenu(new cMenuChannels); break;
+- case osTimers: AddSubMenu(new cMenuTimers); break;
+- case osRecordings: AddSubMenu(new cMenuRecordings(NULL, 0, true)); break;
+- case osSetup: AddSubMenu(new cMenuSetup); break;
+- case osCommands: AddSubMenu(new cMenuCommands(tr("Commands"), &Commands)); break;
++ case osSchedule:
++ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osSchedule", &menu))
++ menu = new cMenuSchedule;
++ break;
++ case osChannels:
++ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osChannels", &menu))
++ menu = new cMenuChannels;
++ break;
++ case osTimers:
++ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osTimers", &menu))
++ menu = new cMenuTimers;
++ break;
++ case osRecordings:
++ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osRecordings", &menu))
++ menu = new cMenuRecordings(NULL, 0, true);
++ break;
++ case osSetup: menu = new cMenuSetup; break;
++ case osCommands: menu = new cMenuCommands(tr("Commands"), &Commands); break;
+ default: break;
+ }
++ if (menu)
++ AddSubMenu(menu);
+ }
+
+ cOsdObject *cMenuMain::PluginOsdObject(void)
+@@ -2927,13 +2942,34 @@
+ eOSState state = cOsdMenu::ProcessKey(Key);
+ HadSubMenu |= HasSubMenu();
+
++ cOsdMenu *menu = NULL;
+ switch (state) {
+- case osSchedule: return AddSubMenu(new cMenuSchedule);
+- case osChannels: return AddSubMenu(new cMenuChannels);
+- case osTimers: return AddSubMenu(new cMenuTimers);
+- case osRecordings: return AddSubMenu(new cMenuRecordings);
+- case osSetup: return AddSubMenu(new cMenuSetup);
+- case osCommands: return AddSubMenu(new cMenuCommands(tr("Commands"), &Commands));
++ case osSchedule:
++ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osSchedule", &menu))
++ menu = new cMenuSchedule;
++ else
++ state = osContinue;
++ break;
++ case osChannels:
++ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osChannels", &menu))
++ menu = new cMenuChannels;
++ else
++ state = osContinue;
++ break;
++ case osTimers:
++ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osTimers", &menu))
++ menu = new cMenuTimers;
++ else
++ state = osContinue;
++ break;
++ case osRecordings:
++ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osRecordings", &menu))
++ menu = new cMenuRecordings;
++ else
++ state = osContinue;
++ break;
++ case osSetup: menu = new cMenuSetup; break;
++ case osCommands: menu = new cMenuCommands(tr("Commands"), &Commands); break;
+ case osStopRecord: if (Interface->Confirm(tr("Stop recording?"))) {
+ cOsdItem *item = Get(Current());
+ if (item) {
+@@ -2985,6 +3021,8 @@
+ default: break;
+ }
+ }
++ if (menu)
++ return AddSubMenu(menu);
+ if (!HasSubMenu() && Update(HadSubMenu))
+ Display();
+ if (Key != kNone) {
+--- vdr-1.4.5/config.h.orig 2007-02-20 11:55:40.000000000 +0100
++++ vdr-1.4.5/config.h 2007-02-20 11:56:43.000000000 +0100
+@@ -35,6 +35,8 @@
+ // plugins to work with newer versions of the core VDR as long as no
+ // VDR header files have changed.
+
++#define MAINMENUHOOKSVERSNUM 1.0
++
+ #define MAXPRIORITY 99
+ #define MAXLIFETIME 99
+
diff --git a/contrib/vdr-1.3.43-extrecmenu.diff b/contrib/vdr-1.3.43-extrecmenu.diff
deleted file mode 100644
index 6e980f0..0000000
--- a/contrib/vdr-1.3.43-extrecmenu.diff
+++ /dev/null
@@ -1,31 +0,0 @@
---- menu.c.org 2006-02-20 16:20:18.000000000 +0100
-+++ menu.c 2006-03-13 14:27:33.000000000 +0100
-@@ -2897,7 +2897,11 @@
- break;
- case osChannels: AddSubMenu(new cMenuChannels); break;
- case osTimers: AddSubMenu(new cMenuTimers); break;
-- case osRecordings: AddSubMenu(new cMenuRecordings(NULL, 0, true)); break;
-+ case osRecordings: {
-+ cPlugin *p = cPluginManager::GetPlugin("extrecmenu");
-+ (p && !p->SetupParse("IsOrgRecMenu", "0")) ? AddSubMenu((cOsdMenu *)p->MainMenuAction()) : AddSubMenu(new cMenuRecordings(NULL, 0, true));
-+ }
-+ break;
- case osSetup: AddSubMenu(new cMenuSetup); break;
- case osCommands: AddSubMenu(new cMenuCommands(tr("Commands"), &Commands)); break;
- default: break;
-@@ -3044,7 +3048,14 @@
- break;
- case osChannels: return AddSubMenu(new cMenuChannels);
- case osTimers: return AddSubMenu(new cMenuTimers);
-- case osRecordings: return AddSubMenu(new cMenuRecordings);
-+ case osRecordings: {
-+ cPlugin *p = cPluginManager::GetPlugin("extrecmenu");
-+ if (p && !p->SetupParse("IsOrgRecMenu", "0"))
-+ return AddSubMenu((cOsdMenu *)p->MainMenuAction());
-+ else
-+ return AddSubMenu(new cMenuRecordings);
-+ }
-+ break;
- case osSetup: return AddSubMenu(new cMenuSetup);
- case osCommands: return AddSubMenu(new cMenuCommands(tr("Commands"), &Commands));
- case osStopRecord: if (Interface->Confirm(tr("Stop recording?"))) {
diff --git a/extrecmenu.c b/extrecmenu.c
index 0b900a8..ebaf3b8 100644
--- a/extrecmenu.c
+++ b/extrecmenu.c
@@ -11,35 +11,33 @@
using namespace std;
-static const char *VERSION = "0.13";
+static const char *VERSION = "1.0";
static const char *DESCRIPTION = "Extended recordings menu";
static const char *MAINMENUENTRY = "ExtRecMenu";
-SortList *mySortList;
-
// --- cPluginExtrecmenu ------------------------------------------------------
class cPluginExtrecmenu:public cPlugin
{
- private:
- public:
- cPluginExtrecmenu(void);
- virtual ~cPluginExtrecmenu();
- virtual const char *Version(void){return VERSION;}
- virtual const char *Description(void){return tr(DESCRIPTION);}
- virtual const char *CommandLineHelp(void);
- virtual bool ProcessArgs(int argc,char *argv[]);
- virtual bool Initialize(void);
- virtual bool Start(void);
- virtual void Stop(void);
- virtual void Housekeeping(void);
- virtual cString Active(void);
- virtual const char *MainMenuEntry(void){return mysetup.HideMainMenuEntry?NULL:MAINMENUENTRY;}
- virtual cOsdObject *MainMenuAction(void);
- virtual cMenuSetupPage *SetupMenu(void);
- virtual bool SetupParse(const char *Name,const char *Value);
- virtual bool Service(const char *Id,void *Data = NULL);
- virtual const char **SVDRPHelpPages(void);
- virtual cString SVDRPCommand(const char *Command,const char *Option,int &ReplyCode);
+ private:
+ public:
+ cPluginExtrecmenu(void);
+ virtual ~cPluginExtrecmenu();
+ virtual const char *Version(void){return VERSION;}
+ virtual const char *Description(void){return tr(DESCRIPTION);}
+ virtual const char *CommandLineHelp(void);
+ virtual bool ProcessArgs(int argc,char *argv[]);
+ virtual bool Initialize(void);
+ virtual bool Start(void);
+ virtual void Stop(void);
+ virtual void Housekeeping(void);
+ virtual cString Active(void);
+ virtual const char *MainMenuEntry(void){return mysetup.HideMainMenuEntry?NULL:MAINMENUENTRY;}
+ virtual cOsdObject *MainMenuAction(void);
+ virtual cMenuSetupPage *SetupMenu(void);
+ virtual bool SetupParse(const char *Name,const char *Value);
+ virtual bool Service(const char *Id,void *Data = NULL);
+ virtual const char **SVDRPHelpPages(void);
+ virtual cString SVDRPCommand(const char *Command,const char *Option,int &ReplyCode);
};
cPluginExtrecmenu::cPluginExtrecmenu(void)
@@ -52,32 +50,35 @@ cPluginExtrecmenu::~cPluginExtrecmenu()
const char *cPluginExtrecmenu::CommandLineHelp(void)
{
- return NULL;
+ return NULL;
}
bool cPluginExtrecmenu::ProcessArgs(int argc,char *argv[])
{
- return true;
+ return true;
}
bool cPluginExtrecmenu::Initialize(void)
{
- RegisterI18n(Phrases);
+ RegisterI18n(Phrases);
- return true;
+ return true;
}
bool cPluginExtrecmenu::Start(void)
{
- mySortList=new SortList;
- mySortList->ReadConfigFile();
+ mySortList=new SortList;
+ mySortList->ReadConfigFile();
+
+ MoveCutterThread=new WorkerThread();
- return true;
+ return true;
}
void cPluginExtrecmenu::Stop(void)
{
- delete mySortList;
+ delete mySortList;
+ delete MoveCutterThread;
}
void cPluginExtrecmenu::Housekeeping(void)
@@ -86,58 +87,71 @@ void cPluginExtrecmenu::Housekeeping(void)
cString cPluginExtrecmenu::Active(void)
{
- if(MoveThread.Active())
- return tr("Move recordings in progress");
- return NULL;
+ return MoveCutterThread->Working();
}
cOsdObject *cPluginExtrecmenu::MainMenuAction(void)
{
- return new myMenuRecordings();
+ return new myMenuRecordings();
}
cMenuSetupPage *cPluginExtrecmenu::SetupMenu(void)
{
- return new myMenuSetup();
+ return new myMenuSetup();
}
bool cPluginExtrecmenu::SetupParse(const char *Name,const char *Value)
{
- if(!strcasecmp(Name,"IsOrgRecMenu"))
- return (mysetup.ReplaceOrgRecMenu==false); // vdr-replace patch
-
- if(!strcasecmp(Name,"ShowRecDate"))
- mysetup.ShowRecDate=atoi(Value);
- else if(!strcasecmp(Name,"ShowRecTime"))
- mysetup.ShowRecTime=atoi(Value);
- else if(!strcasecmp(Name,"ShowRecLength"))
- mysetup.ShowRecLength=atoi(Value);
- else if(!strcasecmp(Name,"HideMainMenuEntry"))
- mysetup.HideMainMenuEntry=atoi(Value);
- else if(!strcasecmp(Name,"ReplaceOrgRecMenu"))
- mysetup.ReplaceOrgRecMenu=atoi(Value);
- else if(!strcasecmp(Name,"PatchNew"))
- mysetup.PatchNew=atoi(Value);
- else if(!strcasecmp(Name,"ShowNewRecs"))
- mysetup.ShowNewRecs=atoi(Value);
- else if(!strcasecmp(Name,"DescendSorting"))
- mysetup.DescendSorting=atoi(Value);
- else if(!strcasecmp(Name,"GoLastReplayed"))
- mysetup.GoLastReplayed=atoi(Value);
- else if(!strcasecmp(Name,"ReturnToPlugin"))
- mysetup.ReturnToPlugin=atoi(Value);
- else if(!strcasecmp(Name,"LimitBandwidth"))
- mysetup.LimitBandwidth=atoi(Value);
- else if(!strcasecmp(Name,"UseVDRsRecInfoMenu"))
- mysetup.UseVDRsRecInfoMenu=atoi(Value);
- else
- return false;
- return true;
+ if(!strcasecmp(Name,"IsOrgRecMenu"))
+ return (mysetup.ReplaceOrgRecMenu==false); // vdr-replace patch
+
+ if(!strcasecmp(Name,"ShowRecDate"))
+ mysetup.ShowRecDate=atoi(Value);
+ else if(!strcasecmp(Name,"ShowRecTime"))
+ mysetup.ShowRecTime=atoi(Value);
+ else if(!strcasecmp(Name,"ShowRecLength"))
+ mysetup.ShowRecLength=atoi(Value);
+ else if(!strcasecmp(Name,"HideMainMenuEntry"))
+ mysetup.HideMainMenuEntry=atoi(Value);
+ else if(!strcasecmp(Name,"ReplaceOrgRecMenu"))
+ mysetup.ReplaceOrgRecMenu=atoi(Value);
+ else if(!strcasecmp(Name,"PatchNew"))
+ mysetup.PatchNew=atoi(Value);
+ else if(!strcasecmp(Name,"ShowNewRecs"))
+ mysetup.ShowNewRecs=atoi(Value);
+ else if(!strcasecmp(Name,"DescendSorting"))
+ mysetup.DescendSorting=atoi(Value);
+ else if(!strcasecmp(Name,"GoLastReplayed"))
+ mysetup.GoLastReplayed=atoi(Value);
+ else if(!strcasecmp(Name,"ReturnToPlugin"))
+ mysetup.ReturnToPlugin=atoi(Value);
+ else if(!strcasecmp(Name,"LimitBandwidth"))
+ mysetup.LimitBandwidth=atoi(Value);
+ else if(!strcasecmp(Name,"UseVDRsRecInfoMenu"))
+ mysetup.UseVDRsRecInfoMenu=atoi(Value);
+ else if(!strcasecmp(Name,"PatchFont"))
+ mysetup.PatchFont=atoi(Value);
+ else if(!strcasecmp(Name,"FileSystemFreeMB"))
+ mysetup.FileSystemFreeMB=atoi(Value);
+ else
+ return false;
+ return true;
}
bool cPluginExtrecmenu::Service(const char *Id,void *Data)
{
- return false;
+ if(!Data)
+ return true;
+
+ cOsdMenu **menu=(cOsdMenu**)Data;
+ if(mysetup.ReplaceOrgRecMenu && strcmp(Id,"MainMenuHooksPatch-v1.0::osRecordings")==0)
+ {
+ if(menu)
+ *menu=(cOsdMenu*)MainMenuAction();
+
+ return true;
+ }
+ return false;
}
const char **cPluginExtrecmenu::SVDRPHelpPages(void)
@@ -151,3 +165,4 @@ cString cPluginExtrecmenu::SVDRPCommand(const char *Command,const char *Option,i
}
VDRPLUGINCREATOR(cPluginExtrecmenu); // Don't touch this!
+
diff --git a/i18n.c b/i18n.c
index 5ae2d35..4d5d39d 100644
--- a/i18n.c
+++ b/i18n.c
@@ -57,7 +57,7 @@ const tI18nPhrase Phrases[] = {
"",
"Retour",
"",
- "",
+ "Takaisin",
"",
"",
"",
@@ -687,28 +687,6 @@ const tI18nPhrase Phrases[] = {
"",
"Modul DVD není nainstalován!",
},
- { "Rename/Move failed!",
- "Umbenennen/Verschieben fehlgeschlagen!",
- "",
- "",
- "",
- "",
- "Renommer/déplacer ŕ échoué!",
- "",
- "Nimeäminen/siirto epäonnistui!",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "Přejmenování/Přesun selhal!",
- },
{ "Invalid filename!",
"Ungültiger Dateiname!",
"",
@@ -797,8 +775,8 @@ const tI18nPhrase Phrases[] = {
"",
"Třídit podle data",
},
- { "Show nr. of new recordings in a directory",
- "Anzahl der neuen Aufz. im Ordner anzeigen",
+ { "Show nr. of new recordings of a directory",
+ "Anzahl der neuen Aufz. eines Ordners anzeigen",
"",
"",
"",
@@ -929,28 +907,6 @@ const tI18nPhrase Phrases[] = {
"",
"Návrat do modulu po ukončení přehrávání",
},
- { "Move recordings already in progress!",
- "Es werden schon Aufzeichnungen verschoben!",
- "",
- "",
- "",
- "",
- "Des enregistrements sont déjŕ en déplacement!",
- "",
- "Tallenteiden siirto on jo käynnissä!",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "Právě probíhá přesouvání nahrávek!",
- },
{ "Move recordings in progress",
"Es werden Aufzeichungen verschoben",
"",
@@ -1001,7 +957,7 @@ const tI18nPhrase Phrases[] = {
"",
"",
"",
- "La partition de déstination est pleine - essayer tout de męme?",
+ "La partition de déstination est pleine - essayer tout de męme?",
"",
"Kohdepartitio täynnä - yritetäänkö silti?",
"",
@@ -1062,7 +1018,14 @@ const tI18nPhrase Phrases[] = {
"Velikost",
},
{ "Use VDR's recording info menu",
- "VDR-Aufz.-Info-Menü benutzen",
+ "VDRs Aufzeichnungs-Info-Menü benutzen",
+ "",
+ "",
+ "",
+ "",
+ "Utiliser le menu info enregistrement de VDR",
+ "",
+ "Käytä alkuperäistä tallenteen tiedot -valikkoa",
"",
"",
"",
@@ -1074,6 +1037,17 @@ const tI18nPhrase Phrases[] = {
"",
"",
"",
+ "Používat info menu nahrávek VDR",
+ },
+ { "Added recording to cutter queue",
+ "Aufzeichnung der Schnitt-Warteschlange hinzugefügt",
+ "",
+ "",
+ "",
+ "",
+ "Enregistrement ajouté ŕ la file d'attente de découpe",
+ "",
+ "Tallenne on lisätty leikkausjonoon",
"",
"",
"",
@@ -1082,6 +1056,187 @@ const tI18nPhrase Phrases[] = {
"",
"",
"",
+ "",
+ "",
+ "",
+ "Nahrávka přidána do střihové fronty",
+ },
+ { "Recording already in cutter queue!",
+ "Aufzeichnung bereits in Schnitt-Warteschlange",
+ "",
+ "",
+ "",
+ "",
+ "L'enregistrement est déjŕ dans la queue d'attente découpe!",
+ "",
+ "Tallenne on jo leikkausjonossa!",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "Nahrávka je již ve střihové frontě!",
+ },
+ { "Cutter queue not empty",
+ "Schnitt-Warteschlange nicht leer",
+ "",
+ "",
+ "",
+ "",
+ "Queue d'attente découpe n'est pas vide",
+ "",
+ "Leikkausjono ei ole tyhjä",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "Střihová fronta není prázdná",
+ },
+ { "Move recordings in progress",
+ "Es werden Aufzeichnungen verschoben",
+ "",
+ "",
+ "",
+ "",
+ "Des enregistrements sont en déplacement",
+ "",
+ "Tallenteiden siirto käynnissä",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "Probíhá přesouvání nahrávek",
+ },
+ { "Cancel moving?",
+ "Verschieben abbrechen?",
+ "",
+ "",
+ "",
+ "",
+ "Interrompre le déplacement?",
+ "",
+ "Peruutetaanko siirto?",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "Přerušit přesouvání?",
+ },
+ { "Patch font",
+ "Font patchen",
+ "",
+ "",
+ "",
+ "",
+ "Patch des police",
+ "",
+ "Käytä paikattua kirjasinta",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "Upravit font",
+ },
+ { "Show free disk space for each file system",
+ "Freien Speicherplatz für jede Partition anzeigen",
+ "",
+ "",
+ "",
+ "",
+ "Afficher la place libre de chaque partition",
+ "",
+ "Näytä vapaa levytila jokaisella tiedostojärjestelmällä",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "Zobrazit volné místo pro každý souborový systém",
+ },
+ { "Can't get filesystem information",
+ "Kann Dateisysteminformationen nicht ermitteln",
+ "",
+ "",
+ "",
+ "",
+ "Impossible de déterminer les informations du systčme de fichiers",
+ "",
+ "Tiedostojärjestelmän tietojen lukeminen epäonnistui",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "Nelze získat informace o souborovém systémy",
+ },
+ { "Rename/Move failed!",
+ "Umbenennen/Verschieben fehlgeschlagen!",
+ "",
+ "",
+ "",
+ "",
+ "Renommer/déplacer ŕ échoué!",
+ "",
+ "Nimeäminen/siirto epäonnistui!",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "Přejmenování/přesun selhal!",
},
{ NULL }
};
+
diff --git a/mymenueditrecording.c b/mymenueditrecording.c
index f9ce9eb..bfac643 100644
--- a/mymenueditrecording.c
+++ b/mymenueditrecording.c
@@ -2,7 +2,7 @@
* See the README file for copyright information and how to reach the author.
*/
-#include <sys/vfs.h>
+#include <sys/statvfs.h>
#include <string>
#include <vdr/videodir.h>
#include <vdr/remote.h>
@@ -14,10 +14,9 @@
using namespace std;
// --- myMenuRenameRecording --------------------------------------------------
-myMenuRenameRecording::myMenuRenameRecording(myMenuRecordings *MenuRecordings,cRecording *Recording,const char *DirBase,const char *DirName):cOsdMenu(tr("Rename"),12)
+myMenuRenameRecording::myMenuRenameRecording(cRecording *Recording,const char *DirBase,const char *DirName):cOsdMenu(tr("Rename"),12)
{
isdir=false;
- menurecordings=MenuRecordings;
recording=Recording;
dirbase=DirBase?ExchangeChars(strdup(DirBase),true):NULL;
dirname=DirName?ExchangeChars(strdup(DirName),true):NULL;
@@ -87,10 +86,7 @@ eOSState myMenuRenameRecording::ProcessKey(eKeys Key)
else
{
if(MoveRename(oldname,newname,isdir?NULL:recording,false))
- {
state=osBack;
- menurecordings->Set(true,isdir?NULL:newname);
- }
else
{
cRemote::Put(kRight);
@@ -208,13 +204,12 @@ myMenuMoveRecordingItem::myMenuMoveRecordingItem(cRecording *Recording,int Level
}
// --- myMenuMoveRecording ----------------------------------------------------
-myMenuMoveRecording::myMenuMoveRecording(myMenuRecordings *MenuRecordings,cRecording *Recording,const char *DirBase,const char *DirName,const char *Base,int Level):cOsdMenu(Base?Base:"")
+myMenuMoveRecording::myMenuMoveRecording(cRecording *Recording,const char *DirBase,const char *DirName,const char *Base,int Level):cOsdMenu(Base?Base:"")
{
dirbase=DirBase?strdup(DirBase):NULL;
dirname=DirName?strdup(DirName):NULL;
strn0cpy(newname,"",sizeof(newname));
recording=Recording;
- menurecordings=MenuRecordings;
base=Base?strdup(Base):NULL;
level=Level;
@@ -234,6 +229,9 @@ void myMenuMoveRecording::Set()
if(level==0)
Add(new myMenuMoveRecordingItem(tr("[base dir]"),0));
+ cThreadLock RecordingsLock(&Recordings);
+ Recordings.Sort();
+
char *lastitemtext=NULL;
myMenuMoveRecordingItem *lastitem=NULL;
for(cRecording *recording=Recordings.First();recording;recording=Recordings.Next(recording))
@@ -279,7 +277,7 @@ eOSState myMenuMoveRecording::Open()
snprintf(buffer,sizeof(buffer),"%s~%s",base,t);
t=buffer;
}
- return AddSubMenu(new myMenuMoveRecording(menurecordings,recording,dirbase,dirname,t,level+1));
+ return AddSubMenu(new myMenuMoveRecording(recording,dirbase,dirname,t,level+1));
}
}
return osContinue;
@@ -307,7 +305,7 @@ eOSState myMenuMoveRecording::MoveRec()
{
if(dirname)
asprintf(&dir,"%s%s%s",base?base:"",base?"~":"",item->Text());
- else
+ else // needed for move recording menu
{
char *p=strrchr(recording->Name(),'~');
asprintf(&dir,"%s%s%s~%s",base?base:"",base?"~":"",item->Text(),p?p+1:recording->Name());
@@ -337,65 +335,91 @@ eOSState myMenuMoveRecording::MoveRec()
asprintf(&newname,"%s%s%s%s",VideoDirectory,dir?"/":"",dir?dir:"",strrchr(dirname?oldname:recording->FileName(),'/'));
- if(!MakeDirs(newname,true))
- Skins.Message(mtError,tr("Creating directories failed!"));
+ // getting existing part of target path
+ string path=newname;
+ string::size_type pos=string::npos;
+ do
+ pos=path.rfind('/',pos)-1;
+ while(access(path.substr(0,pos+1).c_str(),R_OK));
+
+ path=path.substr(0,pos+1);
+
+ struct stat stat1,stat2;
+ stat(oldname,&stat1);
+ stat(path.c_str(),&stat2);
+ // are source and target at the same filesystem?
+ if(stat1.st_dev==stat2.st_dev)
+ {
+ if(MoveRename(oldname,newname,dirname?NULL:recording,true))
+ {
+ clearall=true;
+ state=osBack;
+ }
+ }
else
{
- struct stat stat1,stat2;
- stat(oldname,&stat1);
- stat(newname,&stat2);
- if(stat1.st_dev==stat2.st_dev)
+ struct statvfs fsstat;
+ if(!statvfs(path.c_str(),&fsstat))
{
- if(MoveRename(oldname,newname,dirname?NULL:recording,true))
+ int freemb=int(fsstat.f_bavail/(1024.0*1024.0/fsstat.f_bsize));
+ int recmb=0;
+
+ // moving a single recording
+ if(recording)
{
- clearall=true;
- state=osBack;
- menurecordings->Set(true);
+ recmb=DirSizeMB(recording->FileName());
+ if(freemb-recmb > 0 || Interface->Confirm(tr("Target filesystem filled - try anyway?")))
+ {
+ MoveCutterThread->AddToMoveList(oldname,newname);
+ clearall=true;
+ state=osBack;
+ }
}
- }
- else
- {
- if(MoveThread.Active())
- Skins.Message(mtError,tr("Move recordings already in progress!"));
+ // moving a directory
else
{
- struct statfs fsstat;
- statfs(newname,&fsstat);
- int freemb=int(fsstat.f_bavail/(1024*1024/fsstat.f_bsize));
- int recmb=0;
-
- if(recording)
- recmb=DirSizeMB(recording->FileName());
+ string buf=oldname;
+ buf+="/";
+ if(!buf.compare(0,buf.length(),newname))
+ Skins.Message(mtError,tr("Moving into own sub-directory not allowed!"));
else
{
+ cThreadLock RecordingsLock(&Recordings);
for(cRecording *rec=Recordings.First();rec;rec=Recordings.Next(rec))
{
if(!strncmp(oldname,rec->FileName(),strlen(oldname)))
recmb+=DirSizeMB(rec->FileName());
}
- }
-
- if(freemb-recmb <= 0)
- {
- if(Interface->Confirm(tr("Target filesystem filled - try anyway?")))
+
+ if(freemb-recmb > 0 || Interface->Confirm(tr("Target filesystem filled - try anyway?")))
{
- MoveThread.Start(oldname,newname,dirname?NULL:recording);
+ for(cRecording *rec=Recordings.First();rec;rec=Recordings.Next(rec))
+ {
+ if(!strncmp(oldname,rec->FileName(),strlen(oldname)))
+ {
+ char *buf=ExchangeChars(strdup(oldname+strlen(VideoDirectory)+1),false);
+
+ if(strcmp(rec->Name(),buf))
+ {
+ free(buf);
+ asprintf(&buf,"%s%s",newname,rec->FileName()+strlen(oldname));
+
+ MoveCutterThread->AddToMoveList(rec->FileName(),buf);
+ }
+ free(buf);
+ }
+ }
clearall=true;
state=osBack;
- menurecordings->Set(true);
}
- else
- remove(newname); // remove created directory
- }
- else
- {
- MoveThread.Start(oldname,newname,dirname?NULL:recording);
- clearall=true;
- state=osBack;
- menurecordings->Set(true);
}
}
}
+ else
+ {
+ Skins.Message(mtError,tr("Can't get filesystem information"));
+ esyslog("[extrecmenu] %s",strerror(errno));
+ }
}
free(oldname);
free(newname);
@@ -441,10 +465,9 @@ eOSState myMenuMoveRecording::ProcessKey(eKeys Key)
}
// --- myMenuRecordingDetails -------------------------------------------------
-myMenuRecordingDetails::myMenuRecordingDetails(cRecording *Recording,myMenuRecordings *MenuRecordings):cOsdMenu(tr("Details"),12)
+myMenuRecordingDetails::myMenuRecordingDetails(cRecording *Recording):cOsdMenu(tr("Details"),12)
{
recording=Recording;
- menurecordings=MenuRecordings;
priority=recording->priority;
lifetime=recording->lifetime;
@@ -465,10 +488,7 @@ eOSState myMenuRecordingDetails::ProcessKey(eKeys Key)
sprintf(newname+strlen(newname)-9,"%02d.%02d.rec",priority,lifetime);
if(MoveRename(oldname,newname,recording,false))
- {
state=osBack;
- menurecordings->Set(true,newname);
- }
else
state=osContinue;
diff --git a/mymenurecordings.c b/mymenurecordings.c
index d0cabc1..1a7725d 100644
--- a/mymenurecordings.c
+++ b/mymenurecordings.c
@@ -2,6 +2,7 @@
* See the README file for copyright information and how to reach the author.
*/
+#include <sys/statvfs.h>
#include <string>
#include <sstream>
#include <iomanip>
@@ -21,28 +22,29 @@
using namespace std;
-extern SortList *mySortList;
-
// --- myMenuRecordingInfo ----------------------------------------------------
+// this class is mostly a copy of VDR's cMenuRecording class, I only adjusted
+// the Display()-method
+// ----------------------------------------------------------------------------
class myMenuRecordingInfo:public cOsdMenu
{
- private:
- const cRecording *recording;
- bool withButtons;
- eOSState Play();
- eOSState Rewind();
- public:
- myMenuRecordingInfo(const cRecording *Recording,bool WithButtons = false);
- virtual void Display(void);
- virtual eOSState ProcessKey(eKeys Key);
+ private:
+ const cRecording *recording;
+ bool withButtons;
+ eOSState Play();
+ eOSState Rewind();
+ public:
+ myMenuRecordingInfo(const cRecording *Recording,bool WithButtons = false);
+ virtual void Display(void);
+ virtual eOSState ProcessKey(eKeys Key);
};
myMenuRecordingInfo::myMenuRecordingInfo(const cRecording *Recording, bool WithButtons):cOsdMenu(tr("Recording info"))
{
- recording=Recording;
- withButtons=WithButtons;
- if(withButtons)
- SetHelp(tr("Button$Play"),tr("Button$Rewind"),NULL,tr("Button$Back"));
+ recording=Recording;
+ withButtons=WithButtons;
+ if(withButtons)
+ SetHelp(tr("Button$Play"),tr("Button$Rewind"),NULL,tr("Button$Back"));
}
void myMenuRecordingInfo::Display(void)
@@ -91,43 +93,42 @@ void myMenuRecordingInfo::Display(void)
text << tr("Lifetime") << ": " << recording->lifetime << "\n";
DisplayMenu()->SetText(text.str().c_str(),false);
- cStatus::MsgOsdTextItem(recording->Info()->Description());
}
}
eOSState myMenuRecordingInfo::ProcessKey(eKeys Key)
{
- switch(Key)
- {
- case kUp|k_Repeat:
- case kUp:
- case kDown|k_Repeat:
- case kDown:
- case kLeft|k_Repeat:
- case kLeft:
- case kRight|k_Repeat:
- case kRight: DisplayMenu()->Scroll(NORMALKEY(Key)==kUp||NORMALKEY(Key)==kLeft,NORMALKEY(Key)==kLeft||NORMALKEY(Key)==kRight);
- cStatus::MsgOsdTextItem(NULL, NORMALKEY(Key) == kUp);
- return osContinue;
- default: break;
- }
-
- eOSState state=cOsdMenu::ProcessKey(Key);
- if(state==osUnknown)
- {
switch(Key)
{
- case kRed: if(withButtons)
- Key=kOk; // will play the recording, even if recording commands are defined
- case kGreen: if(!withButtons)
- break;
- cRemote::Put(Key,true);
- case kBlue:
- case kOk: return osBack;
- default: break;
+ case kUp|k_Repeat:
+ case kUp:
+ case kDown|k_Repeat:
+ case kDown:
+ case kLeft|k_Repeat:
+ case kLeft:
+ case kRight|k_Repeat:
+ case kRight: DisplayMenu()->Scroll(NORMALKEY(Key)==kUp||NORMALKEY(Key)==kLeft,NORMALKEY(Key)==kLeft||NORMALKEY(Key)==kRight);
+ cStatus::MsgOsdTextItem(NULL, NORMALKEY(Key) == kUp);
+ return osContinue;
+ default: break;
}
- }
- return state;
+
+ eOSState state=cOsdMenu::ProcessKey(Key);
+ if(state==osUnknown)
+ {
+ switch(Key)
+ {
+ case kRed: if(withButtons)
+ Key=kOk;
+ case kGreen: if(!withButtons)
+ break;
+ cRemote::Put(Key,true);
+ case kBlue:
+ case kOk: return osBack;
+ default: break;
+ }
+ }
+ return state;
}
// --- myMenuRecordingsItem ---------------------------------------------------
@@ -135,6 +136,7 @@ myMenuRecordingsItem::myMenuRecordingsItem(cRecording *Recording,int Level)
{
totalentries=newentries=0;
isdvd=false;
+ dirismoving=true;
name=NULL;
filename=Recording->FileName();
@@ -148,7 +150,7 @@ myMenuRecordingsItem::myMenuRecordingsItem(cRecording *Recording,int Level)
}
// create the title of this item
- if(Level<level) // directory entries
+ if(Level<level) // directory entry
{
s=Recording->Name();
const char *p=s;
@@ -171,7 +173,7 @@ myMenuRecordingsItem::myMenuRecordingsItem(cRecording *Recording,int Level)
}
else
{
- if(Level==level) // recording entries
+ if(Level==level) // recording entry
{
string buffer;
stringstream titlebuffer;
@@ -187,17 +189,16 @@ myMenuRecordingsItem::myMenuRecordingsItem(cRecording *Recording,int Level)
}
// marker
- if(MoveThread.IsMoving(filename))
- titlebuffer << char(133); // move in progress
+ if(MoveCutterThread->IsMoving(filename))
+ titlebuffer << char(133);
else if(isdvd)
- titlebuffer << char(129); // dvd-archiv
- else if(cCutter::Active() && myReplayControl::Cut && myReplayControl::Cutted &&
- (!strcmp(filename,myReplayControl::Cut) || !strcmp(filename,myReplayControl::Cutted)))
- titlebuffer << char(132); // cut in progress
- else if(Recording->IsNew() && !mysetup.PatchNew)
- titlebuffer << '*'; // new recording
- else if(!Recording->IsNew() && mysetup.PatchNew)
- titlebuffer << char(128); // alternative to new marker
+ titlebuffer << char(129);
+ else if(MoveCutterThread->IsCutting(filename))
+ titlebuffer << char(132);
+ else if(Recording->IsNew() && (!mysetup.PatchNew || !mysetup.PatchFont))
+ titlebuffer << '*';
+ else if(!Recording->IsNew() && mysetup.PatchNew && mysetup.PatchFont)
+ titlebuffer << char(128);
else titlebuffer << ' ';
titlebuffer << '\t';
@@ -253,6 +254,8 @@ myMenuRecordingsItem::myMenuRecordingsItem(cRecording *Recording,int Level)
in.close();
}
+ else
+ titlebuffer << '\t';
}
}
if(!mysetup.ShowRecDate && !mysetup.ShowRecTime && !mysetup.ShowRecLength)
@@ -304,7 +307,7 @@ void myMenuRecordingsItem::IncrementCounter(bool IsNew)
if(mysetup.ShowNewRecs)
{
asprintf(&buffer,"%c\t%s (%d)%s%s%s%s%s",
- char(130),
+ GetDirIsMoving()?char(134):char(130),
entries,
newentries,
(!mysetup.ShowRecDate&&!mysetup.ShowRecTime&&!mysetup.ShowRecLength)?"\t":"",
@@ -316,7 +319,7 @@ void myMenuRecordingsItem::IncrementCounter(bool IsNew)
else
{
asprintf(&buffer,"%c\t%s%s%s%s%s%s",
- char(130),
+ GetDirIsMoving()?char(134):char(130),
entries,
(!mysetup.ShowRecDate&&!mysetup.ShowRecTime&&!mysetup.ShowRecLength)?"\t":"",
(mysetup.ShowRecDate||mysetup.ShowRecTime||mysetup.ShowRecLength)?"\t":"",
@@ -332,106 +335,168 @@ void myMenuRecordingsItem::IncrementCounter(bool IsNew)
bool myMenuRecordings::golastreplayed=false;
bool myMenuRecordings::wasdvd;
+dev_t myMenuRecordings::fsid=0;
+int myMenuRecordings::freediskspace=0;
myMenuRecordings::myMenuRecordings(const char *Base,int Level):cOsdMenu("")
{
- // only called if plugin menu was opened
- if(Level==0)
- {
- // patch font
- if(Setup.UseSmallFont==2)
- PatchFont(fontSml);
- else
- PatchFont(fontOsd);
- }
- // set tabs
- if(mysetup.ShowRecDate&&mysetup.ShowRecTime&&!mysetup.ShowRecLength) // recording date and time are shown, recording length not
- SetCols(2,8,6);
- else if(mysetup.ShowRecDate&&mysetup.ShowRecTime) // all details are shown
- SetCols(2,8,6,4);
- else if(mysetup.ShowRecDate&&!mysetup.ShowRecTime) // recording time is not shown
- SetCols(2,8,4);
- else if(!mysetup.ShowRecDate&&mysetup.ShowRecTime&&mysetup.ShowRecLength) // recording date is not shown
- SetCols(2,6,4);
- else // recording date and time are not shown; even if recording length should be not shown we must set two tabs because the details of the directories
- {
- if(mysetup.ShowNewRecs)
- SetCols(2,8,3);
- else
- SetCols(2,4,3);
- }
+#if VDRVERSNUM < 10503
+ // only called if plugin menu was opened
+ if(Level==0 && mysetup.PatchFont)
+ {
+ // patch font
+ if(Setup.UseSmallFont==2)
+ PatchFont(fontSml);
+ else
+ PatchFont(fontOsd);
+ }
+#endif
+ // set tabs
+ if(mysetup.ShowRecDate&&mysetup.ShowRecTime&&!mysetup.ShowRecLength) // recording date and time are shown, recording length not
+ SetCols(2,8,6);
+ else if(mysetup.ShowRecDate&&mysetup.ShowRecTime) // all details are shown
+ SetCols(2,8,6,4);
+ else if(mysetup.ShowRecDate&&!mysetup.ShowRecTime) // recording time is not shown
+ SetCols(2,8,4);
+ else if(!mysetup.ShowRecDate&&mysetup.ShowRecTime&&mysetup.ShowRecLength) // recording date is not shown
+ SetCols(2,6,4);
+ else // recording date and time are not shown; even if recording length should be not shown we must set two tabs because the details of the directories
+ {
+ if(mysetup.ShowNewRecs)
+ SetCols(2,8,3);
+ else
+ SetCols(2,4,3);
+ }
- edit=false;
- level=Level;
- helpkeys=-1;
- base=Base?strdup(Base):NULL;
+ edit=false;
+ level=Level;
+ helpkeys=-1;
+ base=Base?strdup(Base):NULL;
- Recordings.StateChanged(recordingsstate);
+ Recordings.StateChanged(recordingsstate);
- Display();
+ Display();
- if(wasdvd&&!cControl::Control())
- {
- char *cmd=NULL;
- asprintf(&cmd,"dvdarchive.sh umount \"%s\"",*strescape(myReplayControl::LastReplayed(),"'\\\"$"));
- isyslog("[extrecmenu] calling %s to unmount dvd",cmd);
- int result=SystemExec(cmd);
- if(result)
+ if(wasdvd&&!cControl::Control())
{
- result=result/256;
- if(result==1)
- Skins.Message(mtError,tr("Error while mounting DVD!"));
- }
- isyslog("[extrecmenu] dvdarchive.sh returns %d",result);
- free(cmd);
+ char *cmd=NULL;
+ asprintf(&cmd,"dvdarchive.sh umount \"%s\"",*strescape(myReplayControl::LastReplayed(),"'\\\"$"));
+ isyslog("[extrecmenu] calling %s to unmount dvd",cmd);
+ int result=SystemExec(cmd);
+ if(result)
+ {
+ result=result/256;
+ if(result==1)
+ Skins.Message(mtError,tr("Error while mounting DVD!"));
+ }
+ isyslog("[extrecmenu] dvdarchive.sh returns %d",result);
+ free(cmd);
- wasdvd=false;
- }
+ wasdvd=false;
+ }
- Set();
+ Set();
- if(myReplayControl::LastReplayed())
- Open();
+ if(myReplayControl::LastReplayed())
+ Open();
- Display();
- SetHelpKeys();
+ Display();
+ SetHelpKeys();
}
myMenuRecordings::~myMenuRecordings()
{
- free(base);
+ free(base);
+#if VDRVERSNUM < 10503
+ if(level==0)
+ {
+ if(Setup.UseSmallFont==2)
+ cFont::SetFont(fontSml);
+ else
+ cFont::SetFont(fontOsd);
+ }
+#endif
+}
- if(level==0)
- {
- if(Setup.UseSmallFont==2)
- cFont::SetFont(fontSml);
+int myMenuRecordings::FreeMB()
+{
+ if(mysetup.FileSystemFreeMB)
+ {
+ string path=VideoDirectory;
+ path+="/";
+ char *tmpbase=base?ExchangeChars(strdup(base),true):NULL;
+ if(base)
+ path+=tmpbase;
+
+ struct stat statdir;
+ if(!stat(path.c_str(),&statdir))
+ {
+ if(statdir.st_dev!=fsid)
+ {
+ fsid=statdir.st_dev;
+
+ struct statvfs fsstat;
+ if(!statvfs(path.c_str(),&fsstat))
+ {
+ freediskspace=int(fsstat.f_bavail/(1024.0*1024.0/fsstat.f_bsize));
+
+ for(cRecording *rec=DeletedRecordings.First();rec;rec=DeletedRecordings.Next(rec))
+ {
+ if(!stat(rec->FileName(),&statdir))
+ {
+ if(statdir.st_dev==fsid)
+ freediskspace+=DirSizeMB(rec->FileName());
+ }
+ }
+ }
+ else
+ {
+ esyslog("[extrecmenu] error while getting filesystem size - statvfs (%s): %s",path.c_str(),strerror(errno));
+ freediskspace=0;
+ }
+ }
+ }
+ else
+ {
+ esyslog("[extrecmenu] error while getting filesystem size - stat (%s): %s",path.c_str(),strerror(errno));
+ freediskspace=0;
+ }
+ free(tmpbase);
+ }
else
- cFont::SetFont(fontOsd);
- }
+ {
+ int freemb;
+ VideoDiskSpace(&freemb);
+ return freemb;
+ }
+
+ return freediskspace;
}
void myMenuRecordings::Title()
{
- int freemb;
- VideoDiskSpace(&freemb);
+ int freemb=FreeMB();
int minutes=int(double(freemb)/MB_PER_MINUTE);
stringstream buffer;
- if(MoveThread.Active())
+ if(MoveCutterThread->IsMoveListEmpty())
buffer << char(133);
- if(cCutter::Active())
+ if(MoveCutterThread->IsCutterQueueEmpty())
buffer << char(132);
- if(MoveThread.Active() || cCutter::Active())
+ if(MoveCutterThread->IsMoveListEmpty() || MoveCutterThread->IsCutterQueueEmpty())
buffer << ' ';
if(base)
buffer << base;
else
- buffer << tr("Recordings")<< " - "
- << minutes/60 << ":"
- << setw(2) << setfill('0') << minutes%60 << " "
- << tr("free");
+ buffer << tr("Recordings");
+
+ buffer << " ("
+ << minutes/60 << ":"
+ << setw(2) << setfill('0') << minutes%60 << " "
+ << tr("free")
+ << ")";
SetTitle(buffer.str().c_str());
}
@@ -445,22 +510,30 @@ void myMenuRecordings::SetHelpKeys()
if(item)
{
if(item->IsDirectory())
- newhelpkeys=1;
+ {
+ if(item->GetDirIsMoving())
+ newhelpkeys=6;
+ else
+ newhelpkeys=1;
+ }
else
{
newhelpkeys=2;
cRecording *recording=GetRecording(item);
- if(mysetup.UseVDRsRecInfoMenu)
+ if(recording)
{
- if(!recording->Info()->Title())
+ if(mysetup.UseVDRsRecInfoMenu)
{
- newhelpkeys=4;
- if(MoveThread.IsMoving(recording->FileName()) || IsCutted())
- newhelpkeys=5;
+ if(!recording->Info()->Title())
+ {
+ newhelpkeys=4;
+ if(MoveCutterThread->IsMoving(recording->FileName()) || MoveCutterThread->IsCutting(recording->FileName()))
+ newhelpkeys=5;
+ }
}
+ if(MoveCutterThread->IsMoving(recording->FileName()) || MoveCutterThread->IsCutting(recording->FileName()))
+ newhelpkeys=3;
}
- if(MoveThread.IsMoving(recording->FileName()) || IsCutted())
- newhelpkeys=3;
}
if(newhelpkeys!=helpkeys)
{
@@ -469,9 +542,10 @@ void myMenuRecordings::SetHelpKeys()
case 0: SetHelp(NULL);break;
case 1: SetHelp(tr("Button$Open"),NULL,tr("Button$Edit"));break;
case 2: SetHelp(RecordingCommands.Count()?tr("Button$Commands"):tr("Button$Play"),tr("Button$Rewind"),tr("Button$Edit"),tr("Button$Info"));break;
- case 3: SetHelp(RecordingCommands.Count()?tr("Button$Commands"):tr("Button$Play"),tr("Button$Rewind"),NULL,tr("Button$Info"));break;
+ case 3: SetHelp(RecordingCommands.Count()?tr("Button$Commands"):tr("Button$Play"),tr("Button$Rewind"),tr("Button$Cancel"),tr("Button$Info"));break;
case 4: SetHelp(RecordingCommands.Count()?tr("Button$Commands"):tr("Button$Play"),tr("Button$Rewind"),tr("Button$Edit"),NULL);break;
- case 5: SetHelp(RecordingCommands.Count()?tr("Button$Commands"):tr("Button$Play"),tr("Button$Rewind"),NULL,NULL);break;
+ case 5: SetHelp(RecordingCommands.Count()?tr("Button$Commands"):tr("Button$Play"),tr("Button$Rewind"),tr("Button$Cancel"),NULL);break;
+ case 6: SetHelp(tr("Button$Open"),NULL,tr("Button$Cancel"));break;
}
}
helpkeys=newhelpkeys;
@@ -484,12 +558,11 @@ void myMenuRecordings::Set(bool Refresh,char *current)
{
const char *lastreplayed=current?current:myReplayControl::LastReplayed();
- Title();
-
cThreadLock RecordingsLock(&Recordings);
- if(Refresh&&!current)
+ if(Refresh && !current)
{
+ fsid=0;
myMenuRecordingsItem *item=(myMenuRecordingsItem*)Get(Current());
if(item)
{
@@ -506,13 +579,12 @@ void myMenuRecordings::Set(bool Refresh,char *current)
for(cRecording *recording=Recordings.First();recording;recording=Recordings.Next(recording))
list->Add(new myRecListItem(recording));
// sort my recordings list
- char path[BUFSIZ];
- snprintf(path,sizeof(path),"%s/%s",VideoDirectory,base?base:"");
+ string path=VideoDirectory;
+ path+="/";
+ if(base)
+ path+=base;
list->Sort(mySortList->Find(path));
- // needed for move recording menu
- Recordings.Sort();
-
char *lastitemtext=NULL;
myMenuRecordingsItem *lastitem=NULL;
for(myRecListItem *listitem=list->First();listitem;listitem=list->Next(listitem))
@@ -521,7 +593,17 @@ void myMenuRecordings::Set(bool Refresh,char *current)
if(!base||(strstr(listitem->recording->Name(),base)==listitem->recording->Name()&&listitem->recording->Name()[strlen(base)]=='~'))
{
myMenuRecordingsItem *recitem=new myMenuRecordingsItem(listitem->recording,level);
+#ifdef WITHPINPLUGIN
+ bool hidepinprotectedrecs=false;
+ cPlugin *pinplugin=cPluginManager::GetPlugin("pin");
+ if(pinplugin)
+ hidepinprotectedrecs=pinplugin->SetupParse("hideProtectedRecordings","1");
+
+ if((*recitem->UniqID() && ((!lastitem || strcmp(recitem->UniqID(),lastitemtext)))) &&
+ !((cStatus::MsgReplayProtected(GetRecording(recitem),recitem->Name(),base,recitem->IsDirectory(),true)) && hidepinprotectedrecs))
+#else
if(*recitem->UniqID() && ((!lastitem || strcmp(recitem->UniqID(),lastitemtext))))
+#endif
{
Add(recitem);
lastitem=recitem;
@@ -533,9 +615,12 @@ void myMenuRecordings::Set(bool Refresh,char *current)
if(lastitem)
{
+ if(!MoveCutterThread->IsMoving(recording->FileName()))
+ lastitem->SetDirIsMoving(false);
+
if(lastitem->IsDirectory())
lastitem->IncrementCounter(recording->IsNew());
- if(lastreplayed&&!strcmp(lastreplayed,recording->FileName()))
+ if(lastreplayed && !strcmp(lastreplayed,recording->FileName()))
{
if(golastreplayed||Refresh)
{
@@ -551,6 +636,8 @@ void myMenuRecordings::Set(bool Refresh,char *current)
}
free(lastitemtext);
delete list;
+
+ Title();
if(Refresh)
Display();
}
@@ -588,118 +675,119 @@ bool myMenuRecordings::Open()
// plays a recording
eOSState myMenuRecordings::Play()
{
- char *msg=NULL;
- char *name=NULL;
+ char *msg=NULL;
+ char *name=NULL;
- char path[MaxFileName];
+ char path[MaxFileName];
- myMenuRecordingsItem *item=(myMenuRecordingsItem*)Get(Current());
- if(item)
- {
+ myMenuRecordingsItem *item=(myMenuRecordingsItem*)Get(Current());
+ if(item)
+ {
#ifdef WITHPINPLUGIN
- if(cStatus::MsgReplayProtected(GetRecording(item),item->Name(),base,item->IsDirectory())==true)
- return osContinue;
+ if(cStatus::MsgReplayProtected(GetRecording(item),item->Name(),base,item->IsDirectory())==true)
+ return osContinue;
#endif
- if(item->IsDirectory())
- Open();
- else
- {
- cRecording *recording=GetRecording(item);
- if(recording)
- {
- if(item->IsDVD())
+ if(item->IsDirectory())
+ Open();
+ else
{
- bool isvideodvd=false;
- char dvdnr[BUFSIZ];
- char *buffer=NULL;
- FILE *f;
-
- asprintf(&buffer,"%s/dvd.vdr",recording->FileName());
- if((f=fopen(buffer,"r"))!=NULL)
+ cRecording *recording=GetRecording(item);
+ if(recording)
{
- // get the dvd id
- if(fgets(dvdnr,sizeof(dvdnr),f))
+ if(item->IsDVD())
{
- char *p=strchr(dvdnr,'\n');
- if(p)
- *p=0;
- }
- // determine if dvd is a video dvd
- char tmp[BUFSIZ];
- if(fgets(tmp,sizeof(dvdnr),f))
- isvideodvd=true;
+ bool isvideodvd=false;
+ char dvdnr[BUFSIZ];
+ char *buffer=NULL;
+ FILE *f;
+
+ asprintf(&buffer,"%s/dvd.vdr",recording->FileName());
+ if((f=fopen(buffer,"r"))!=NULL)
+ {
+ // get the dvd id
+ if(fgets(dvdnr,sizeof(dvdnr),f))
+ {
+ char *p=strchr(dvdnr,'\n');
+ if(p)
+ *p=0;
+ }
+ // determine if dvd is a video dvd
+ char tmp[BUFSIZ];
+ if(fgets(tmp,sizeof(dvdnr),f))
+ isvideodvd=true;
- fclose(f);
- }
- free(buffer);
+ fclose(f);
+ }
+ free(buffer);
- asprintf(&msg,tr("Please insert DVD %s"),dvdnr);
- if(Interface->Confirm(msg))
- {
- free(msg);
- // recording is a video dvd
- if(isvideodvd)
- {
- cPlugin *plugin=cPluginManager::GetPlugin("dvd");
- if(plugin)
+ asprintf(&msg,tr("Please insert DVD %s"),dvdnr);
+ if(Interface->Confirm(msg))
{
- cOsdObject *osd=plugin->MainMenuAction();
- delete osd;
- osd=NULL;
- return osEnd;
+ free(msg);
+ // recording is a video dvd
+ if(isvideodvd)
+ {
+ cPlugin *plugin=cPluginManager::GetPlugin("dvd");
+ if(plugin)
+ {
+ cOsdObject *osd=plugin->MainMenuAction();
+ delete osd;
+ osd=NULL;
+ return osEnd;
+ }
+ else
+ {
+ Skins.Message(mtError,tr("DVD plugin is not installed!"));
+ return osContinue;
+ }
+ }
+ // recording is an archive dvd
+ else
+ {
+ strcpy(path,recording->FileName());
+ name=strrchr(path,'/')+1;
+ asprintf(&msg,"dvdarchive.sh mount \"%s\" '%s'",*strescape(path,"'"),*strescape(name,"'\\\"$"));
+
+ isyslog("[extrecmenu] calling %s to mount dvd",msg);
+ int result=SystemExec(msg);
+ isyslog("[extrecmenu] dvdarchive.sh returns %d",result);
+ free(msg);
+ if(result)
+ {
+ result=result/256;
+ if(result==1)
+ Skins.Message(mtError,tr("Error while mounting DVD!"));
+ if(result==2)
+ Skins.Message(mtError,tr("No DVD in drive!"));
+ if(result==3)
+ Skins.Message(mtError,tr("Recording not found on DVD!"));
+ if(result==4)
+ Skins.Message(mtError,tr("Error while linking [0-9]*.vdr!"));
+ if(result==5)
+ Skins.Message(mtError,tr("sudo or mount --bind / umount error (vfat system)"));
+ if(result==127)
+ Skins.Message(mtError,tr("Script 'dvdarchive.sh' not found!"));
+ return osContinue;
+ }
+ wasdvd=true;
+ }
}
else
{
- Skins.Message(mtError,tr("DVD plugin is not installed!"));
+ free(msg);
return osContinue;
}
}
- // recording is a archive dvd
- else
- {
- strcpy(path,recording->FileName());
- name=strrchr(path,'/')+1;
- asprintf(&msg,"dvdarchive.sh mount \"%s\" '%s'",*strescape(path,"'"),*strescape(name,"'\\\"$"));
-
- isyslog("[extrecmenu] calling %s to mount dvd",msg);
- int result=SystemExec(msg);
- isyslog("[extrecmenu] dvdarchive.sh returns %d",result);
- free(msg);
- if(result)
- {
- result=result/256;
- if(result==1)
- Skins.Message(mtError,tr("Error while mounting DVD!"));
- if(result==2)
- Skins.Message(mtError,tr("No DVD in drive!"));
- if(result==3)
- Skins.Message(mtError,tr("Recording not found on DVD!"));
- if(result==4)
- Skins.Message(mtError,tr("Error while linking [0-9]*.vdr!"));
- if(result==5)
- Skins.Message(mtError,tr("sudo or mount --bind / umount error (vfat system)"));
- if(result==127)
- Skins.Message(mtError,tr("Script 'dvdarchive.sh' not found!"));
- return osContinue;
- }
- wasdvd=true;
- }
- }
- else
- {
- free(msg);
- return osContinue;
+ golastreplayed=true;
+ myReplayControl::SetRecording(recording->FileName(),recording->Title());
+ cControl::Shutdown();
+ isyslog("[extrecmenu] starting replay of recording");
+ cControl::Launch(new myReplayControl());
+ return osEnd;
}
}
- golastreplayed=true;
- myReplayControl::SetRecording(recording->FileName(),recording->Title());
- cControl::Shutdown(); // stop running playbacks
- cControl::Launch(new myReplayControl); // start playback
- return osEnd; // close plugin
- }
}
- }
- return osContinue;
+ return osContinue;
}
// plays a recording from the beginning
@@ -722,55 +810,55 @@ eOSState myMenuRecordings::Rewind()
// delete a recording
eOSState myMenuRecordings::Delete()
{
- if(HasSubMenu()||Count()==0)
- return osContinue;
+ if(HasSubMenu()||Count()==0)
+ return osContinue;
- myMenuRecordingsItem *item=(myMenuRecordingsItem*)Get(Current());
- if(item&&!item->IsDirectory())
- {
- if(Interface->Confirm(tr("Delete recording?")))
+ myMenuRecordingsItem *item=(myMenuRecordingsItem*)Get(Current());
+ if(item&&!item->IsDirectory())
{
- cRecordControl *rc=cRecordControls::GetRecordControl(item->FileName());
- if(rc)
- {
- if(Interface->Confirm(tr("Timer still recording - really delete?")))
+ if(Interface->Confirm(tr("Delete recording?")))
{
- cTimer *timer=rc->Timer();
- if(timer)
- {
- timer->Skip();
- cRecordControls::Process(time(NULL));
- if(timer->IsSingleEvent())
+ cRecordControl *rc=cRecordControls::GetRecordControl(item->FileName());
+ if(rc)
+ {
+ if(Interface->Confirm(tr("Timer still recording - really delete?")))
+ {
+ cTimer *timer=rc->Timer();
+ if(timer)
+ {
+ timer->Skip();
+ cRecordControls::Process(time(NULL));
+ if(timer->IsSingleEvent())
+ {
+ isyslog("deleting timer %s",*timer->ToDescr());
+ Timers.Del(timer);
+ }
+ Timers.SetModified();
+ }
+ }
+ else
+ return osContinue;
+ }
+ cRecording *recording=GetRecording(item);
+ if(recording)
{
- isyslog("deleting timer %s",*timer->ToDescr());
- Timers.Del(timer);
+ if(recording->Delete())
+ {
+ cRecordingUserCommand::InvokeCommand("delete",item->FileName());
+ myReplayControl::ClearLastReplayed(item->FileName());
+ Recordings.DelByName(item->FileName());
+ cOsdMenu::Del(Current());
+ SetHelpKeys();
+ Display();
+ if(!Count())
+ return osBack;
+ }
+ else
+ Skins.Message(mtError,tr("Error while deleting recording!"));
}
- Timers.SetModified();
- }
- }
- else
- return osContinue;
- }
- cRecording *recording=GetRecording(item);
- if(recording)
- {
- if(recording->Delete())
- {
- cRecordingUserCommand::InvokeCommand("delete",item->FileName());
- myReplayControl::ClearLastReplayed(item->FileName());
- Recordings.DelByName(item->FileName());
- cOsdMenu::Del(Current());
- SetHelpKeys();
- Display();
- if(!Count())
- return osBack;
}
- else
- Skins.Message(mtError,tr("Error while deleting recording!"));
- }
}
- }
- return osContinue;
+ return osContinue;
}
// renames a recording
@@ -783,12 +871,12 @@ eOSState myMenuRecordings::Rename()
if(item)
{
if(item->IsDirectory())
- return AddSubMenu(new myMenuRenameRecording(this,NULL,base,item->Name()));
+ return AddSubMenu(new myMenuRenameRecording(NULL,base,item->Name()));
else
{
cRecording *recording=GetRecording(item);
if(recording)
- return AddSubMenu(new myMenuRenameRecording(this,recording,NULL,NULL));
+ return AddSubMenu(new myMenuRenameRecording(recording,NULL,NULL));
}
}
return osContinue;
@@ -805,7 +893,7 @@ eOSState myMenuRecordings::Details()
{
cRecording *recording=GetRecording(item);
if(recording)
- return AddSubMenu(new myMenuRecordingDetails(recording,this));
+ return AddSubMenu(new myMenuRecordingDetails(recording));
}
return osContinue;
}
@@ -813,23 +901,23 @@ eOSState myMenuRecordings::Details()
// moves a recording
eOSState myMenuRecordings::MoveRec()
{
- if(HasSubMenu()||Count()==0)
- return osContinue;
+ if(HasSubMenu() || Count()==0)
+ return osContinue;
- myMenuRecordingsItem *item=(myMenuRecordingsItem*)Get(Current());
- if(item)
- {
- myMenuMoveRecording::clearall=false;
- if(item->IsDirectory())
- return AddSubMenu(new myMenuMoveRecording(this,NULL,base,item->Name()));
- else
+ myMenuRecordingsItem *item=(myMenuRecordingsItem*)Get(Current());
+ if(item)
{
- cRecording *recording=GetRecording(item);
- if(recording)
- return AddSubMenu(new myMenuMoveRecording(this,recording,NULL,NULL));
+ myMenuMoveRecording::clearall=false;
+ if(item->IsDirectory())
+ return AddSubMenu(new myMenuMoveRecording(NULL,base,item->Name()));
+ else
+ {
+ cRecording *recording=GetRecording(item);
+ if(recording)
+ return AddSubMenu(new myMenuMoveRecording(recording,NULL,NULL));
+ }
}
- }
- return osContinue;
+ return osContinue;
}
// opens an info screen to a recording
@@ -862,7 +950,7 @@ eOSState myMenuRecordings::Commands(eKeys Key)
if(recording)
{
char *parameter=NULL;
- asprintf(&parameter,"'%s'",recording->FileName());
+ asprintf(&parameter,"\"%s\"",recording->FileName());
myMenuCommands *menu;
eOSState state=AddSubMenu(menu=new myMenuCommands(tr("Recording commands"),&RecordingCommands,parameter));
free(parameter);
@@ -877,151 +965,155 @@ eOSState myMenuRecordings::Commands(eKeys Key)
// change sorting
eOSState myMenuRecordings::ChangeSorting()
{
- char buffer[BUFSIZ];
-
- snprintf(buffer,sizeof(buffer),"%s/%s",VideoDirectory,base?base:"");
-
- for(SortListItem *item=mySortList->First();item;item=mySortList->Next(item))
- {
- if(!strcmp(buffer,item->Path()))
+ string path=VideoDirectory;
+ path+="/";
+ if(base)
+ path+=base;
+
+ for(SortListItem *item=mySortList->First();item;item=mySortList->Next(item))
{
- mySortList->Del(item);
- mySortList->WriteConfigFile();
- Set(true);
+ if(path==item->Path())
+ {
+ mySortList->Del(item);
+ mySortList->WriteConfigFile();
+ Set(true);
- Skins.Message(mtInfo,tr("Sort by date"),1);
+ Skins.Message(mtInfo,tr("Sort by date"),1);
- return osContinue;
+ return osContinue;
+ }
}
- }
- mySortList->Add(new SortListItem(buffer));
- mySortList->WriteConfigFile();
- Set(true);
+ mySortList->Add(new SortListItem(path));
+ mySortList->WriteConfigFile();
+ Set(true);
- Skins.Message(mtInfo,tr("Sort by name"),1);
+ Skins.Message(mtInfo,tr("Sort by name"),1);
- return osContinue;
-}
-
-bool myMenuRecordings::IsCutted()
-{
- if(cCutter::Active()) // cut in progress?
- {
- if(myReplayControl::Cut && myReplayControl::Cutted) // are there the paths to the cutted recording?
- {
- myMenuRecordingsItem *item=(myMenuRecordingsItem*)Get(Current());
- if(item)
- {
- cRecording *recording=GetRecording(item);
- if(recording)
- {
- if(!strcmp(recording->FileName(),myReplayControl::Cut) || !strcmp(recording->FileName(),myReplayControl::Cutted))
- return true; // selected recording is cutted
- else
- return false; // seleted recording is not cutted
- }
- }
- }
- return true; // cut is in progress but i don't know for which recording, so editing for all recordings is prohibited
- }
- return false; // no cut in progress
+ return osContinue;
}
eOSState myMenuRecordings::ProcessKey(eKeys Key)
{
- eOSState state;
+ eOSState state;
- if(edit)
- {
- myMenuRecordingsItem *item=(myMenuRecordingsItem*)Get(Current());
- if(Key==kRed||Key==kGreen||Key==kYellow||(!item->IsDVD()&&Key==kBlue)||Key==kBack)
- {
- edit=false;
- helpkeys=-1;
- }
- switch(Key)
+ if(edit)
{
- case kRed: return Rename();
- case kGreen: return MoveRec();
- case kYellow: return Delete();
- case kBlue: if(item&&!item->IsDVD())
- return Details();
- else
- break;
- case kBack: SetHelpKeys();
- default: break;
+ myMenuRecordingsItem *item=(myMenuRecordingsItem*)Get(Current());
+ if(Key==kRed || Key==kGreen || Key==kYellow || (!item->IsDVD() && Key==kBlue) || Key==kBack)
+ {
+ edit=false;
+ helpkeys=-1;
+ }
+ switch(Key)
+ {
+ case kRed: return Rename();
+ case kGreen: return MoveRec();
+ case kYellow: return Delete();
+ case kBlue: if(item&&!item->IsDVD())
+ return Details();
+ else
+ break;
+ case kBack: SetHelpKeys();
+ default: break;
+ }
+ state=osContinue;
}
- state=osContinue;
- }
- else
- {
- bool hadsubmenu=HasSubMenu();
-
- state=cOsdMenu::ProcessKey(Key);
- if(state==osUnknown)
+ else
{
- switch(Key)
- {
- case kOk: return Play();
- case kRed: return (helpkeys>1&&RecordingCommands.Count())?Commands():Play();
- case kGreen: return Rewind();
- case kYellow: if(!IsCutted())
- {
- myMenuRecordingsItem *item=(myMenuRecordingsItem*)Get(Current());
- if(item)
- {
- cRecording *rec=GetRecording(item);
- if(rec)
- {
- if(MoveThread.IsMoving(rec->FileName()))
- break;
+ state=cOsdMenu::ProcessKey(Key);
+ if(state==osUnknown)
+ {
+ switch(Key)
+ {
+ case kOk: return Play();
+ case kRed: return (helpkeys>1 && RecordingCommands.Count())?Commands():Play();
+ case kGreen: return Rewind();
+ case kYellow: {
+ if(!HasSubMenu())
+ {
+ myMenuRecordingsItem *item=(myMenuRecordingsItem*)Get(Current());
+ if(item)
+ {
+ if(item->IsDirectory())
+ {
+ if(item->GetDirIsMoving())
+ {
+ string path;
+ if(base)
+ {
+ path=base;
+ path+="~";
+ path+=item->Name();
+ }
+ else
+ path=item->Name();
+
+ if(Interface->Confirm(tr("Cancel moving?")))
+ {
+ for(cRecording *rec=Recordings.First();rec;rec=Recordings.Next(rec))
+ {
+ if(!strncmp(path.c_str(),rec->Name(),path.length()))
+ MoveCutterThread->CancelMove(rec->FileName());
+ }
+ Set(true);
+ }
+ }
+ else
+ {
+ edit=true;
+ SetHelp(tr("Button$Rename"),tr("Button$Move"));
+ }
+ }
+ else
+ {
+ cRecording *rec=GetRecording(item);
+ if(rec)
+ {
#ifdef WITHPINPLUGIN
- if(cStatus::MsgReplayProtected(rec,item->Name(),base,item->IsDirectory())==true)
- break;
-#endif
- }
- if(!HasSubMenu())
- {
- edit=true;
- if(item->IsDirectory())
- SetHelp(tr("Button$Rename"),tr("Button$Move"));
- else
- SetHelp(tr("Button$Rename"),tr("Button$Move"),tr("Button$Delete"),(!item->IsDVD())?tr("Details"):NULL);
+ if(cStatus::MsgReplayProtected(rec,item->Name(),base,item->IsDirectory())==true)
+ break;
+#endif
+ if(MoveCutterThread->IsCutting(rec->FileName()))
+ {
+ if(Interface->Confirm(tr("Cancel editing?")))
+ {
+ MoveCutterThread->CancelCut(rec->FileName());
+ Set(true);
+ }
+ }
+ else if(MoveCutterThread->IsMoving(rec->FileName()))
+ {
+ if(Interface->Confirm(tr("Cancel moving?")))
+ {
+ MoveCutterThread->CancelMove(rec->FileName());
+ Set(true);
+ }
+ }
+ else
+ {
+ edit=true;
+ SetHelp(tr("Button$Rename"),tr("Button$Move"),tr("Button$Delete"),(!item->IsDVD())?tr("Details"):NULL);
+ }
+ }
+ }
+ }
+ }
}
- }
- }
- break;
- case kBlue: return Info();
- case k1...k9: return Commands(Key);
- case k0: return ChangeSorting();
- default: break;
- }
- }
- // go back if list is empty
- if(!Count()&&level>0)
- state=osBack;
-
- // update menu list after sub menu has closed
- if(hadsubmenu&&!HasSubMenu()||Recordings.StateChanged(recordingsstate)||cCutter::Active())
- Set(true);
-
- if(!cCutter::Active())
- {
- // no cut in progress so delete the paths to the cutted recording
- if(myReplayControl::Cut)
- {
- free(myReplayControl::Cut);
- myReplayControl::Cut=NULL;
- }
- if(myReplayControl::Cutted)
- {
- free(myReplayControl::Cutted);
- myReplayControl::Cutted=NULL;
+ break;
+ case kBlue: return Info();
+ case k1...k9: return Commands(Key);
+ case k0: return ChangeSorting();
+ default: break;
+ }
}
+ if(Recordings.StateChanged(recordingsstate) || MoveCutterThread->IsCutterQueueEmpty())
+ Set(true);
+
+ if(!Count() && level>0)
+ state=osBack;
+
+ if(!HasSubMenu() && Key!=kNone)
+ SetHelpKeys();
}
-
- if(!HasSubMenu()&&Key!=kNone);
- SetHelpKeys();
- }
- return state;
+ return state;
}
diff --git a/mymenurecordings.h b/mymenurecordings.h
index c112be2..e23e61f 100644
--- a/mymenurecordings.h
+++ b/mymenurecordings.h
@@ -2,6 +2,7 @@
class myMenuRecordingsItem:public cOsdItem
{
private:
+ bool dirismoving;
bool isdvd;
int level,isdirectory;
int totalentries,newentries;
@@ -17,6 +18,8 @@ class myMenuRecordingsItem:public cOsdItem
bool IsDirectory(){return name!=NULL;}
void IncrementCounter(bool IsNew);
bool IsDVD(){return isdvd;}
+ void SetDirIsMoving(bool moving){dirismoving=moving;}
+ bool GetDirIsMoving(){return dirismoving;}
const char *UniqID(){return uniqid.length()?uniqid.c_str():"";}
};
@@ -27,6 +30,8 @@ class myMenuRecordings:public cOsdMenu
bool edit;
static bool wasdvd;
static bool golastreplayed;
+ static dev_t fsid;
+ static int freediskspace;
int level,helpkeys;
int recordingsstate;
char *base;
@@ -43,7 +48,7 @@ class myMenuRecordings:public cOsdMenu
eOSState Details();
eOSState Commands(eKeys Key=kNone);
eOSState ChangeSorting();
- bool IsCutted();
+ int FreeMB();
public:
myMenuRecordings(const char *Base=NULL,int Level=0);
~myMenuRecordings();
@@ -62,7 +67,7 @@ class myMenuRenameRecording:public cOsdMenu
cRecording *recording;
myMenuRecordings *menurecordings;
public:
- myMenuRenameRecording(myMenuRecordings *MenuRecordings,cRecording *Recording,const char *DirBase,const char *DirName);
+ myMenuRenameRecording(cRecording *Recording,const char *DirBase,const char *DirName);
~myMenuRenameRecording();
virtual eOSState ProcessKey(eKeys Key);
};
@@ -81,7 +86,7 @@ class myMenuMoveRecording:public cOsdMenu
eOSState MoveRec();
eOSState Create();
public:
- myMenuMoveRecording(myMenuRecordings *MenuRecordings,cRecording *Recording,const char *DirBase,const char *DirName,const char *Base=NULL,int Level=0);
+ myMenuMoveRecording(cRecording *Recording,const char *DirBase,const char *DirName,const char *Base=NULL,int Level=0);
~myMenuMoveRecording();
virtual eOSState ProcessKey(eKeys Key);
static bool clearall;
@@ -95,6 +100,6 @@ class myMenuRecordingDetails:public cOsdMenu
cRecording *recording;
myMenuRecordings *menurecordings;
public:
- myMenuRecordingDetails(cRecording *Recording,myMenuRecordings *MenuRecordings);
+ myMenuRecordingDetails(cRecording *Recording);
virtual eOSState ProcessKey(eKeys Key);
};
diff --git a/mymenusetup.c b/mymenusetup.c
index 40442e8..42c9eb3 100644
--- a/mymenusetup.c
+++ b/mymenusetup.c
@@ -7,66 +7,81 @@
mySetup::mySetup()
{
- mysetup.HideMainMenuEntry=0;
- mysetup.PatchNew=1;
- mysetup.ReplaceOrgRecMenu=0;
- mysetup.ShowRecDate=1;
- mysetup.ShowRecTime=1;
- mysetup.ShowRecLength=0;
- mysetup.ShowNewRecs=1;
- mysetup.DescendSorting=0;
- mysetup.GoLastReplayed=0;
- mysetup.ReturnToPlugin=1;
- mysetup.LimitBandwidth=0;
- mysetup.UseVDRsRecInfoMenu=0;
+ mysetup.HideMainMenuEntry=0;
+ mysetup.PatchNew=1;
+ mysetup.ReplaceOrgRecMenu=0;
+ mysetup.ShowRecDate=1;
+ mysetup.ShowRecTime=1;
+ mysetup.ShowRecLength=0;
+ mysetup.ShowNewRecs=1;
+ mysetup.DescendSorting=0;
+ mysetup.GoLastReplayed=0;
+ mysetup.ReturnToPlugin=1;
+ mysetup.LimitBandwidth=0;
+ mysetup.UseVDRsRecInfoMenu=0;
+ mysetup.PatchFont=1;
+ mysetup.FileSystemFreeMB=1;
}
mySetup mysetup;
myMenuSetup::myMenuSetup()
{
- hidemainmenuentry=mysetup.HideMainMenuEntry;
- patchnew=mysetup.PatchNew;
- replaceorgrecmenu=mysetup.ReplaceOrgRecMenu;
- showrecdate=mysetup.ShowRecDate;
- showrectime=mysetup.ShowRecTime;
- showreclength=mysetup.ShowRecLength;
- shownewrecs=mysetup.ShowNewRecs;
- descendsorting=mysetup.DescendSorting;
- golastreplayed=mysetup.GoLastReplayed;
- returntoplugin=mysetup.ReturnToPlugin;
- limitbandwidth=mysetup.LimitBandwidth;
- usevdrsrecinfomenu=mysetup.UseVDRsRecInfoMenu;
+ SetCols(36);
+
+ hidemainmenuentry=mysetup.HideMainMenuEntry;
+ patchnew=mysetup.PatchNew;
+ replaceorgrecmenu=mysetup.ReplaceOrgRecMenu;
+ showrecdate=mysetup.ShowRecDate;
+ showrectime=mysetup.ShowRecTime;
+ showreclength=mysetup.ShowRecLength;
+ shownewrecs=mysetup.ShowNewRecs;
+ descendsorting=mysetup.DescendSorting;
+ golastreplayed=mysetup.GoLastReplayed;
+ returntoplugin=mysetup.ReturnToPlugin;
+ limitbandwidth=mysetup.LimitBandwidth;
+ usevdrsrecinfomenu=mysetup.UseVDRsRecInfoMenu;
+ patchfont=mysetup.PatchFont;
+ filesystemfreemb=mysetup.FileSystemFreeMB;
- sortingtypetexts[0]=tr("ascending");
- sortingtypetexts[1]=tr("descending");
+ sortingtypetexts[0]=tr("ascending");
+ sortingtypetexts[1]=tr("descending");
- Add(new cMenuEditBoolItem(tr("Hide main menu entry"),&hidemainmenuentry));
- Add(new cMenuEditBoolItem(tr("Replace original recordings menu"),&replaceorgrecmenu));
- Add(new cMenuEditStraItem(tr("Sorting"),&descendsorting,2,sortingtypetexts));
- Add(new cMenuEditBoolItem(tr("Show recording date"),&showrecdate));
- Add(new cMenuEditBoolItem(tr("Show recording time"),&showrectime));
- Add(new cMenuEditBoolItem(tr("Show recording length"),&showreclength));
- Add(new cMenuEditBoolItem(tr("Show nr. of new recordings in a directory"),&shownewrecs));
- Add(new cMenuEditBoolItem(tr("Show alternative to new marker"),&patchnew));
- Add(new cMenuEditBoolItem(tr("Jump to last replayed recording"),&golastreplayed));
- Add(new cMenuEditBoolItem(tr("Call plugin after playback"),&returntoplugin));
- Add(new cMenuEditBoolItem(tr("Limit bandwidth for move recordings"),&limitbandwidth));
- Add(new cMenuEditBoolItem(tr("Use VDR's recording info menu"),&usevdrsrecinfomenu));
+ Add(new cMenuEditBoolItem(tr("Show recording date"),&showrecdate));
+ Add(new cMenuEditBoolItem(tr("Show recording time"),&showrectime));
+ Add(new cMenuEditBoolItem(tr("Show recording length"),&showreclength));
+ Add(new cMenuEditBoolItem(tr("Show nr. of new recordings of a directory"),&shownewrecs));
+ Add(new cMenuEditBoolItem(tr("Show alternative to new marker"),&patchnew));
+ Add(new cMenuEditBoolItem(tr("Show free disk space for each file system"),&filesystemfreemb));
+ Add(new cMenuEditStraItem(tr("Sorting"),&descendsorting,2,sortingtypetexts));
+ Add(new cMenuEditBoolItem(tr("Hide main menu entry"),&hidemainmenuentry));
+#ifdef MAINMENUHOOKSVERSNUM
+ Add(new cMenuEditBoolItem(tr("Replace original recordings menu"),&replaceorgrecmenu));
+#endif
+ Add(new cMenuEditBoolItem(tr("Jump to last replayed recording"),&golastreplayed));
+ Add(new cMenuEditBoolItem(tr("Call plugin after playback"),&returntoplugin));
+#if VDRVERSNUM < 10503
+ Add(new cMenuEditBoolItem(tr("Patch font"),&patchfont));
+#endif
+ Add(new cMenuEditBoolItem(tr("Limit bandwidth for move recordings"),&limitbandwidth));
+ Add(new cMenuEditBoolItem(tr("Use VDR's recording info menu"),&usevdrsrecinfomenu));
}
void myMenuSetup::Store()
{
- SetupStore("HideMainMenuEntry",mysetup.HideMainMenuEntry=hidemainmenuentry);
- SetupStore("PatchNew",mysetup.PatchNew=patchnew);
- SetupStore("ReplaceOrgRecMenu",mysetup.ReplaceOrgRecMenu=replaceorgrecmenu);
- SetupStore("ShowRecDate",mysetup.ShowRecDate=showrecdate);
- SetupStore("ShowRecTime",mysetup.ShowRecTime=showrectime);
- SetupStore("ShowRecLength",mysetup.ShowRecLength=showreclength);
- SetupStore("ShowNewRecs",mysetup.ShowNewRecs=shownewrecs);
- SetupStore("DescendSorting",mysetup.DescendSorting=descendsorting);
- SetupStore("GoLastReplayed",mysetup.GoLastReplayed=golastreplayed);
- SetupStore("ReturnToPlugin",mysetup.ReturnToPlugin=returntoplugin);
- SetupStore("LimitBandwidth",mysetup.LimitBandwidth=limitbandwidth);
- SetupStore("UseVDRsRecInfoMenu",mysetup.UseVDRsRecInfoMenu=usevdrsrecinfomenu);
+ SetupStore("HideMainMenuEntry",mysetup.HideMainMenuEntry=hidemainmenuentry);
+ SetupStore("PatchNew",mysetup.PatchNew=patchnew);
+ SetupStore("ReplaceOrgRecMenu",mysetup.ReplaceOrgRecMenu=replaceorgrecmenu);
+ SetupStore("ShowRecDate",mysetup.ShowRecDate=showrecdate);
+ SetupStore("ShowRecTime",mysetup.ShowRecTime=showrectime);
+ SetupStore("ShowRecLength",mysetup.ShowRecLength=showreclength);
+ SetupStore("ShowNewRecs",mysetup.ShowNewRecs=shownewrecs);
+ SetupStore("DescendSorting",mysetup.DescendSorting=descendsorting);
+ SetupStore("GoLastReplayed",mysetup.GoLastReplayed=golastreplayed);
+ SetupStore("ReturnToPlugin",mysetup.ReturnToPlugin=returntoplugin);
+ SetupStore("LimitBandwidth",mysetup.LimitBandwidth=limitbandwidth);
+ SetupStore("UseVDRsRecInfoMenu",mysetup.UseVDRsRecInfoMenu=usevdrsrecinfomenu);
+ SetupStore("PatchFont",mysetup.PatchFont=patchfont);
+ SetupStore("FileSystemFreeMB",mysetup.FileSystemFreeMB=filesystemfreemb);
}
+
diff --git a/mymenusetup.h b/mymenusetup.h
index 740cd25..8332b93 100644
--- a/mymenusetup.h
+++ b/mymenusetup.h
@@ -16,6 +16,8 @@ class mySetup
int ReturnToPlugin;
int LimitBandwidth;
int UseVDRsRecInfoMenu;
+ int PatchFont;
+ int FileSystemFreeMB;
};
extern mySetup mysetup;
@@ -36,6 +38,8 @@ class myMenuSetup:public cMenuSetupPage
int returntoplugin;
int limitbandwidth;
int usevdrsrecinfomenu;
+ int patchfont;
+ int filesystemfreemb;
protected:
virtual void Store();
public:
diff --git a/myreplaycontrol.c b/myreplaycontrol.c
index 5305746..d929272 100644
--- a/myreplaycontrol.c
+++ b/myreplaycontrol.c
@@ -2,16 +2,21 @@
* See the README file for copyright information and how to reach the author.
*/
+#include <string>
#include <vdr/interface.h>
#include <vdr/status.h>
#include <vdr/menu.h>
+#include <vdr/cutter.h>
#include "myreplaycontrol.h"
#include "mymenusetup.h"
+#include "tools.h"
using namespace std;
-char *myReplayControl::Cut=NULL;
-char *myReplayControl::Cutted=NULL;
+myReplayControl::myReplayControl()
+{
+ timesearchactive=false;
+}
myReplayControl::~myReplayControl()
{
@@ -21,18 +26,47 @@ myReplayControl::~myReplayControl()
eOSState myReplayControl::ProcessKey(eKeys Key)
{
- if(Key==kBack)
- return osEnd;
-
- if(Key==kEditCut)
+ if(Key!=kNone)
{
- free(Cut);
- Cut=strdup(LastReplayed());
+ if(Key==kBack)
+ return osEnd;
+
+ if(timesearchactive)
+ {
+ if(Key<k0 && Key>k9)
+ timesearchactive=false;
+ }
+ else
+ {
+ if(Key==kEditCut)
+ {
+ const char *filename=NowReplaying();
- cRecording recording(LastReplayed());
- free(Cutted);
- Cutted=strdup(recording.PrefixFileName('%'));
+ if(filename)
+ {
+ if(MoveCutterThread->IsCutting(filename))
+ Skins.Message(mtError,tr("Recording already in cutter queue!"));
+ else
+ {
+ cMarks marks;
+ marks.Load(filename);
+
+ if(!marks.Count())
+ Skins.Message(mtError,tr("No editing marks defined!"));
+ else
+ {
+ MoveCutterThread->AddToCutterQueue(filename);
+ Skins.Message(mtInfo,tr("Added recording to cutter queue"));
+ }
+ }
+ }
+ return osContinue;
+ }
+
+ if(Key==kRed)
+ timesearchactive=true;
+ }
}
-
+
return cReplayControl::ProcessKey(Key);
}
diff --git a/myreplaycontrol.h b/myreplaycontrol.h
index 2819dd1..85bc179 100644
--- a/myreplaycontrol.h
+++ b/myreplaycontrol.h
@@ -1,8 +1,9 @@
class myReplayControl:public cReplayControl
{
+ private:
+ bool timesearchactive;
public:
- static char *Cut;
- static char *Cutted;
- eOSState ProcessKey(eKeys Key);
- ~myReplayControl();
+ myReplayControl();
+ ~myReplayControl();
+ eOSState ProcessKey(eKeys Key);
};
diff --git a/patchfont.c b/patchfont.c
index 72c023b..28b4237 100644
--- a/patchfont.c
+++ b/patchfont.c
@@ -6,6 +6,7 @@
#include "patchfont.h"
#include "mymenusetup.h"
+#if VDRVERSNUM < 10503
void PatchFont(eDvbFont DvbFont)
{
const cFont *font = cFont::GetFont(DvbFont);
@@ -253,23 +254,23 @@ void PatchFont(eDvbFont DvbFont)
{
font_data[i*num_rows+ 0]=22;
font_data[i*num_rows+ 1]=27;
- font_data[i*num_rows+ 8]=0x000000; // .. .... .... .... .... ....
- font_data[i*num_rows+ 9]=0x0001fe; // .. .... .... .... .... ....
- font_data[i*num_rows+10]=0x0001fe; // .. .... .... .... .... ....
- font_data[i*num_rows+11]=0x000186; // .. .... .... .... .... ....
- font_data[i*num_rows+12]=0x000006; // .. .... .... .... .... ....
- font_data[i*num_rows+13]=0x0ff7e6; // .. .... .... .... .... ....
- font_data[i*num_rows+14]=0x0fe3c6; // .. .... .... .... .... ....
- font_data[i*num_rows+15]=0x0c07c6; // .. .... .... .... .... ....
- font_data[i*num_rows+16]=0x0c1f86; // .. .... .... .... .... ....
- font_data[i*num_rows+17]=0x0c7906; // .. .... .... .... .... ....
- font_data[i*num_rows+18]=0x0de07e; // .. .... .... .... .... ....
- font_data[i*num_rows+19]=0x0d80fe; // .. .... .... .... .... ....
- font_data[i*num_rows+20]=0x0c3000; // .. .... .... .... .... ....
- font_data[i*num_rows+21]=0x0c3000; // .. .... .... .... .... ....
- font_data[i*num_rows+22]=0x0ff000; // .. .... .... .... .... ....
- font_data[i*num_rows+23]=0x0ff000; // .. .... .... .... .... ....
- font_data[i*num_rows+24]=0x000000; // .. .... .... .... .... ....
+ font_data[i*num_rows+ 8]=0x0001fe; // .. .... .... ...# #### ###.
+ font_data[i*num_rows+ 9]=0x0001fe; // .. .... .... ...# #### ###.
+ font_data[i*num_rows+10]=0x000186; // .. .... .... ...# #... .##.
+ font_data[i*num_rows+11]=0x000186; // .. .... .... ...#.#... .##.
+ font_data[i*num_rows+12]=0x000006; // .. .... .... .... .... .##.
+ font_data[i*num_rows+13]=0x1fe7e6; // .# #### ###. .### ###. .##.
+ font_data[i*num_rows+14]=0x1fe3c6; // .# #### ###. ..## ##.. .##.
+ font_data[i*num_rows+15]=0x1847c6; // .# #... .#.. .### ##.. .##.
+ font_data[i*num_rows+16]=0x181f86; // .# #... ...# #### #... .##.
+ font_data[i*num_rows+17]=0x187906; // .# #... .### #..# .... .##.
+ font_data[i*num_rows+18]=0x19e07e; // .# #..# ###. .... .### ###.
+ font_data[i*num_rows+19]=0x1981fe; // .# #..# #... ...# #### ###.
+ font_data[i*num_rows+20]=0x182000; // .# #... ..#. .... .... ....
+ font_data[i*num_rows+21]=0x186000; // .# #... .##. .... .... ....
+ font_data[i*num_rows+22]=0x186000; // .# #... .##. .... .... ....
+ font_data[i*num_rows+23]=0x1fe000; // .# #### ###. .... .... ....
+ font_data[i*num_rows+24]=0x1fe000; // .# #### ###. .... .... ....
}
else
{
@@ -294,6 +295,53 @@ void PatchFont(eDvbFont DvbFont)
font_data[i*num_rows+21]=0x1fe000; // .# #### ###. .... .... ....
}
}
+ else if(num_char==134)
+ {
+ if(DvbFont==fontOsd)
+ {
+ font_data[i*num_rows+ 0]=22;
+ font_data[i*num_rows+ 1]=27;
+ font_data[i*num_rows+ 8]=0x00fc00; // .. .... #### ##.. .... ....
+ font_data[i*num_rows+ 9]=0x00fe00; // .. .... #### ###. .... ....
+ font_data[i*num_rows+10]=0x00c300; // .. .... ##.. ..## .... ....
+ font_data[i*num_rows+11]=0x00fffe; // .. .... #### #### #### ###.
+ font_data[i*num_rows+12]=0x1ffffe; // .# #### #### #### #### ###.
+ font_data[i*num_rows+13]=0x1fc006; // .# #### ##.. .... .... .##.
+ font_data[i*num_rows+14]=0x186006; // .# #... .##. .... .... .##.
+ font_data[i*num_rows+15]=0x1fffc6; // .# #### #### #### ##.. .##.
+ font_data[i*num_rows+16]=0x1fffc6; // .# #### #### #### ##.. .##.
+ font_data[i*num_rows+17]=0x1800c6; // .# #... .... .... ##.. .##.
+ font_data[i*num_rows+18]=0x1800c6; // .# #... .... .... ##.. .##.
+ font_data[i*num_rows+19]=0x1800c6; // .# #... .... .... ##.. .##.
+ font_data[i*num_rows+20]=0x1800fe; // .# #... .... .... #### ###.
+ font_data[i*num_rows+21]=0x1800fe; // .# #... .... .... #### ###.
+ font_data[i*num_rows+22]=0x1800c0; // .# #... .... .... ##.. ....
+ font_data[i*num_rows+23]=0x1fffc0; // .# #### #### #### ##.. ....
+ font_data[i*num_rows+24]=0x1fffc0; // .# #### #### #### ##.. ....
+ }
+ else
+ {
+ font_data[i*num_rows+ 0]=22;
+ font_data[i*num_rows+ 1]=22;
+ font_data[i*num_rows+ 5]=0x00fc00; // .. .... #### ##.. .... ....
+ font_data[i*num_rows+ 6]=0x00fe00; // .. .... #### ###. .... ....
+ font_data[i*num_rows+ 7]=0x00c300; // .. .... ##.. ..## .... ....
+ font_data[i*num_rows+ 8]=0x00fffe; // .. .... #### #### #### ###.
+ font_data[i*num_rows+ 9]=0x1ffffe; // .# #### #### #### #### ###.
+ font_data[i*num_rows+10]=0x1fc006; // .# #### ##.. .... .... .##.
+ font_data[i*num_rows+11]=0x186006; // .# #... .##. .... .... .##.
+ font_data[i*num_rows+12]=0x1fffc6; // .# #### #### #### ##.. .##.
+ font_data[i*num_rows+13]=0x1fffc6; // .# #### #### #### ##.. .##.
+ font_data[i*num_rows+14]=0x1800c6; // .# #... .... .... ##.. .##.
+ font_data[i*num_rows+15]=0x1800c6; // .# #... .... .... ##.. .##.
+ font_data[i*num_rows+16]=0x1800c6; // .# #... .... .... ##.. .##.
+ font_data[i*num_rows+17]=0x1800fe; // .# #... .... .... #### ###.
+ font_data[i*num_rows+18]=0x1800fe; // .# #... .... .... #### ###.
+ font_data[i*num_rows+19]=0x1800c0; // .# #... .... .... ##.. ....
+ font_data[i*num_rows+20]=0x1fffc0; // .# #### #### #### ##.. ....
+ font_data[i*num_rows+21]=0x1fffc0; // .# #### #### #### ##.. ....
+ }
+ }
else
{
for(j = 0; j<(int)char_data->height; j++)
@@ -306,3 +354,5 @@ void PatchFont(eDvbFont DvbFont)
}
cFont::SetFont(DvbFont, font_data);
}
+#endif
+
diff --git a/tools.c b/tools.c
index 439051e..a2aa4bf 100644
--- a/tools.c
+++ b/tools.c
@@ -8,15 +8,18 @@
#include <vdr/plugin.h>
#include <vdr/videodir.h>
#include <vdr/recording.h>
+#include <vdr/cutter.h>
#include "tools.h"
#include "mymenusetup.h"
using namespace std;
+extern bool VfatFileSytem;
#define CONFIGFILE "/extrecmenu.sort.conf"
#define BUFFERSIZE 20972 // (2*1024*1024)/100
-MoveBetweenFileSystems MoveThread;
+SortList *mySortList;
+WorkerThread *MoveCutterThread;
string myStrEscape(string S,const char *Chars)
{
@@ -48,20 +51,20 @@ string myStrReplace(string S,char C1,char C2)
// --- SortList ---------------------------------------------------------------
void SortList::ReadConfigFile()
{
- string configfile(cPlugin::ConfigDirectory());
- configfile+=CONFIGFILE;
+ string configfile(cPlugin::ConfigDirectory());
+ configfile+=CONFIGFILE;
- ifstream in(configfile.c_str());
- if(in)
- {
- string buf;
- while(!in.eof())
+ ifstream in(configfile.c_str());
+ if(in)
{
- getline(in,buf);
- if(buf.length()>0)
- Add(new SortListItem(buf.c_str()));
+ string buf;
+ while(!in.eof())
+ {
+ getline(in,buf);
+ if(buf.length()>0)
+ Add(new SortListItem(buf));
+ }
}
- }
}
void SortList::WriteConfigFile()
@@ -75,183 +78,16 @@ void SortList::WriteConfigFile()
outfile << item->Path() << endl;
}
-bool SortList::Find(char *Path)
+bool SortList::Find(string Path)
{
for(SortListItem *item=First();item;item=Next(item))
{
- if(!strcmp(item->Path(),Path))
+ if(item->Path()==Path)
return true;
}
return false;
}
-// --- MoveBetweenFileSystems -------------------------------------------------
-MoveBetweenFileSystems::MoveBetweenFileSystems():cThread("moving files between filesystems")
-{
-}
-
-bool MoveBetweenFileSystems::Start(string OldName,string NewName,cRecording *Recording)
-{
- oldname=OldName;
- newname=NewName;
- recording=Recording;
-
- return cThread::Start();
-}
-
-bool MoveBetweenFileSystems::IsMoving(string Path)
-{
- if(Active())
- {
- if(recording)
- {
- if(Path==oldname)
- return true;
- }
- else
- {
- if(!strncmp(oldname.c_str(),Path.c_str(),oldname.length()))
- return true;
- }
- }
- return false;
-}
-
-bool MoveBetweenFileSystems::Move(string From,string To,cRecording *Recording)
-{
- if(Recording)
- {
- isyslog("[extrecmenu] moving %s to %s",From.c_str(),To.c_str());
-
- DIR *dir;
- struct dirent *entry;
- dir=opendir(From.c_str());
- while((entry=readdir(dir))!=NULL)
- {
- string from,to;
- from=From+'/'+entry->d_name;
- to=To+'/'+entry->d_name;
-
- struct stat st;
- stat(from.c_str(),&st);
- if(S_ISREG(st.st_mode))
- {
- isyslog("[extrecmenu] moving %s",entry->d_name);
-
- time_t copytime=time(NULL);
-
- char buf[BUFFERSIZE];
- int infile=-1,outfile=-1;
- struct stat from_stat;
- ssize_t sz,sz_read=1,sz_write;
-
- if(stat(from.c_str(),&from_stat)!=0 ||
- (infile=open(from.c_str(),O_RDONLY))<0 ||
- (outfile=open(to.c_str(),O_WRONLY|O_CREAT|O_EXCL,from_stat.st_mode))<0)
- {
- if(infile>=0)
- close(infile);
- closedir(dir);
-
- Skins.Message(mtError,strerror(errno));
- return false;
- }
-
- while(sz_read>0 && (sz_read=read(infile,buf,BUFFERSIZE))>0)
- {
- sz_write=0;
- do
- {
- if((sz=write(outfile,buf+sz_write,sz_read-sz_write))<0)
- {
- close(infile);
- close(outfile);
- closedir(dir);
-
- Skins.Message(mtError,tr("Rename/Move failed!"));
- esyslog("[extrecmenu] %s",strerror(errno));
- return false;
- }
- sz_write+=sz;
- }
- while(sz_write<sz_read);
-
- if(mysetup.LimitBandwidth)
- usleep(10);
- }
- close(infile);
- close(outfile);
-
- copytime=time(NULL)-copytime;
- isyslog("[extrecmenu] needed %d secs for %d bytes",(int)copytime,(int)st.st_size);
- }
- }
- closedir(dir);
-
- Recordings.AddByName(To.c_str());
- Recording->Delete();
- Recordings.DelByName(From.c_str());
-
- string buf="move \"";
- buf+=myStrEscape(From,"'\\\"$");
- buf+="\"";
- cRecordingUserCommand::InvokeCommand(buf.c_str(),To.c_str());
- }
- else
- {
- string buf;
- buf=From+'/';
- if(!strncmp(buf.c_str(),To.c_str(),buf.length()))
- {
- Skins.Message(mtError,tr("Moving into own sub-directory not allowed!"));
- return false;
- }
-
- myRecList *list=new myRecList();
- for(cRecording *recording=Recordings.First();recording;recording=Recordings.Next(recording))
- list->Add(new myRecListItem(recording));
-
- myRecListItem *item=list->First();
- while(item)
- {
- if(!strncmp(From.c_str(),item->recording->FileName(),From.length()))
- {
- char *buffer=NULL;
- buffer=strdup(From.c_str()+strlen(VideoDirectory)+1);
- buffer=ExchangeChars(buffer,false);
-
- if(strcmp(item->recording->Name(),buffer))
- {
- buf=To+(item->recording->FileName()+From.length());
- if(!MakeDirs(buf.c_str(),true))
- {
- Skins.Message(mtError,tr("Rename/Move failed!"));
- esyslog("[extrecmenu] %s",strerror(errno));
- free(buffer);
- delete list;
- return false;
- }
- if(Move(item->recording->FileName(),buf,item->recording)==false)
- {
- free(buffer);
- delete list;
- return false;
- }
- }
- free(buffer);
- }
- item=list->Next(item);
- }
- delete list;
- }
- return true;
-}
-
-void MoveBetweenFileSystems::Action()
-{
- Move(oldname,newname,recording);
-}
-
// --- MoveRename -------------------------------------------------------------
// creates the necassery directories and renames the given old name to the new name
bool MoveRename(const char *OldName,const char *NewName,cRecording *Recording,bool Move)
@@ -265,16 +101,23 @@ bool MoveRename(const char *OldName,const char *NewName,cRecording *Recording,bo
{
isyslog("[extrecmenu] moving %s to %s",OldName,NewName);
+ if(!MakeDirs(NewName,true))
+ {
+ Skins.Message(mtError,tr("Creating directories failed!"));
+ return false;
+ }
+
if(rename(OldName,NewName)==-1)
{
remove(NewName); // remove created directory
Skins.Message(mtError,tr("Rename/Move failed!"));
- esyslog("[extrecmenu] %s",strerror(errno));
+ esyslog("[extrecmenu] MoveRename() - rename() - %s",strerror(errno));
return false;
}
+ cThreadLock RecordingsLock(&Recordings);
+ Recordings.DelByName(OldName);
Recordings.AddByName(NewName);
- Recordings.Del(Recording);
// set user command for '-r'-option of VDR
asprintf(&buf,"%s \"%s\"",Move?"move":"rename",*strescape(OldName,"'\\\"$"));
@@ -312,7 +155,6 @@ bool MoveRename(const char *OldName,const char *NewName,cRecording *Recording,bo
if(!MakeDirs(buf,true))
{
Skins.Message(mtError,tr("Creating directories failed!"));
- esyslog("[extrecmenu] %s",strerror(errno));
free(buf);
delete list;
return false;
@@ -338,66 +180,66 @@ bool myRecListItem::SortByName=false;
myRecListItem::myRecListItem(cRecording *Recording)
{
- recording=Recording;
- filename=strdup(recording->FileName());
+ recording=Recording;
+ filename=strdup(recording->FileName());
}
myRecListItem::~myRecListItem()
{
- free(filename);
+ free(filename);
}
char *myRecListItem::StripEpisodeName(char *s)
{
- char *t=s,*s1=NULL,*s2=NULL;
- while(*t)
- {
- if(*t=='/')
+ char *t=s,*s1=NULL,*s2=NULL;
+ while(*t)
{
- if(s1)
- {
- if(s2)
- s1=s2;
- s2=t;
- }
- else
- s1=t;
+ if(*t=='/')
+ {
+ if(s1)
+ {
+ if(s2)
+ s1=s2;
+ s2=t;
+ }
+ else
+ s1=t;
+ }
+ t++;
}
- t++;
- }
- if(mysetup.DescendSorting)
- {
- if(SortByName)
- *s1=1;
- else
- *(s2+1)=255;
- }
- else
- *s1=255;
+ if(mysetup.DescendSorting)
+ {
+ if(SortByName)
+ *s1=1;
+ else
+ *(s2+1)=255;
+ }
+ else
+ *s1=255;
- if(s1&&s2&&!SortByName)
- memmove(s1+1,s2,t-s2+1);
+ if(s1 && s2 && !SortByName)
+ memmove(s1+1,s2,t-s2+1);
- return s;
+ return s;
}
int myRecListItem::Compare(const cListObject &ListObject)const
{
- myRecListItem *item=(myRecListItem*)&ListObject;
+ myRecListItem *item=(myRecListItem*)&ListObject;
- char *s1=StripEpisodeName(strdup(filename+strlen(VideoDirectory)));
- char *s2=StripEpisodeName(strdup(item->filename+strlen(VideoDirectory)));
-
- int compare;
- if(mysetup.DescendSorting)
- compare=strcasecmp(s2,s1);
- else
- compare=strcasecmp(s1,s2);
+ char *s1=StripEpisodeName(strdup(filename+strlen(VideoDirectory)));
+ char *s2=StripEpisodeName(strdup(item->filename+strlen(VideoDirectory)));
+
+ int compare;
+ if(mysetup.DescendSorting)
+ compare=strcasecmp(s2,s1);
+ else
+ compare=strcasecmp(s1,s2);
- free(s1);
- free(s2);
+ free(s1);
+ free(s2);
- return compare;
+ return compare;
}
// --- myRecList --------------------------------------------------------------
@@ -406,3 +248,438 @@ void myRecList::Sort(bool SortByName)
myRecListItem::SortByName=SortByName;
cListBase::Sort();
}
+
+// --- WorkerThread -----------------------------------------------------------
+WorkerThread::WorkerThread():cThread("extrecmenu worker thread")
+{
+ cancelmove=cancelcut=false;
+ CutterQueue=new CutterList();
+ MoveBetweenFileSystemsList=new MoveList();
+
+ Start();
+}
+
+WorkerThread::~WorkerThread()
+{
+ Cancel(3);
+
+ delete CutterQueue;
+ delete MoveBetweenFileSystemsList;
+}
+
+const char *WorkerThread::Working()
+{
+ if(CutterQueue->First()!=NULL)
+ return tr("Cutter queue not empty");
+
+ if(MoveBetweenFileSystemsList->First()!=NULL)
+ return tr("Move recordings in progress");
+
+ return NULL;
+}
+
+void WorkerThread::Action()
+{
+ CutterListItem *cutteritem=NULL;
+ MoveListItem *moveitem=NULL;
+
+ while(Running())
+ {
+ if((cutteritem=CutterQueue->First())!=NULL)
+ {
+ cutteritem->SetCutInProgress();
+
+ // create filename for edited recording, check for recordings with this name, if exists -> delete recording
+ // (based upon VDR's code (cutter.c))
+ cRecording rec(cutteritem->FileName().c_str());
+ const char *editedfilename=rec.PrefixFileName('%');
+ if(editedfilename && RemoveVideoFile(editedfilename) && MakeDirs(editedfilename,true))
+ {
+ char *s=strdup(editedfilename);
+ char *e=strrchr(s,'.');
+ if(e)
+ {
+ if(!strcmp(e,".rec"))
+ {
+ strcpy(e,".del");
+ RemoveVideoFile(s);
+ }
+ }
+ free(s);
+ rec.WriteInfo(); // don't know why, but VDR also does it
+ Recordings.AddByName(editedfilename);
+ cutteritem->SetNewFileName(editedfilename);
+ Cut(cutteritem->FileName(),editedfilename);
+ }
+ else
+ Skins.QueueMessage(mtError,tr("Can't start editing process!"));
+ CutterQueue->Del(cutteritem);
+
+ Recordings.ChangeState();
+ }
+
+ if((moveitem=MoveBetweenFileSystemsList->First())!=NULL)
+ {
+ moveitem->SetMoveInProgress();
+ if(Move(moveitem->From(),moveitem->To()))
+ MoveBetweenFileSystemsList->Del(moveitem);
+ else
+ // error occured -> empty move queue
+ MoveBetweenFileSystemsList->Clear();
+
+ Recordings.ChangeState();
+ }
+
+ sleep(1);
+ }
+}
+
+void WorkerThread::AddToCutterQueue(std::string Path)
+{
+ CutterQueue->Add(new CutterListItem(Path));
+}
+
+bool WorkerThread::IsCutting(string Path)
+{
+ for(CutterListItem *item=CutterQueue->First();item;item=CutterQueue->Next(item))
+ {
+ if(Path==item->FileName() || Path==item->NewFileName())
+ return true;
+ }
+ return false;
+}
+
+void WorkerThread::CancelCut(string Path)
+{
+ for(CutterListItem *item=CutterQueue->First();item;item=CutterQueue->Next(item))
+ {
+ if(item->FileName()==Path || item->NewFileName()==Path)
+ {
+ if(item->GetCutInProgress())
+ cancelcut=true;
+ else
+ CutterQueue->Del(item);
+
+ return;
+ }
+ }
+}
+
+// this based mainly upon VDR's code (cutter.c)
+void WorkerThread::Cut(string From,string To)
+{
+ cUnbufferedFile *fromfile=NULL,*tofile=NULL;
+ cFileName *fromfilename=NULL,*tofilename=NULL;
+ cIndexFile *fromindex=NULL,*toindex=NULL;
+ cMarks frommarks,tomarks;
+ cMark *mark;
+ const char *error=NULL;
+ uchar filenumber,picturetype,buffer[MAXFRAMESIZE];
+ int fileoffset,length,index,currentfilenumber=0,filesize=0,lastiframe=0;
+ bool lastmark=false,cutin=true;
+
+ if(frommarks.Load(From.c_str()) && frommarks.Count())
+ {
+ fromfilename=new cFileName(From.c_str(),false,true);
+ tofilename=new cFileName(To.c_str(),true,false);
+ fromindex=new cIndexFile(From.c_str(),false);
+ toindex=new cIndexFile(To.c_str(),true);
+ tomarks.Load(To.c_str());
+ }
+ else
+ {
+ esyslog("[extrecmenu] no editing marks found for %s",From.c_str());
+ return;
+ }
+
+ if((mark=frommarks.First())!=NULL)
+ {
+ if(!(fromfile=fromfilename->Open()) || !(tofile=tofilename->Open()))
+ return;
+ fromfile->SetReadAhead(MEGABYTE(20));
+ index=mark->position;
+ mark=frommarks.Next(mark);
+ tomarks.Add(0);
+ tomarks.Save();
+ }
+ else
+ {
+ esyslog("[extrecmenu] no editing marks found for %s",From.c_str());
+ return;
+ }
+
+ isyslog("[extecmenu] editing %s",From.c_str());
+ while(fromindex->Get(index++,&filenumber,&fileoffset,&picturetype,&length) && Running() && !cancelcut)
+ {
+ AssertFreeDiskSpace(-1);
+
+ if(filenumber!=currentfilenumber)
+ {
+ fromfile=fromfilename->SetOffset(filenumber,fileoffset);
+ fromfile->SetReadAhead(MEGABYTE(20));
+ currentfilenumber=filenumber;
+ }
+ if(fromfile)
+ {
+ int len=ReadFrame(fromfile,buffer,length,sizeof(buffer));
+ if(len<0)
+ {
+ error="ReadFrame";
+ break;
+ }
+ if(len!=length)
+ {
+ currentfilenumber=0;
+ length=len;
+ }
+ }
+ else
+ {
+ error="fromfile";
+ break;
+ }
+ if(picturetype==I_FRAME)
+ {
+ if(lastmark)
+ break;
+ if(filesize > MEGABYTE(Setup.MaxVideoFileSize))
+ {
+ tofile=tofilename->NextFile();
+ if(!tofile)
+ {
+ error="tofile 1";
+ break;
+ }
+ filesize=0;
+ }
+ lastiframe=0;
+ if(cutin)
+ {
+ cRemux::SetBrokenLink(buffer,length);
+ cutin=false;
+ }
+ }
+ if(tofile->Write(buffer,length)<0)
+ {
+ error="safe_write";
+ break;
+ }
+ if(!toindex->Write(picturetype,tofilename->Number(),filesize))
+ {
+ error="toindex";
+ break;
+ }
+ filesize+=length;
+ if(!lastiframe)
+ lastiframe=toindex->Last();
+
+ if(mark && index >= mark->position)
+ {
+ mark=frommarks.Next(mark);
+ tomarks.Add(lastiframe);
+ if(mark)
+ tomarks.Add(toindex->Last()+1);
+ tomarks.Save();
+ if(mark)
+ {
+ index=mark->position;
+ mark=frommarks.Next(mark);
+ currentfilenumber=0;
+ cutin=true;
+ if(Setup.SplitEditedFiles)
+ {
+ tofile=tofilename->NextFile();
+ if(!tofile)
+ {
+ error="tofile 2";
+ break;
+ }
+ filesize=0;
+ }
+ }
+ else
+ lastmark=true;
+ }
+ }
+ if(!Running() || cancelcut || error)
+ {
+ if(error)
+ esyslog("[extrecmenu] ERROR: '%s' during editing process",error);
+ else
+ isyslog("[extrecmenu] editing process canceled, deleting edited recording");
+
+ cancelcut=false;
+ RemoveVideoFile(To.c_str());
+ Recordings.DelByName(To.c_str());
+ }
+ else
+ {
+ isyslog("[extrecmenu] editing process ended");
+ cRecordingUserCommand::InvokeCommand(RUC_EDITEDRECORDING,To.c_str());
+ }
+ Recordings.TouchUpdate();
+ delete fromfilename;
+ delete tofilename;
+ delete fromindex;
+ delete toindex;
+}
+
+bool WorkerThread::IsMoving(string Path)
+{
+ for(MoveListItem *item=MoveBetweenFileSystemsList->First();item;item=MoveBetweenFileSystemsList->Next(item))
+ {
+ if(Path==item->From() && !item->GetMoveCanceled())
+ return true;
+ }
+ return false;
+}
+
+void WorkerThread::CancelMove(string Path)
+{
+ for(MoveListItem *item=MoveBetweenFileSystemsList->First();item;item=MoveBetweenFileSystemsList->Next(item))
+ {
+ if(Path==item->From())
+ {
+ if(item->GetMoveInProgress())
+ {
+ cancelmove=true;
+ item->SetMoveCanceled();
+ }
+ else
+ MoveBetweenFileSystemsList->Del(item);
+
+ return;
+ }
+ }
+}
+
+void WorkerThread::AddToMoveList(string From,string To)
+{
+ MoveBetweenFileSystemsList->Add(new MoveListItem(From,To));
+ Recordings.ChangeState();
+}
+
+bool WorkerThread::Move(string From,string To)
+{
+ if(!MakeDirs(To.c_str(),true))
+ {
+ Skins.QueueMessage(mtError,tr("Creating directories failed!"));
+ return false;
+ }
+
+ isyslog("[extrecmenu] moving '%s' to '%s'",From.c_str(),To.c_str());
+
+ DIR *dir=NULL;
+ struct dirent *entry;
+ int infile=-1,outfile=-1;
+
+ if((dir=opendir(From.c_str()))!=NULL)
+ {
+ bool ok=true;
+ // copy each file in this dir, except sub-dirs
+ while((entry=readdir(dir))!=NULL)
+ {
+ string from,to;
+ from=From+"/"+entry->d_name;
+ to=To+"/"+entry->d_name;
+
+ AssertFreeDiskSpace(-1);
+
+ struct stat st;
+ if(stat(from.c_str(),&st)==0)
+ {
+ if(S_ISREG(st.st_mode))
+ {
+ isyslog("[extrecmenu] moving '%s'",entry->d_name);
+
+ ssize_t sz,sz_read=1,sz_write;
+ if(stat(from.c_str(),&st)==0 && (infile=open(from.c_str(),O_RDONLY))!=-1 && (outfile=open(to.c_str(),O_WRONLY|O_CREAT|O_EXCL,st.st_mode))!=-1)
+ {
+ char buf[BUFFERSIZE];
+ while(sz_read>0 && (sz_read=read(infile,buf,BUFFERSIZE))>0)
+ {
+ AssertFreeDiskSpace(-1);
+
+ sz_write=0;
+ do
+ {
+ if(cancelmove || !Running())
+ {
+ cancelmove=false;
+
+ close(infile);
+ close(outfile);
+ closedir(dir);
+
+ isyslog("[extrecmenu] moving canceled");
+
+ RemoveVideoFile(To.c_str());
+
+ return true;
+ }
+
+ if((sz=write(outfile,buf+sz_write,sz_read-sz_write))<0)
+ {
+ close(infile);
+ close(outfile);
+ closedir(dir);
+
+ Skins.Message(mtError,tr("Rename/Move failed!"));
+ esyslog("[extrecmenu] WorkerThread::Move() - write() - %s",strerror(errno));
+ return false;
+ }
+ sz_write+=sz;
+ }
+ while(sz_write<sz_read);
+
+ if(mysetup.LimitBandwidth)
+ usleep(10);
+ }
+ close(infile);
+ close(outfile);
+ }
+ else
+ {
+ ok=false;
+ break;
+ }
+ }
+ }
+ else
+ {
+ ok=false;
+ break;
+ }
+ }
+ if(ok)
+ {
+ closedir(dir);
+
+ cThreadLock RecordingsLock(&Recordings);
+ cRecording rec(From.c_str());
+ rec.Delete();
+ Recordings.DelByName(From.c_str());
+ Recordings.AddByName(To.c_str());
+
+ string cmdstring="move \"";
+ cmdstring+=myStrEscape(From,"'\\\"$");
+ cmdstring+="\"";
+ cRecordingUserCommand::InvokeCommand(cmdstring.c_str(),To.c_str());
+
+ Recordings.TouchUpdate();
+
+ return true;
+ }
+ }
+ if(dir)
+ closedir(dir);
+ if(infile!=-1)
+ close(infile);
+ if(outfile!=-1)
+ close(outfile);
+
+ Skins.QueueMessage(mtError,tr("Rename/Move failed!"));
+ esyslog("[extrecmenu] WorkerThread::Move() - %s",strerror(errno));
+ return false;
+}
+
diff --git a/tools.h b/tools.h
index c12b070..66167da 100644
--- a/tools.h
+++ b/tools.h
@@ -5,8 +5,8 @@ class SortListItem:public cListObject
private:
std::string path;
public:
- SortListItem(const char *Path){path=Path;};
- const char *Path(){return path.c_str();}
+ SortListItem(std::string Path){path=Path;};
+ std::string Path(){return path;}
};
class SortList:public cList<SortListItem>
@@ -14,25 +14,10 @@ class SortList:public cList<SortListItem>
public:
void ReadConfigFile();
void WriteConfigFile();
- bool Find(char *Path);
+ bool Find(std::string Path);
};
-class MoveBetweenFileSystems:public cThread
-{
- private:
- std::string oldname;
- std::string newname;
- cRecording *recording;
- bool Move(std::string From,std::string To,cRecording *Recording);
- protected:
- virtual void Action();
- public:
- MoveBetweenFileSystems();
- bool Start(std::string OldName,std::string NewName,cRecording *Recording);
- bool IsMoving(std::string Path);
-};
-
-extern MoveBetweenFileSystems MoveThread;
+extern SortList *mySortList;
bool MoveRename(const char *OldName,const char *NewName,cRecording *Recording,bool Move);
@@ -55,3 +40,75 @@ class myRecList:public cList<myRecListItem>
public:
void Sort(bool SortByName);
};
+
+// --- MoveListItem -----------------------------------------------------------
+class MoveListItem:public cListObject
+{
+ private:
+ bool moveinprogress;
+ bool movecanceled;
+ std::string from;
+ std::string to;
+ public:
+ MoveListItem(std::string From,std::string To){from=From;to=To;moveinprogress=false;movecanceled=false;}
+ std::string From(){return from;}
+ std::string To(){return to;}
+ void SetMoveInProgress(){moveinprogress=true;}
+ bool GetMoveInProgress(){return moveinprogress;}
+ void SetMoveCanceled(){movecanceled=true;}
+ bool GetMoveCanceled(){return movecanceled;}
+};
+
+// --- MoveList ---------------------------------------------------------------
+class MoveList:public cList<MoveListItem>
+{
+};
+
+// --- CutterListItem ---------------------------------------------------------
+class CutterListItem:public cListObject
+{
+ private:
+ bool cutinprogress;
+ std::string filename;
+ std::string newfilename;
+ public:
+ CutterListItem(std::string FileName){filename=FileName;cutinprogress=false;};
+ void SetNewFileName(std::string NewFileName){newfilename=NewFileName;}
+ std::string FileName(){return filename;}
+ std::string NewFileName(){return newfilename;}
+ void SetCutInProgress(){cutinprogress=true;}
+ bool GetCutInProgress(){return cutinprogress;}
+};
+
+// --- CutterList -------------------------------------------------------------
+class CutterList:public cList<CutterListItem>
+{
+};
+
+// --- WorkerThread -----------------------------------------------------------
+class WorkerThread:public cThread
+{
+ private:
+ bool cancelmove,cancelcut;
+ MoveList *MoveBetweenFileSystemsList;
+ CutterList *CutterQueue;
+ void Cut(std::string From,std::string To);
+ bool Move(std::string From,std::string To);
+ protected:
+ virtual void Action();
+ public:
+ WorkerThread();
+ ~WorkerThread();
+ const char *Working();
+ bool IsCutting(std::string Path);
+ bool IsMoving(std::string Path);
+ void CancelCut(std::string Path);
+ void CancelMove(std::string Path);
+ void AddToCutterQueue(std::string Path);
+ void AddToMoveList(std::string From,std::string To);
+ bool IsCutterQueueEmpty(){return CutterQueue->First();}
+ bool IsMoveListEmpty(){return MoveBetweenFileSystemsList->First();}
+};
+
+extern WorkerThread *MoveCutterThread;
+