diff options
author | Martin Prochnow <nordlicht@martins-kabuff.de> | 2007-02-04 23:31:11 +0100 |
---|---|---|
committer | Andreas Mair <andreas@vdr-developer.org> | 2007-02-04 23:31:11 +0100 |
commit | 8adfaaf81b104b8e981026da593e40f9d780c251 (patch) | |
tree | 0a72c71d85e1d5bbac8729cefa9e41ec9e58758b /tools.c | |
parent | 074a396ce9f5c5239dd790c6566e0f19dff45f59 (diff) | |
download | vdr-plugin-extrecmenu-8adfaaf81b104b8e981026da593e40f9d780c251.tar.gz vdr-plugin-extrecmenu-8adfaaf81b104b8e981026da593e40f9d780c251.tar.bz2 |
Version 0.13v0.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
- 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)
* prevent editing of recordings that are moved
* marker for recordings, that are moved
- added marker for cutting and moving recording entries
- added marker to title bar for cutting and moving recordings
- recording info menu shows additional informations (name, path, channel, size, lifetime, priority)
- added setup option to select between plugin's and VDR's recording info menu
- dvd.vdr is ignored, as long as a 001.vdr is present
- fixed following issue (again): if there are more then one recording with the same name, only one of it is shown if all recording details are hidden
Diffstat (limited to 'tools.c')
-rw-r--r-- | tools.c | 329 |
1 files changed, 266 insertions, 63 deletions
@@ -2,13 +2,48 @@ * See the README file for copyright information and how to reach the author. */ +#include <string> +#include <fstream> +#include <iostream> #include <vdr/plugin.h> #include <vdr/videodir.h> #include <vdr/recording.h> #include "tools.h" #include "mymenusetup.h" +using namespace std; + #define CONFIGFILE "/extrecmenu.sort.conf" +#define BUFFERSIZE 20972 // (2*1024*1024)/100 + +MoveBetweenFileSystems MoveThread; + +string myStrEscape(string S,const char *Chars) +{ + int i=0; + while(Chars[i]!=0) + { + string::size_type j=0; + while((j=S.find(Chars[i],j))!=string::npos) + { + S.insert(j,1,'\\'); + j+=2; + } + i++; + } + return S; +} + +string myStrReplace(string S,char C1,char C2) +{ + string::size_type i=0; + while((i=S.find(C1,i))!=string::npos) + { + S.replace(i,1,1,C2); + i++; + } + return S; +} // --- SortList --------------------------------------------------------------- void SortList::ReadConfigFile() @@ -50,84 +85,252 @@ bool SortList::Find(char *Path) return false; } -// --- 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) +// --- MoveBetweenFileSystems ------------------------------------------------- +MoveBetweenFileSystems::MoveBetweenFileSystems():cThread("moving files between filesystems") { - char *buf=NULL; +} - // is OldName different to NewName - if(!strcmp(OldName,NewName)) - return true; +bool MoveBetweenFileSystems::Start(string OldName,string NewName,cRecording *Recording) +{ + oldname=OldName; + newname=NewName; + recording=Recording; + + return cThread::Start(); +} - // move/rename a recording - if(Recording) - { - if(!MakeDirs(NewName,true)) +bool MoveBetweenFileSystems::IsMoving(string Path) +{ + if(Active()) { - Skins.Message(mtError,tr("Creating directories failed!")); - return false; + if(recording) + { + if(Path==oldname) + return true; + } + else + { + if(!strncmp(oldname.c_str(),Path.c_str(),oldname.length())) + return true; + } } - isyslog("[extrecmenu] moving %s to %s",OldName,NewName); - - if(rename(OldName,NewName)==-1) + return false; +} + +bool MoveBetweenFileSystems::Move(string From,string To,cRecording *Recording) +{ + if(Recording) { - esyslog("[extrecmenu] %s",strerror(errno)); - Skins.Message(mtError,tr("Rename/Move failed!")); - return false; + 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()); } - - // set user command for '-r'-option of VDR - asprintf(&buf,"%s \"%s\"",Move?"move":"rename",*strescape(OldName,"'\\\"$")); - cRecordingUserCommand::InvokeCommand(buf,NewName); - free(buf); - - // update recordings list - Recordings.AddByName(NewName); - Recordings.Del(Recording); - } - // move/rename a directory - else - { - // is the new path within the old? - asprintf(&buf,"%s/",OldName); // we have to append a / to make sure that we search for a directory - if(!strncmp(buf,NewName,strlen(buf))) + else { - Skins.Message(mtError,tr("Moving into own sub-directory not allowed!")); - free(buf); - return false; + 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; } - free(buf); - - // build my own recordings list - myRecList *list=new myRecList(); - for(cRecording *recording=Recordings.First();recording;recording=Recordings.Next(recording)) - list->Add(new myRecListItem(recording)); + 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) +{ + char *buf=NULL; + + if(!strcmp(OldName,NewName)) + return true; - myRecListItem *item=list->First(); - while(item) + if(Recording) { - // find recordings within the path of OldName - if(!strncmp(OldName,item->recording->FileName(),strlen(OldName))) - { - buf=strdup(OldName+strlen(VideoDirectory)+1); - buf=ExchangeChars(buf,false); - - // exclude recordings with the same name as OldName - if(strcmp(item->recording->Name(),buf)) + isyslog("[extrecmenu] moving %s to %s",OldName,NewName); + + if(rename(OldName,NewName)==-1) { - free(buf); - asprintf(&buf,"%s%s",NewName,item->recording->FileName()+strlen(OldName)); - // move/rename the recording - MoveRename(item->recording->FileName(),buf,item->recording,Move); + remove(NewName); // remove created directory + Skins.Message(mtError,tr("Rename/Move failed!")); + esyslog("[extrecmenu] %s",strerror(errno)); + return false; } + + Recordings.AddByName(NewName); + Recordings.Del(Recording); + + // set user command for '-r'-option of VDR + asprintf(&buf,"%s \"%s\"",Move?"move":"rename",*strescape(OldName,"'\\\"$")); + cRecordingUserCommand::InvokeCommand(buf,NewName); free(buf); - } - item=list->Next(item); } - delete list; - } - return true; + else + { + // is the new path within the old? + asprintf(&buf,"%s/",OldName); // we have to append a / to make sure that we search for a directory + if(!strncmp(buf,NewName,strlen(buf))) + { + Skins.Message(mtError,tr("Moving into own sub-directory not allowed!")); + free(buf); + return false; + } + free(buf); + + 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(OldName,item->recording->FileName(),strlen(OldName))) + { + buf=strdup(OldName+strlen(VideoDirectory)+1); + buf=ExchangeChars(buf,false); + + if(strcmp(item->recording->Name(),buf)) + { + free(buf); + asprintf(&buf,"%s%s",NewName,item->recording->FileName()+strlen(OldName)); + if(!MakeDirs(buf,true)) + { + Skins.Message(mtError,tr("Creating directories failed!")); + esyslog("[extrecmenu] %s",strerror(errno)); + free(buf); + delete list; + return false; + } + if(MoveRename(item->recording->FileName(),buf,item->recording,Move)==false) + { + free(buf); + delete list; + return false; + } + } + free(buf); + } + item=list->Next(item); + } + delete list; + } + return true; } // --- myRecListItem ---------------------------------------------------------- |