summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjaromil <jaromil@949728d9-16ea-0310-a75c-cbdf8430a4b8>2006-03-14 13:55:15 (GMT)
committer jaromil <jaromil@949728d9-16ea-0310-a75c-cbdf8430a4b8>2006-03-14 13:55:15 (GMT)
commit01857e9c23bee6e460dd683fcf285413422bf5f0 (patch)
treec5af5be31718f2a4dd7c8aa6e64987bddc95170a
parentba18f1e1ec7be0587c3930ff2382bfd5b5a90e9a (diff)
linklist class now included,
fseek64 used (POSIX X/Open conformancy, see lfs64) git-svn-id: svn://dyne.org/montevideo/ivysync@61 949728d9-16ea-0310-a75c-cbdf8430a4b8
-rw-r--r--decoder.cpp10
-rw-r--r--decoder.h19
-rw-r--r--linklist.cpp450
-rw-r--r--linklist.h110
4 files changed, 577 insertions, 12 deletions
diff --git a/decoder.cpp b/decoder.cpp
index b128d2f..78814a6 100644
--- a/decoder.cpp
+++ b/decoder.cpp
@@ -250,7 +250,7 @@ void Decoder::run() {
// } else
// filesize = moviestat.st_size;
- playlist_fd = fopen( movie->name, "rb" );
+ playlist_fd = fopen64( movie->name, "rb" );
if(!playlist_fd) {
E("can't open %s: %s (%i)", movie->name, strerror(errno), errno);
@@ -272,11 +272,11 @@ void Decoder::run() {
N("now playing %s",movie->name);
// read the total length of movie file
- fseek(playlist_fd, 0L, SEEK_END);
- filesize = ftell(playlist_fd);
+ fseeko64(playlist_fd, 0L, SEEK_END);
+ filesize = ftello64(playlist_fd);
// set position at the beginning
filepos = 0L;
- fseek(playlist_fd, filepos, SEEK_SET);
+ fseeko64(playlist_fd, filepos, SEEK_SET);
//////////////////////////////////////
// ??? or should we use:
@@ -378,7 +378,7 @@ void Decoder::flush() {
// if there is a seek to do, do it now
if((newfilepos > 0L) && playlist_fd) {
D("seeking to new position %lu", newfilepos);
- fseek(playlist_fd, newfilepos, SEEK_SET);
+ fseeko64(playlist_fd, newfilepos, SEEK_SET);
filepos = newfilepos;
newfilepos = 0;
}
diff --git a/decoder.h b/decoder.h
index 56b53b2..8e1492a 100644
--- a/decoder.h
+++ b/decoder.h
@@ -23,6 +23,15 @@
#ifndef __DECODER_H__
#define __DECODER_H__
+// for large file support (64bit file offsets)
+#define _LARGEFILE_SOURCE 1
+
+/* On many architectures both off_t and long are 32-bit types, but
+ compilation with #define _FILE_OFFSET_BITS 64 will turn off_t into
+ a 64-bit type. - see man fseeko(3) */
+#define _FILE_OFFSET_BITS 64
+
+
#include <iostream>
#include <pthread.h>
#include <inttypes.h>
@@ -30,10 +39,6 @@
#include <linklist.h>
#include <thread.h>
-/* On many architectures both off_t and long are 32-bit types, but
- compilation with #define _FILE_OFFSET_BITS 64 will turn off_t into
- a 64-bit type. - see man fseeko(3) */
-#define _FILE_OFFSET_BITS 64
// playmode values
@@ -108,9 +113,9 @@ class Decoder : public Thread, public Entry {
void flush();
- uint64_t filesize; // current file playing, size in bytes
- uint64_t filepos; // current file playing, position in bytes
- uint64_t newfilepos; // new position to skip in file
+ off64_t filesize; // current file playing, size in bytes
+ off64_t filepos; // current file playing, position in bytes
+ off64_t newfilepos; // new position to skip in file
int fd;
FILE *playlist_fd;
diff --git a/linklist.cpp b/linklist.cpp
new file mode 100644
index 0000000..4c6d1b4
--- /dev/null
+++ b/linklist.cpp
@@ -0,0 +1,450 @@
+/* C++ Linked list class, threadsafe (boolean is atom)
+ *
+ * (c) Copyright 2001-2004 Denis Roio aka jaromil <jaromil@dyne.org>
+ *
+ * This source code is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Public License as published
+ * by the Free Software Foundation; either version 2 of the License,
+ * or (at your option) any later version.
+ *
+ * This source code is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * Please refer to the GNU Public License for more details.
+ *
+ * You should have received a copy of the GNU Public License along with
+ * this source code; if not, write to:
+ * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * "$Id: linklist.cpp 274 2005-05-04 13:29:10Z kysucix $"
+ *
+ -------------------------------------------------------------------------
+ linked list container class
+
+ NOTE: add and rem don't take care of deleting pointers
+ that has to be done by the process that creates them and
+ knows which inheriting class they are (delete is done in main)
+*/
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <utils.h>
+#include <linklist.h>
+
+
+Linklist::Linklist() {
+ length = 0;
+ first = NULL;
+ last = NULL;
+#ifdef THREADSAFE
+ pthread_mutex_init(&mutex,NULL);
+#endif
+
+// unlock();
+}
+
+Linklist::~Linklist() {
+ clear();
+}
+
+/* adds one element at the end of the list */
+void Linklist::append(Entry *addr) {
+ Entry *ptr = NULL;
+ if(!addr) {
+ W("Linklist::append called with NULL argument");
+ return;
+ }
+ if(addr->list) addr->rem();
+#ifdef THREADSAFE
+ lock();
+#endif
+
+ if(!last) { /* that's the first entry */
+ last = addr;
+ last->next = NULL;
+ last->prev = NULL;
+ first = last;
+ } else { /* add the entry to the end */
+ ptr = last;
+ ptr->next = addr;
+ addr->next = NULL;
+ addr->prev = ptr;
+ last = addr;
+ }
+ /* save the pointer to this list */
+ addr->list = this;
+ length++;
+#ifdef THREADSAFE
+ unlock();
+#endif
+}
+
+void Linklist::prepend(Entry *addr) {
+ Entry *ptr = NULL;
+ if(addr->list) addr->rem();
+#ifdef THREADSAFE
+ lock();
+#endif
+
+ if(!first) { /* that's the first entry */
+ first = addr;
+ first->next = NULL;
+ first->prev = NULL;
+ last = first;
+ } else { /* add an entry to the beginning */
+ ptr = first;
+ ptr->prev = addr;
+ addr->next = ptr;
+ addr->prev = NULL;
+ first = addr;
+ }
+ addr->list = this;
+ length++;
+#ifdef THREADSAFE
+ unlock();
+#endif
+}
+
+
+// inserts an element after the given one
+void Linklist::insert_after(Entry *addr, Entry *pos) {
+
+ // take it out from other lists
+ if(addr->list) addr->rem();
+
+#ifdef THREADSAFE
+ lock();
+#endif
+ if(pos->next) {
+ pos->next->prev = addr;
+ addr->next = pos->next;
+ } else last = addr; // it's the last
+
+ addr->prev = pos;
+ pos->next = addr;
+
+ length++;
+ addr->list = this;
+
+#ifdef THREADSAFE
+ unlock();
+#endif
+}
+
+
+/* adds an element at the position specified
+ if pos is out of bounds adds it at the beginning or the end
+ the element occupying allready the position slides down
+ THIS FUNCTION IS NOT YET RELIABLE
+*/
+void Linklist::insert(Entry *addr, int pos) {
+ if(length<=pos) { /* adds it at the end */
+ append(addr);
+ return;
+ } else if(pos<=1) {
+ prepend(addr);
+ return;
+ }
+
+ if(addr->list) addr->rem();
+
+ Entry *ptr = pick(pos);
+
+#ifdef THREADSAFE
+ lock();
+#endif
+ ptr->prev->next = addr;
+ addr->prev = ptr->prev;
+
+ ptr->prev = addr;
+ addr->next = ptr;
+
+ length++;
+ addr->list = this;
+#ifdef THREADSAFE
+ unlock();
+#endif
+}
+
+/* clears the list
+ i don't delete filters here because they have to be deleted
+ from the procedure creating them. so this call simply discards
+ the pointers stored into the linked list. OBJECTS ARE NOT FREED */
+void Linklist::clear() {
+#ifdef THREADSAFE
+ lock();
+#endif
+ sel(0);
+ length = 0;
+ first = NULL;
+ last = NULL;
+#ifdef THREADSAFE
+ unlock();
+#endif
+}
+
+/* takes one element from the list
+ === STARTING FROM 1 ===
+ returns NULL if called with pos=0 or pos>length
+ returns Entry pointer otherwise
+ this function is then overloading the operator[]
+*/
+Entry *Linklist::pick(int pos) {
+ if((length<pos)||(pos<1)) return(NULL);
+ if(pos==1) return(first);
+ if(pos==length) return(last);
+
+ Entry *ptr = first;
+ register int c;
+ for(c=1;c<pos;c++) {
+ if(!ptr) break;
+ ptr = ptr->next;
+ }
+
+ return(ptr);
+}
+
+/* search the linklist for the entry matching *name
+ returns the Entry* on success, NULL on failure */
+Entry *Linklist::search(char *name) {
+ Entry *ptr = first;
+ while(ptr) {
+ if( strcasecmp(ptr->name,name)==0 ) break;
+ ptr = ptr->next;
+ }
+ return(ptr);
+}
+/* searches all the linklist for entries starting with *needle
+ returns a list of indexes where to reach the matches */
+int *Linklist::completion(char *needle) {
+ register int c;
+ int found;
+ int len = strlen(needle);
+
+ /* cleanup */
+ memset(compbuf,0,MAX_COMPLETION);
+
+ /* check it */
+ Entry *ptr = first;
+ if(!ptr) return compbuf;
+
+ for( found=0, c=1 ; ptr ; c++ , ptr=ptr->next ) {
+ if(!len) { // 0 lenght needle: return the full list
+ compbuf[found] = c;
+ found++;
+ } else if( strncasecmp(needle,ptr->name,len)==0 ) {
+ compbuf[found] = c;
+ found++;
+ }
+ }
+
+ D("completion found %i hits",found);
+ return compbuf;
+}
+
+
+/* this function is a wrapper around Entry::up()
+ better to use that if you have a pointer to your Entry */
+bool Linklist::moveup(int pos) {
+ Entry *p = pick(pos);
+ if(!p) return(false);
+ return( p->up() );
+}
+bool Linklist::movedown(int pos) {
+ Entry *p = pick(pos);
+ if(!p) return(false);
+ return( p->down() );
+}
+bool Linklist::moveto(int num, int pos) {
+ Entry
+ *p = pick(num);
+ if(!p) return(false);
+ return( p->move(pos) );
+}
+/* removes one element from the list */
+void Linklist::rem(int pos) {
+ Entry *ptr = pick(pos);
+ if(ptr==NULL) return;
+ ptr->rem();
+}
+
+/* selects ONLY ONE, deselects the others
+ use Entry::sel() if you want to do multiple selects */
+void Linklist::sel(int pos) {
+ int c;
+ Entry *ptr = last;
+
+ if(pos>length) return;
+
+ for(c=length;c>0;c--) {
+ if(c==pos) ptr->sel(true);
+ else ptr->sel(false);
+ ptr = ptr->prev;
+ }
+}
+
+/* returns the last one selected
+ this is supposed to be used with single selections */
+Entry *Linklist::selected() {
+ int c;
+ Entry *ptr = last;
+ for(c=length;c>0;c--) {
+ if(ptr->select) return ptr;
+ ptr = ptr->prev;
+ }
+ return NULL;
+}
+
+Entry::Entry() {
+ next = NULL;
+ prev = NULL;
+ list = NULL;
+ data = NULL;
+ select = false;
+ strcpy(name,"noname");
+}
+
+Entry::~Entry() {
+ rem();
+ if(data) free(data);
+}
+
+void Entry::set_name(char *nn) {
+ strncpy(name,nn,MAX_ENTRY_NAME-1);
+}
+
+bool Entry::up() {
+ if(!prev || !list) return(false);
+#ifdef THREADSAFE
+ list->lock();
+#endif
+
+ Entry *tprev = prev,
+ *tnext = next,
+ *pp = prev->prev;
+
+ if(!next)
+ list->last = prev;
+
+ if(tnext)
+ tnext->prev = tprev;
+
+ next = tprev;
+ prev = pp;
+ tprev->next = tnext;
+ tprev->prev = this;
+
+ if(pp)
+ pp->next = this;
+
+ if(!prev)
+ list->first = this;
+
+#ifdef THREADSAFE
+ list->unlock();
+#endif
+ return(true);
+}
+
+bool Entry::down() {
+ if(!next || !list) return(false);
+#ifdef THREADSAFE
+ list->lock();
+#endif
+
+ Entry *tprev = prev,
+ *tnext = next,
+ *nn = next->next;
+
+ if(!prev)
+ list->first = next;
+
+ if(tprev)
+ tprev->next = tnext;
+
+ prev = tnext;
+ next = nn;
+ tnext->prev = tprev;
+ tnext->next = this;
+ if(nn)
+ nn->prev = this;
+
+ if(!next)
+ list->last = this;
+
+#ifdef THREADSAFE
+ list->unlock();
+#endif
+ return(true);
+}
+
+bool Entry::move(int pos) {
+ D("Entry::move(%i) - NEW LINKLIST MOVE, TRYING IT...");
+ if(!list) return(false);
+#ifdef THREADSAFE
+ list->lock();
+#endif
+
+ Entry *tn, *tp;
+
+ Entry *swapping = list->pick(pos);
+ if(swapping == this) return(true);
+ if(!swapping) return(false);
+
+ tn = swapping->next;
+ tp = swapping->prev;
+
+ swapping->next = next;
+ swapping->prev = prev;
+ if(next) next->prev = swapping;
+ else list->last = swapping;
+ if(prev) prev->next = swapping;
+ else list->first = swapping;
+
+ next = tn;
+ prev = tp;
+ if(next) next->prev = this;
+ else list->last = this;
+ if(prev) prev->next = this;
+ else list->first = this;
+
+#ifdef THREADSAFE
+ list->unlock();
+#endif
+ D("LINKLIST MOVE RETURNS SUCCESS");
+
+ return(true);
+}
+
+void Entry::rem() {
+ bool lastone = false;
+ if(!list) return;
+#ifdef THREADSAFE
+ list->lock();
+#endif
+
+ if(next) { // if there is a next
+ next->prev = prev; // link it to the previous
+ next->select = select; // inherit selection
+ } else {
+ list->last = prev; // else just make it the last
+ lastone = true;
+ }
+
+ if(prev) { // if there is a previous
+ prev->next = next; // link it to the next
+ if(lastone) prev->select = select;
+ } else list->first = next; // else just make it a first
+
+ list->length--;
+#ifdef THREADSAFE
+ list->unlock();
+#endif
+
+ list = NULL;
+}
+
+void Entry::sel(bool on) {
+ select = on;
+}
diff --git a/linklist.h b/linklist.h
new file mode 100644
index 0000000..db030e5
--- /dev/null
+++ b/linklist.h
@@ -0,0 +1,110 @@
+/* C++ Linked list class, threadsafe (boolean is atom)
+ *
+ * (c) Copyright 2001 Denis Roio aka jaromil <jaromil@dyne.org>
+ *
+ * This source code is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Public License as published
+ * by the Free Software Foundation; either version 2 of the License,
+ * or (at your option) any later version.
+ *
+ * This source code is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * Please refer to the GNU Public License for more details.
+ *
+ * You should have received a copy of the GNU Public License along with
+ * this source code; if not, write to:
+ * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __linklist_h__
+#define __linklist_h__
+
+
+// uncomment to have mutex locked operations
+// can be slow on OSX and adds dependency to pthreads
+//#define THREADSAFE 1
+#ifdef THREADSAFE
+#include <pthread.h>
+#endif
+
+// maximum lenght of names
+#define MAX_ENTRY_NAME 512
+
+// maximum number of members returned by the completion
+#define MAX_COMPLETION 256
+
+class Entry;
+
+class Linklist {
+ public:
+ Linklist();
+ virtual ~Linklist();
+
+ Entry *begin() { return(first); };
+ Entry *end() { return(last); };
+ int len() { return(length); };
+
+ void append(Entry *addr);
+ void add(Entry *addr) { append(addr); }; /* lazy backward compatibility */
+ void prepend(Entry *addr);
+ void insert(Entry *addr, int pos);
+ void insert_after(Entry *addr, Entry *pos);
+ void rem(int pos);
+ void sel(int pos);
+ void clear();
+ bool moveup(int pos);
+ bool movedown(int pos);
+ bool moveto(int num, int pos);
+ Entry *pick(int pos);
+ Entry *search(char *name);
+ int *completion(char *needle);
+
+ Entry *Linklist::selected();
+
+ Entry *operator[](int pos) { return pick(pos); };
+
+ /* don't touch these directly */
+ Entry *first;
+ Entry *last;
+ int length;
+
+
+#ifdef THREADSAFE
+ pthread_mutex_t mutex;
+ void lock() { pthread_mutex_lock(&mutex); };
+ void unlock() { pthread_mutex_unlock(&mutex); };
+#endif
+
+ int compbuf[MAX_COMPLETION]; // maximum completion listsize allowed
+
+};
+
+class Entry {
+ friend class Linklist;
+
+ public:
+ Entry();
+ ~Entry();
+
+ void set_name(char *nn);
+
+ Entry *next;
+ Entry *prev;
+
+ Linklist *list;
+
+ bool up();
+ bool down();
+ bool move(int pos);
+ void rem();
+ void sel(bool on);
+
+ bool select;
+
+ char name[MAX_ENTRY_NAME];
+
+ void *data; ///< generic data pointer
+};
+
+#endif