summaryrefslogtreecommitdiff
path: root/command/marks.cpp
diff options
context:
space:
mode:
authorJochen Dolze <vdr@dolze.de>2010-03-30 18:49:58 +0200
committerJochen Dolze <vdr@dolze.de>2010-03-30 18:49:58 +0200
commit74cdd9ffa1d0e5f74942051e7e22e07542929c03 (patch)
treee59472547b1ed3543b8e2d1d0e2a7c52fcb24c04 /command/marks.cpp
parent6446f24dce1b30fa341b7de078ca4385d1378457 (diff)
downloadvdr-plugin-markad-74cdd9ffa1d0e5f74942051e7e22e07542929c03.tar.gz
vdr-plugin-markad-74cdd9ffa1d0e5f74942051e7e22e07542929c03.tar.bz2
Changed directory structure, added Makefiles
Diffstat (limited to 'command/marks.cpp')
-rw-r--r--command/marks.cpp373
1 files changed, 373 insertions, 0 deletions
diff --git a/command/marks.cpp b/command/marks.cpp
new file mode 100644
index 0000000..543ed0d
--- /dev/null
+++ b/command/marks.cpp
@@ -0,0 +1,373 @@
+/*
+ * marks.cpp: A program for the Video Disk Recorder
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ */
+
+#include "marks.h"
+
+clMark::clMark(int Type, int Position, const char *Comment)
+{
+ type=Type;
+ position=Position;
+ if (Comment)
+ {
+ comment=strdup(Comment);
+ }
+ else
+ {
+ comment=NULL;
+ }
+ prev=NULL;
+ next=NULL;
+}
+
+clMark::~clMark()
+{
+ if (comment) free(comment);
+}
+
+// --------------------------------------------------------------------------
+
+clMarks::~clMarks()
+{
+ clMark *next,*mark=first;
+ while (mark)
+ {
+ next=mark->Next();
+ Del(mark);
+ mark=next;
+ }
+
+}
+
+int clMarks::Count(int Type)
+{
+ if (Type==0xFF) return count;
+
+ if (!first) return 0;
+
+ int ret=0;
+ clMark *mark=first;
+ while (mark)
+ {
+ if (mark->type==Type) ret++;
+ mark=mark->Next();
+ }
+ return ret;
+}
+
+void clMarks::Del(int Type)
+{
+ if (!first) return; // no elements yet
+
+ clMark *next,*mark=first;
+ while (mark)
+ {
+ next=mark->Next();
+ if (mark->type==Type) Del(mark);
+ mark=next;
+ }
+}
+
+void clMarks::Del(clMark *Mark)
+{
+ if (!Mark) return;
+
+ if (first==Mark)
+ {
+ // we are the first mark
+ first=Mark->Next();
+ }
+ else
+ {
+ if (Mark->Next() && (Mark->Prev()))
+ {
+ // there is a next and prev object
+ Mark->Prev()->SetNext(Mark->Next());
+ Mark->Next()->SetPrev(Mark->Prev());
+ }
+ else
+ {
+ // we are the last
+ Mark->Prev()->SetNext(NULL);
+ }
+ }
+ delete Mark;
+ count--;
+}
+
+clMark *clMarks::Get(int Position)
+{
+ if (!first) return NULL; // no elements yet
+
+ clMark *mark=first;
+ while (mark)
+ {
+ if (Position==mark->position) break;
+ mark=mark->Next();
+ }
+ return mark;
+}
+
+clMark *clMarks::GetPrev(int Position, int Type)
+{
+ if (!first) return NULL; // no elements yet
+
+ clMark *mark=first;
+ while (mark)
+ {
+ if (Type==0xFF)
+ {
+ if (mark->position>=Position) break;
+ }
+ else
+ {
+ if ((mark->position>=Position) && (mark->type==Type)) break;
+ }
+ mark=mark->Next();
+ }
+ if (mark) return mark->Prev();
+ return last;
+}
+
+clMark *clMarks::GetNext(int Position, int Type)
+{
+ if (!first) return NULL; // no elements yet
+ clMark *mark=first;
+ while (mark)
+ {
+ if (Type==0xFF)
+ {
+ if (mark->position>=Position) break;
+ }
+ else
+ {
+ if ((mark->position>=Position) && (mark->type==Type)) break;
+ }
+ mark=mark->Next();
+ }
+ return mark->Next();
+}
+
+clMark *clMarks::Add(int Type, int Position,const char *Comment)
+{
+ clMark *newmark;
+ if ((newmark=Get(Position)))
+ {
+ if ((newmark->comment) && (Comment))
+ {
+ free(newmark->comment);
+ newmark->comment=strdup(Comment);
+ }
+ newmark->type=Type;
+ return newmark;
+ }
+
+ newmark=new clMark(Type, Position,Comment);
+ if (!newmark) return NULL;
+
+ if (!first)
+ {
+ //first element
+ first=last=newmark;
+ count++;
+ return newmark;
+ }
+ else
+ {
+ clMark *mark=first;
+ while (mark)
+ {
+ if (!mark->Next())
+ {
+ if (Position>mark->position)
+ {
+ // add as last element
+ newmark->Set(mark,NULL);
+ mark->SetNext(newmark);
+ last=newmark;
+ break;
+ }
+ else
+ {
+ // add before
+ if (!mark->Prev())
+ {
+ // add as first element
+ newmark->Set(NULL,mark);
+ mark->SetPrev(newmark);
+ first=newmark;
+ break;
+ }
+ else
+ {
+ newmark->Set(mark->Prev(),mark);
+ mark->SetPrev(newmark);
+ break;
+ }
+ }
+ }
+ else
+ {
+ if ((Position>mark->position) && (Position<mark->Next()->position))
+ {
+ // add between two marks
+ newmark->Set(mark,mark->Next());
+ mark->SetNext(newmark);
+ break;
+ }
+ }
+ mark=mark->Next();
+ }
+ if (!mark)return NULL;
+ count++;
+ return newmark;
+ }
+ return NULL;
+}
+
+char *clMarks::IndexToHMSF(int Index, double FramesPerSecond)
+{
+ if (FramesPerSecond==0.0) return NULL;
+ char *buf=NULL;
+ double Seconds;
+ int f = int(modf((Index+0.5)/FramesPerSecond,&Seconds)*FramesPerSecond+1);
+ int s = int(Seconds);
+ int m = s / 60 % 60;
+ int h = s / 3600;
+ s %= 60;
+ if (asprintf(&buf,"%d:%02d:%02d.%02d",h,m,s,f)==-1) return NULL;
+ return buf;
+}
+
+bool clMarks::CheckIndex(const char *Directory, bool isTS, bool *IndexError)
+{
+ if (!IndexError) return false;
+ *IndexError=false;
+
+ if (!first) return true;
+
+ char *ipath=NULL;
+ if (asprintf(&ipath,"%s/index%s",Directory,isTS ? "" : ".vdr")==-1) return false;
+
+ int fd=open(ipath,O_RDONLY);
+ free(ipath);
+ if (fd==-1) return false;
+
+ clMark *mark=first;
+ while (mark)
+ {
+ if (isTS)
+ {
+ off_t offset = mark->position * sizeof(struct tIndexTS);
+ if (lseek(fd,offset,SEEK_SET)!=offset)
+ {
+ *IndexError=true;
+ break;
+ }
+ struct tIndexTS IndexTS;
+ if (read(fd,&IndexTS,sizeof(IndexTS))!=sizeof(IndexTS))
+ {
+ *IndexError=true;
+ break;
+ }
+ if (!IndexTS.independent)
+ {
+ *IndexError=true;
+ break;
+ }
+ }
+ else
+ {
+ off_t offset = mark->position * sizeof(struct tIndexVDR);
+ if (lseek(fd,offset,SEEK_SET)!=offset)
+ {
+ *IndexError=true;
+ break;
+ }
+ struct tIndexVDR IndexVDR;
+ if (read(fd,&IndexVDR,sizeof(IndexVDR))!=sizeof(IndexVDR))
+ {
+ *IndexError=true;
+ break;
+ }
+ if (IndexVDR.type!=1)
+ {
+ *IndexError=true;
+ break;
+ }
+ }
+ mark=mark->Next();
+ }
+
+ return true;
+}
+
+bool clMarks::Backup(const char *Directory, bool isTS)
+{
+ char *fpath=NULL;
+ if (asprintf(&fpath,"%s/%s%s",Directory,filename,isTS ? "" : ".vdr")==-1) return false;
+
+ // make backup of old marks, filename convention taken from noad
+ char *bpath=NULL;
+ if (asprintf(&bpath,"%s/%s0%s",Directory,filename,isTS ? "" : ".vdr")==-1)
+ {
+ free(fpath);
+ return false;
+ }
+
+ int ret=rename(fpath,bpath);
+ free(bpath);
+ free(fpath);
+ return (ret==0);
+}
+
+bool clMarks::Save(const char *Directory, double FrameRate, bool isTS)
+{
+ if (!first) return false;
+ if (savedcount==count) return false;
+
+ char *fpath=NULL;
+ if (asprintf(&fpath,"%s/%s%s",Directory,filename,isTS ? "" : ".vdr")==-1) return false;
+
+ FILE *mf;
+ mf=fopen(fpath,"w+");
+
+ if (!mf)
+ {
+ free(fpath);
+ return false;
+ }
+
+ clMark *mark=first;
+ while (mark)
+ {
+ char *buf=IndexToHMSF(mark->position,FrameRate);
+ if (buf)
+ {
+ fprintf(mf,"%s %s\n",buf,mark->comment ? mark->comment : "");
+ free(buf);
+ }
+ mark=mark->Next();
+ }
+ fclose(mf);
+
+ if (getuid()==0 || geteuid()!=0)
+ {
+ // if we are root, set fileowner to owner of 001.vdr/00001.ts file
+ char *spath=NULL;
+ if (asprintf(&spath,"%s/%s",Directory,isTS ? "00001.ts" : "001.vdr")!=-1)
+ {
+ struct stat statbuf;
+ if (!stat(spath,&statbuf))
+ {
+ chown(fpath,statbuf.st_uid, statbuf.st_gid);
+ }
+ free(spath);
+ }
+ }
+ free(fpath);
+ return true;
+}