diff options
Diffstat (limited to 'libs/pbd3/pbd')
52 files changed, 4645 insertions, 0 deletions
diff --git a/libs/pbd3/pbd/.DS_Store b/libs/pbd3/pbd/.DS_Store Binary files differnew file mode 100644 index 0000000000..5008ddfcf5 --- /dev/null +++ b/libs/pbd3/pbd/.DS_Store diff --git a/libs/pbd3/pbd/.cvsignore b/libs/pbd3/pbd/.cvsignore new file mode 100644 index 0000000000..67020331ba --- /dev/null +++ b/libs/pbd3/pbd/.cvsignore @@ -0,0 +1 @@ +version.h diff --git a/libs/pbd3/pbd/abstract_ui.h b/libs/pbd3/pbd/abstract_ui.h new file mode 100644 index 0000000000..0c845c15cd --- /dev/null +++ b/libs/pbd3/pbd/abstract_ui.h @@ -0,0 +1,67 @@ +/* + Copyright (C) 1998-99 Paul Barton-Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __pbd_abstract_ui_h__ +#define __pbd_abstract_ui_h__ + +#include <pbd/receiver.h> +#include <sigc++/sigc++.h> + +class Touchable; + +class AbstractUI : public Receiver +{ + public: + enum RequestType { + ErrorMessage, + Quit, + CallSlot, + CallSlotLocked, + TouchDisplay, + StateChange, + SetTip, + AddIdle, + AddTimeout, + }; + + bool ok() { return _ok; } + + AbstractUI () {} + virtual ~AbstractUI() {} + + virtual void run (Receiver &old_receiver) = 0; + virtual void quit () = 0; + virtual bool running () = 0; + virtual void request (RequestType) = 0; + virtual void touch_display (Touchable *) = 0; + virtual void call_slot (sigc::slot<void>) = 0; + virtual bool caller_is_gui_thread() = 0; + + /* needed to be a receiver ... */ + + virtual void receive (Transmitter::Channel, const char *) = 0; + + protected: + bool _ok; +}; + +#endif // __pbd_abstract_ui_h__ + + diff --git a/libs/pbd3/pbd/atomic.h b/libs/pbd3/pbd/atomic.h new file mode 100644 index 0000000000..81e76f41fa --- /dev/null +++ b/libs/pbd3/pbd/atomic.h @@ -0,0 +1,1232 @@ +/* + Copyright (C) 2001 Paul Davis and others (see below) + Code derived from various headers from the Linux kernel. + Copyright attributions maintained where present. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __libpbd_atomic_h__ +#define __libpbd_atomic_h__ + +#ifdef HAVE_SMP /* a macro we control, to manage ... */ +#define CONFIG_SMP /* ... the macro the kernel headers use */ +#endif + +#if defined(__powerpc__) || defined(__ppc__) + +/* + * BK Id: SCCS/s.atomic.h 1.15 10/28/01 10:37:22 trini + */ +/* + * PowerPC atomic operations + */ + +#ifndef _ASM_PPC_ATOMIC_H_ +#define _ASM_PPC_ATOMIC_H_ + +typedef struct { volatile int counter; } atomic_t; + + +#define ATOMIC_INIT(i) { (i) } + +#define atomic_read(v) ((v)->counter) +#define atomic_set(v,i) (((v)->counter) = (i)) + +extern void atomic_clear_mask(unsigned long mask, unsigned long *addr); +extern void atomic_set_mask(unsigned long mask, unsigned long *addr); + +#ifdef CONFIG_SMP +#define SMP_ISYNC "\n\tisync" +#else +#define SMP_ISYNC +#endif + +static __inline__ void atomic_add(int a, atomic_t *v) +{ + int t; + + __asm__ __volatile__( +"1: lwarx %0,0,%3\n\ + add %0,%2,%0\n\ + stwcx. %0,0,%3\n\ + bne- 1b" + : "=&r" (t), "=m" (v->counter) + : "r" (a), "r" (&v->counter), "m" (v->counter) + : "cc"); +} + +static __inline__ int atomic_add_return(int a, atomic_t *v) +{ + int t; + + __asm__ __volatile__( +"1: lwarx %0,0,%2\n\ + add %0,%1,%0\n\ + stwcx. %0,0,%2\n\ + bne- 1b" + SMP_ISYNC + : "=&r" (t) + : "r" (a), "r" (&v->counter) + : "cc", "memory"); + + return t; +} + +static __inline__ void atomic_sub(int a, atomic_t *v) +{ + int t; + + __asm__ __volatile__( +"1: lwarx %0,0,%3\n\ + subf %0,%2,%0\n\ + stwcx. %0,0,%3\n\ + bne- 1b" + : "=&r" (t), "=m" (v->counter) + : "r" (a), "r" (&v->counter), "m" (v->counter) + : "cc"); +} + +static __inline__ int atomic_sub_return(int a, atomic_t *v) +{ + int t; + + __asm__ __volatile__( +"1: lwarx %0,0,%2\n\ + subf %0,%1,%0\n\ + stwcx. %0,0,%2\n\ + bne- 1b" + SMP_ISYNC + : "=&r" (t) + : "r" (a), "r" (&v->counter) + : "cc", "memory"); + + return t; +} + +static __inline__ void atomic_inc(atomic_t *v) +{ + int t; + + __asm__ __volatile__( +"1: lwarx %0,0,%2\n\ + addic %0,%0,1\n\ + stwcx. %0,0,%2\n\ + bne- 1b" + : "=&r" (t), "=m" (v->counter) + : "r" (&v->counter), "m" (v->counter) + : "cc"); +} + +static __inline__ int atomic_inc_return(atomic_t *v) +{ + int t; + + __asm__ __volatile__( +"1: lwarx %0,0,%1\n\ + addic %0,%0,1\n\ + stwcx. %0,0,%1\n\ + bne- 1b" + SMP_ISYNC + : "=&r" (t) + : "r" (&v->counter) + : "cc", "memory"); + + return t; +} + +static __inline__ void atomic_dec(atomic_t *v) +{ + int t; + + __asm__ __volatile__( +"1: lwarx %0,0,%2\n\ + addic %0,%0,-1\n\ + stwcx. %0,0,%2\n\ + bne- 1b" + : "=&r" (t), "=m" (v->counter) + : "r" (&v->counter), "m" (v->counter) + : "cc"); +} + +static __inline__ int atomic_dec_return(atomic_t *v) +{ + int t; + + __asm__ __volatile__( +"1: lwarx %0,0,%1\n\ + addic %0,%0,-1\n\ + stwcx. %0,0,%1\n\ + bne- 1b" + SMP_ISYNC + : "=&r" (t) + : "r" (&v->counter) + : "cc", "memory"); + + return t; +} + +#define atomic_sub_and_test(a, v) (atomic_sub_return((a), (v)) == 0) +#define atomic_dec_and_test(v) (atomic_dec_return((v)) == 0) + +/* + * Atomically test *v and decrement if it is greater than 0. + * The function returns the old value of *v minus 1. + */ +static __inline__ int atomic_dec_if_positive(atomic_t *v) +{ + int t; + + __asm__ __volatile__( +"1: lwarx %0,0,%1\n\ + addic. %0,%0,-1\n\ + blt- 2f\n\ + stwcx. %0,0,%1\n\ + bne- 1b" + SMP_ISYNC + "\n\ +2:" : "=&r" (t) + : "r" (&v->counter) + : "cc", "memory"); + + return t; +} + +#define smp_mb__before_atomic_dec() smp_mb() +#define smp_mb__after_atomic_dec() smp_mb() +#define smp_mb__before_atomic_inc() smp_mb() +#define smp_mb__after_atomic_inc() smp_mb() + +#endif /* _ASM_PPC_ATOMIC_H_ */ + +/***********************************************************************/ + +# else /* !PPC */ + +#if defined(__i386__) || defined(__x86_64__) + +#ifndef __ARCH_I386_ATOMIC__ +#define __ARCH_I386_ATOMIC__ + +/* + * Atomic operations that C can't guarantee us. Useful for + * resource counting etc.. + */ + +#ifdef CONFIG_SMP +#define SMP_LOCK "lock ; " +#else +#define SMP_LOCK "" +#endif + +/* + * Make sure gcc doesn't try to be clever and move things around + * on us. We need to use _exactly_ the address the user gave us, + * not some alias that contains the same information. + */ +typedef struct { volatile int counter; } atomic_t; + +#define ATOMIC_INIT(i) { (i) } + +/** + * atomic_read - read atomic variable + * @v: pointer of type atomic_t + * + * Atomically reads the value of @v. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +#define atomic_read(v) ((v)->counter) + +/** + * atomic_set - set atomic variable + * @v: pointer of type atomic_t + * @i: required value + * + * Atomically sets the value of @v to @i. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +#define atomic_set(v,i) (((v)->counter) = (i)) + +/** + * atomic_add - add integer to atomic variable + * @i: integer value to add + * @v: pointer of type atomic_t + * + * Atomically adds @i to @v. Note that the guaranteed useful range + * of an atomic_t is only 24 bits. + */ +static __inline__ void atomic_add(int i, atomic_t *v) +{ + __asm__ __volatile__( + SMP_LOCK "addl %1,%0" + :"=m" (v->counter) + :"ir" (i), "m" (v->counter)); +} + +/** + * atomic_sub - subtract the atomic variable + * @i: integer value to subtract + * @v: pointer of type atomic_t + * + * Atomically subtracts @i from @v. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +static __inline__ void atomic_sub(int i, atomic_t *v) +{ + __asm__ __volatile__( + SMP_LOCK "subl %1,%0" + :"=m" (v->counter) + :"ir" (i), "m" (v->counter)); +} + +/** + * atomic_sub_and_test - subtract value from variable and test result + * @i: integer value to subtract + * @v: pointer of type atomic_t + * + * Atomically subtracts @i from @v and returns + * true if the result is zero, or false for all + * other cases. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +static __inline__ int atomic_sub_and_test(int i, atomic_t *v) +{ + unsigned char c; + + __asm__ __volatile__( + SMP_LOCK "subl %2,%0; sete %1" + :"=m" (v->counter), "=qm" (c) + :"ir" (i), "m" (v->counter) : "memory"); + return c; +} + +/** + * atomic_inc - increment atomic variable + * @v: pointer of type atomic_t + * + * Atomically increments @v by 1. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +static __inline__ void atomic_inc(atomic_t *v) +{ + __asm__ __volatile__( + SMP_LOCK "incl %0" + :"=m" (v->counter) + :"m" (v->counter)); +} + +/** + * atomic_dec - decrement atomic variable + * @v: pointer of type atomic_t + * + * Atomically decrements @v by 1. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +static __inline__ void atomic_dec(atomic_t *v) +{ + __asm__ __volatile__( + SMP_LOCK "decl %0" + :"=m" (v->counter) + :"m" (v->counter)); +} + +/** + * atomic_dec_and_test - decrement and test + * @v: pointer of type atomic_t + * + * Atomically decrements @v by 1 and + * returns true if the result is 0, or false for all other + * cases. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +static __inline__ int atomic_dec_and_test(atomic_t *v) +{ + unsigned char c; + + __asm__ __volatile__( + SMP_LOCK "decl %0; sete %1" + :"=m" (v->counter), "=qm" (c) + :"m" (v->counter) : "memory"); + return c != 0; +} + +/** + * atomic_inc_and_test - increment and test + * @v: pointer of type atomic_t + * + * Atomically increments @v by 1 + * and returns true if the result is zero, or false for all + * other cases. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +static __inline__ int atomic_inc_and_test(atomic_t *v) +{ + unsigned char c; + + __asm__ __volatile__( + SMP_LOCK "incl %0; sete %1" + :"=m" (v->counter), "=qm" (c) + :"m" (v->counter) : "memory"); + return c != 0; +} + +/** + * atomic_add_negative - add and test if negative + * @v: pointer of type atomic_t + * @i: integer value to add + * + * Atomically adds @i to @v and returns true + * if the result is negative, or false when + * result is greater than or equal to zero. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +static __inline__ int atomic_add_negative(int i, atomic_t *v) +{ + unsigned char c; + + __asm__ __volatile__( + SMP_LOCK "addl %2,%0; sets %1" + :"=m" (v->counter), "=qm" (c) + :"ir" (i), "m" (v->counter) : "memory"); + return c; +} + +/* These are x86-specific, used by some header files */ +#define atomic_clear_mask(mask, addr) \ +__asm__ __volatile__(SMP_LOCK "andl %0,%1" \ +: : "r" (~(mask)),"m" (*addr) : "memory") + +#define atomic_set_mask(mask, addr) \ +__asm__ __volatile__(SMP_LOCK "orl %0,%1" \ +: : "r" (mask),"m" (*addr) : "memory") + +/* Atomic operations are already serializing on x86 */ +#define smp_mb__before_atomic_dec() barrier() +#define smp_mb__after_atomic_dec() barrier() +#define smp_mb__before_atomic_inc() barrier() +#define smp_mb__after_atomic_inc() barrier() + +#endif /* __ARCH_I386_ATOMIC__ */ + +/***********************************************************************/ + +#else /* !PPC && !i386 */ + +#ifdef __sparc__ + +/* atomic.h: These still suck, but the I-cache hit rate is higher. + * + * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 2000 Anton Blanchard (anton@linuxcare.com.au) + */ + +#ifndef __ARCH_SPARC_ATOMIC__ +#define __ARCH_SPARC_ATOMIC__ + +typedef struct { volatile int counter; } atomic_t; + +#ifndef CONFIG_SMP + +#define ATOMIC_INIT(i) { (i) } +#define atomic_read(v) ((v)->counter) +#define atomic_set(v, i) (((v)->counter) = i) + +#else +/* We do the bulk of the actual work out of line in two common + * routines in assembler, see arch/sparc/lib/atomic.S for the + * "fun" details. + * + * For SMP the trick is you embed the spin lock byte within + * the word, use the low byte so signedness is easily retained + * via a quick arithmetic shift. It looks like this: + * + * ---------------------------------------- + * | signed 24-bit counter value | lock | atomic_t + * ---------------------------------------- + * 31 8 7 0 + */ + +#define ATOMIC_INIT(i) { (i << 8) } + +static __inline__ int atomic_read(atomic_t *v) +{ + int ret = v->counter; + + while(ret & 0xff) + ret = v->counter; + + return ret >> 8; +} + +#define atomic_set(v, i) (((v)->counter) = ((i) << 8)) +#endif + +static __inline__ int __atomic_add(int i, atomic_t *v) +{ + register volatile int *ptr asm("g1"); + register int increment asm("g2"); + + ptr = &v->counter; + increment = i; + + __asm__ __volatile__( + "mov %%o7, %%g4\n\t" + "call ___atomic_add\n\t" + " add %%o7, 8, %%o7\n" + : "=&r" (increment) + : "0" (increment), "r" (ptr) + : "g3", "g4", "g7", "memory", "cc"); + + return increment; +} + +static __inline__ int __atomic_sub(int i, atomic_t *v) +{ + register volatile int *ptr asm("g1"); + register int increment asm("g2"); + + ptr = &v->counter; + increment = i; + + __asm__ __volatile__( + "mov %%o7, %%g4\n\t" + "call ___atomic_sub\n\t" + " add %%o7, 8, %%o7\n" + : "=&r" (increment) + : "0" (increment), "r" (ptr) + : "g3", "g4", "g7", "memory", "cc"); + + return increment; +} + +#define atomic_add(i, v) ((void)__atomic_add((i), (v))) +#define atomic_sub(i, v) ((void)__atomic_sub((i), (v))) + +#define atomic_dec_return(v) __atomic_sub(1, (v)) +#define atomic_inc_return(v) __atomic_add(1, (v)) + +#define atomic_sub_and_test(i, v) (__atomic_sub((i), (v)) == 0) +#define atomic_dec_and_test(v) (__atomic_sub(1, (v)) == 0) + +#define atomic_inc(v) ((void)__atomic_add(1, (v))) +#define atomic_dec(v) ((void)__atomic_sub(1, (v))) + +#define atomic_add_negative(i, v) (__atomic_add((i), (v)) < 0) + +/* Atomic operations are already serializing */ +#define smp_mb__before_atomic_dec() barrier() +#define smp_mb__after_atomic_dec() barrier() +#define smp_mb__before_atomic_inc() barrier() +#define smp_mb__after_atomic_inc() barrier() + + +#endif /* !(__ARCH_SPARC_ATOMIC__) */ + +/***********************************************************************/ + +#else + +#ifdef __ia64__ + +#ifndef __ARCH_IA64_ATOMIC__ +#define __ARCH_IA64_ATOMIC__ + +typedef volatile int atomic_t; + +inline +int +atomic_read (const atomic_t * a) +{ + return *a; +} + +inline +void +atomic_set(atomic_t *a, int v) +{ + *a = v; +} + +inline +void +atomic_inc (atomic_t *v) +{ + int old, r; + + do { + old = atomic_read(v); + __asm__ __volatile__ ("mov ar.ccv=%0;;" :: "rO" (old)); + __asm__ __volatile__ ("cmpxchg4.acq %0=[%1],%2,ar.ccv" + : "=r"(r) : "r"(v), "r"(old + 1) + : "memory"); + } while (r != old); +} + +inline +void +atomic_dec (atomic_t *v) +{ + int old, r; + + do { + old = atomic_read(v); + __asm__ __volatile__ ("mov ar.ccv=%0;;" :: "rO" (old)); + __asm__ __volatile__ ("cmpxchg4.acq %0=[%1],%2,ar.ccv" + : "=r"(r) : "r"(v), "r"(old - 1) + : "memory"); + } while (r != old); +} + +inline +int +atomic_dec_and_test (atomic_t *v) +{ + int old, r; + + do { + old = atomic_read(v); + __asm__ __volatile__ ("mov ar.ccv=%0;;" :: "rO" (old)); + __asm__ __volatile__ ("cmpxchg4.acq %0=[%1],%2,ar.ccv" + : "=r"(r) : "r"(v), "r"(old - 1) + : "memory"); + } while (r != old); + return old != 1; +} + +#endif /* !(__ARCH_IA64_ATOMIC__) */ + +#else + +#ifdef __alpha__ + +#ifndef _ALPHA_ATOMIC_H +#define _ALPHA_ATOMIC_H + +/* + * Atomic operations that C can't guarantee us. Useful for + * resource counting etc... + * + * But use these as seldom as possible since they are much slower + * than regular operations. + */ + + +/* + * Counter is volatile to make sure gcc doesn't try to be clever + * and move things around on us. We need to use _exactly_ the address + * the user gave us, not some alias that contains the same information. + */ +typedef struct { volatile int counter; } atomic_t; + +#define ATOMIC_INIT(i) ( (atomic_t) { (i) } ) + +#define atomic_read(v) ((v)->counter) +#define atomic_set(v,i) ((v)->counter = (i)) + +/* + * To get proper branch prediction for the main line, we must branch + * forward to code at the end of this object's .text section, then + * branch back to restart the operation. + */ + +static __inline__ void atomic_add(int i, atomic_t * v) +{ + unsigned long temp; + __asm__ __volatile__( + "1: ldl_l %0,%1\n" + " addl %0,%2,%0\n" + " stl_c %0,%1\n" + " beq %0,2f\n" + ".subsection 2\n" + "2: br 1b\n" + ".previous" + :"=&r" (temp), "=m" (v->counter) + :"Ir" (i), "m" (v->counter)); +} + +static __inline__ void atomic_sub(int i, atomic_t * v) +{ + unsigned long temp; + __asm__ __volatile__( + "1: ldl_l %0,%1\n" + " subl %0,%2,%0\n" + " stl_c %0,%1\n" + " beq %0,2f\n" + ".subsection 2\n" + "2: br 1b\n" + ".previous" + :"=&r" (temp), "=m" (v->counter) + :"Ir" (i), "m" (v->counter)); +} + +/* + * Same as above, but return the result value + */ +static __inline__ long atomic_add_return(int i, atomic_t * v) +{ + long temp, result; + __asm__ __volatile__( + "1: ldl_l %0,%1\n" + " addl %0,%3,%2\n" + " addl %0,%3,%0\n" + " stl_c %0,%1\n" + " beq %0,2f\n" + " mb\n" + ".subsection 2\n" + "2: br 1b\n" + ".previous" + :"=&r" (temp), "=m" (v->counter), "=&r" (result) + :"Ir" (i), "m" (v->counter) : "memory"); + return result; +} + +static __inline__ long atomic_sub_return(int i, atomic_t * v) +{ + long temp, result; + __asm__ __volatile__( + "1: ldl_l %0,%1\n" + " subl %0,%3,%2\n" + " subl %0,%3,%0\n" + " stl_c %0,%1\n" + " beq %0,2f\n" + " mb\n" + ".subsection 2\n" + "2: br 1b\n" + ".previous" + :"=&r" (temp), "=m" (v->counter), "=&r" (result) + :"Ir" (i), "m" (v->counter) : "memory"); + return result; +} + +#define atomic_dec_return(v) atomic_sub_return(1,(v)) +#define atomic_inc_return(v) atomic_add_return(1,(v)) + +#define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0) +#define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0) + +#define atomic_inc(v) atomic_add(1,(v)) +#define atomic_dec(v) atomic_sub(1,(v)) + +#define smp_mb__before_atomic_dec() smp_mb() +#define smp_mb__after_atomic_dec() smp_mb() +#define smp_mb__before_atomic_inc() smp_mb() +#define smp_mb__after_atomic_inc() smp_mb() + +#endif /* _ALPHA_ATOMIC_H */ + +#else + +#ifdef __s390__ + +#ifndef __ARCH_S390_ATOMIC__ +#define __ARCH_S390_ATOMIC__ + +/* + * include/asm-s390/atomic.h + * + * S390 version + * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), + * Denis Joseph Barrow + * + * Derived from "include/asm-i386/bitops.h" + * Copyright (C) 1992, Linus Torvalds + * + */ + +/* + * Atomic operations that C can't guarantee us. Useful for + * resource counting etc.. + * S390 uses 'Compare And Swap' for atomicity in SMP enviroment + */ + +typedef struct { volatile int counter; } __attribute__ ((aligned (4))) atomic_t; +#define ATOMIC_INIT(i) { (i) } + +#define atomic_eieio() __asm__ __volatile__ ("BCR 15,0") + +#define __CS_LOOP(old_val, new_val, ptr, op_val, op_string) \ + __asm__ __volatile__(" l %0,0(%2)\n" \ + "0: lr %1,%0\n" \ + op_string " %1,%3\n" \ + " cs %0,%1,0(%2)\n" \ + " jl 0b" \ + : "=&d" (old_val), "=&d" (new_val) \ + : "a" (ptr), "d" (op_val) : "cc" ); + +#define atomic_read(v) ((v)->counter) +#define atomic_set(v,i) (((v)->counter) = (i)) + +static __inline__ void atomic_add(int i, atomic_t *v) +{ + int old_val, new_val; + __CS_LOOP(old_val, new_val, v, i, "ar"); +} + +static __inline__ int atomic_add_return (int i, atomic_t *v) +{ + int old_val, new_val; + __CS_LOOP(old_val, new_val, v, i, "ar"); + return new_val; +} + +static __inline__ int atomic_add_negative(int i, atomic_t *v) +{ + int old_val, new_val; + __CS_LOOP(old_val, new_val, v, i, "ar"); + return new_val < 0; +} + +static __inline__ void atomic_sub(int i, atomic_t *v) +{ + int old_val, new_val; + __CS_LOOP(old_val, new_val, v, i, "sr"); +} + +static __inline__ void atomic_inc(volatile atomic_t *v) +{ + int old_val, new_val; + __CS_LOOP(old_val, new_val, v, 1, "ar"); +} + +static __inline__ int atomic_inc_return(volatile atomic_t *v) +{ + int old_val, new_val; + __CS_LOOP(old_val, new_val, v, 1, "ar"); + return new_val; +} + +static __inline__ int atomic_inc_and_test(volatile atomic_t *v) +{ + int old_val, new_val; + __CS_LOOP(old_val, new_val, v, 1, "ar"); + return new_val != 0; +} + +static __inline__ void atomic_dec(volatile atomic_t *v) +{ + int old_val, new_val; + __CS_LOOP(old_val, new_val, v, 1, "sr"); +} + +static __inline__ int atomic_dec_return(volatile atomic_t *v) +{ + int old_val, new_val; + __CS_LOOP(old_val, new_val, v, 1, "sr"); + return new_val; +} + +static __inline__ int atomic_dec_and_test(volatile atomic_t *v) +{ + int old_val, new_val; + __CS_LOOP(old_val, new_val, v, 1, "sr"); + return new_val == 0; +} + +static __inline__ void atomic_clear_mask(unsigned long mask, atomic_t *v) +{ + int old_val, new_val; + __CS_LOOP(old_val, new_val, v, ~mask, "nr"); +} + +static __inline__ void atomic_set_mask(unsigned long mask, atomic_t *v) +{ + int old_val, new_val; + __CS_LOOP(old_val, new_val, v, mask, "or"); +} + +/* + returns 0 if expected_oldval==value in *v ( swap was successful ) + returns 1 if unsuccessful. +*/ +static __inline__ int +atomic_compare_and_swap(int expected_oldval,int new_val,atomic_t *v) +{ + int retval; + + __asm__ __volatile__( + " lr 0,%2\n" + " cs 0,%3,0(%1)\n" + " ipm %0\n" + " srl %0,28\n" + "0:" + : "=&d" (retval) + : "a" (v), "d" (expected_oldval) , "d" (new_val) + : "0", "cc"); + return retval; +} + +/* + Spin till *v = expected_oldval then swap with newval. + */ +static __inline__ void +atomic_compare_and_swap_spin(int expected_oldval,int new_val,atomic_t *v) +{ + __asm__ __volatile__( + "0: lr 0,%1\n" + " cs 0,%2,0(%0)\n" + " jl 0b\n" + : : "a" (v), "d" (expected_oldval) , "d" (new_val) + : "cc", "0" ); +} + +#define smp_mb__before_atomic_dec() smp_mb() +#define smp_mb__after_atomic_dec() smp_mb() +#define smp_mb__before_atomic_inc() smp_mb() +#define smp_mb__after_atomic_inc() smp_mb() + +#endif /* __ARCH_S390_ATOMIC __ */ + +#else + +#ifdef __mips__ + +/* + * Atomic operations that C can't guarantee us. Useful for + * resource counting etc.. + * + * But use these as seldom as possible since they are much more slower + * than regular operations. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1996, 1997, 2000 by Ralf Baechle + */ +#ifndef __ASM_ATOMIC_H +#define __ASM_ATOMIC_H + +typedef struct { volatile int counter; } atomic_t; + +#define ATOMIC_INIT(i) { (i) } + +/* + * atomic_read - read atomic variable + * @v: pointer of type atomic_t + * + * Atomically reads the value of @v. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +#define atomic_read(v) ((v)->counter) + +/* + * atomic_set - set atomic variable + * @v: pointer of type atomic_t + * @i: required value + * + * Atomically sets the value of @v to @i. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +#define atomic_set(v,i) ((v)->counter = (i)) + +/* + * ... while for MIPS II and better we can use ll/sc instruction. This + * implementation is SMP safe ... + */ + +/* + * atomic_add - add integer to atomic variable + * @i: integer value to add + * @v: pointer of type atomic_t + * + * Atomically adds @i to @v. Note that the guaranteed useful range + * of an atomic_t is only 24 bits. + */ +extern __inline__ void atomic_add(int i, atomic_t * v) +{ + unsigned long temp; + + __asm__ __volatile__( + ".set push # atomic_add\n" + ".set mips2 \n" + "1: ll %0, %1 \n" + " addu %0, %2 \n" + " sc %0, %1 \n" + " beqz %0, 1b \n" + ".set pop \n" + : "=&r" (temp), "=m" (v->counter) + : "Ir" (i), "m" (v->counter)); +} + +/* + * atomic_sub - subtract the atomic variable + * @i: integer value to subtract + * @v: pointer of type atomic_t + * + * Atomically subtracts @i from @v. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +extern __inline__ void atomic_sub(int i, atomic_t * v) +{ + unsigned long temp; + + __asm__ __volatile__( + ".set push # atomic_sub\n" + ".set mips2 \n" + "1: ll %0, %1 \n" + " subu %0, %2 \n" + " sc %0, %1 \n" + " beqz %0, 1b \n" + ".set pop \n" + : "=&r" (temp), "=m" (v->counter) + : "Ir" (i), "m" (v->counter)); +} + +/* + * Same as above, but return the result value + */ +extern __inline__ int atomic_add_return(int i, atomic_t * v) +{ + unsigned long temp, result; + + __asm__ __volatile__( + ".set push # atomic_add_return\n" + ".set mips2 \n" + ".set noreorder \n" + "1: ll %1, %2 \n" + " addu %0, %1, %3 \n" + " sc %0, %2 \n" + " beqz %0, 1b \n" + " addu %0, %1, %3 \n" + " sync \n" + ".set pop \n" + : "=&r" (result), "=&r" (temp), "=m" (v->counter) + : "Ir" (i), "m" (v->counter) + : "memory"); + + return result; +} + +extern __inline__ int atomic_sub_return(int i, atomic_t * v) +{ + unsigned long temp, result; + + __asm__ __volatile__( + ".set push # atomic_sub_return\n" + ".set mips2 \n" + ".set noreorder \n" + "1: ll %1, %2 \n" + " subu %0, %1, %3 \n" + " sc %0, %2 \n" + " beqz %0, 1b \n" + " subu %0, %1, %3 \n" + " sync \n" + ".set pop \n" + : "=&r" (result), "=&r" (temp), "=m" (v->counter) + : "Ir" (i), "m" (v->counter) + : "memory"); + + return result; +} + +#define atomic_dec_return(v) atomic_sub_return(1,(v)) +#define atomic_inc_return(v) atomic_add_return(1,(v)) + +/* + * atomic_sub_and_test - subtract value from variable and test result + * @i: integer value to subtract + * @v: pointer of type atomic_t + * + * Atomically subtracts @i from @v and returns + * true if the result is zero, or false for all + * other cases. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +#define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0) + +/* + * atomic_inc_and_test - increment and test + * @v: pointer of type atomic_t + * + * Atomically increments @v by 1 + * and returns true if the result is zero, or false for all + * other cases. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +#define atomic_inc_and_test(v) (atomic_inc_return(1, (v)) == 0) + +/* + * atomic_dec_and_test - decrement by 1 and test + * @v: pointer of type atomic_t + * + * Atomically decrements @v by 1 and + * returns true if the result is 0, or false for all other + * cases. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +#define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0) + +/* + * atomic_inc - increment atomic variable + * @v: pointer of type atomic_t + * + * Atomically increments @v by 1. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +#define atomic_inc(v) atomic_add(1,(v)) + +/* + * atomic_dec - decrement and test + * @v: pointer of type atomic_t + * + * Atomically decrements @v by 1. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +#define atomic_dec(v) atomic_sub(1,(v)) + +/* + * atomic_add_negative - add and test if negative + * @v: pointer of type atomic_t + * @i: integer value to add + * + * Atomically adds @i to @v and returns true + * if the result is negative, or false when + * result is greater than or equal to zero. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + * + * Currently not implemented for MIPS. + */ + +/* Atomic operations are already serializing */ +#define smp_mb__before_atomic_dec() smp_mb() +#define smp_mb__after_atomic_dec() smp_mb() +#define smp_mb__before_atomic_inc() smp_mb() +#define smp_mb__after_atomic_inc() smp_mb() + +#endif /* __ASM_ATOMIC_H */ + +#else + +#if defined(__m68k__) + +#ifndef __ARCH_M68K_ATOMIC__ +#define __ARCH_M68K_ATOMIC__ + +/* + * Atomic operations that C can't guarantee us. Useful for + * resource counting etc.. + */ + +/* + * We do not have SMP m68k systems, so we don't have to deal with that. + */ + +typedef struct { int counter; } atomic_t; +#define ATOMIC_INIT(i) { (i) } + +#define atomic_read(v) ((v)->counter) +#define atomic_set(v, i) (((v)->counter) = i) + +static __inline__ void atomic_add(int i, atomic_t *v) +{ + __asm__ __volatile__("addl %1,%0" : "=m" (*v) : "id" (i), "0" (*v)); +} + +static __inline__ void atomic_sub(int i, atomic_t *v) +{ + __asm__ __volatile__("subl %1,%0" : "=m" (*v) : "id" (i), "0" (*v)); +} + +static __inline__ void atomic_inc(volatile atomic_t *v) +{ + __asm__ __volatile__("addql #1,%0" : "=m" (*v): "0" (*v)); +} + +static __inline__ void atomic_dec(volatile atomic_t *v) +{ + __asm__ __volatile__("subql #1,%0" : "=m" (*v): "0" (*v)); +} + +static __inline__ int atomic_dec_and_test(volatile atomic_t *v) +{ + char c; + __asm__ __volatile__("subql #1,%1; seq %0" : "=d" (c), "=m" (*v): "1" (*v)); + return c != 0; +} + +#define atomic_clear_mask(mask, v) \ + __asm__ __volatile__("andl %1,%0" : "=m" (*v) : "id" (~(mask)),"0"(*v)) + +#define atomic_set_mask(mask, v) \ + __asm__ __volatile__("orl %1,%0" : "=m" (*v) : "id" (mask),"0"(*v)) + +/* Atomic operations are already serializing */ +#define smp_mb__before_atomic_dec() barrier() +#define smp_mb__after_atomic_dec() barrier() +#define smp_mb__before_atomic_inc() barrier() +#define smp_mb__after_atomic_inc() barrier() + +#endif /* __ARCH_M68K_ATOMIC __ */ + +#else + +#warning libs/pbd has no implementation of strictly atomic operations for your hardware. + +#define __NO_STRICT_ATOMIC +#ifdef __NO_STRICT_ATOMIC + +/* + * Because the implementations from the kernel (where all these come + * from) use cli and spinlocks for hppa and arm... + */ + +typedef struct { volatile int counter; } atomic_t; + +#define ATOMIC_INIT(i) ( (atomic_t) { (i) } ) + +#define atomic_read(v) ((v)->counter) +#define atomic_set(v,i) ((v)->counter = (i)) + +static __inline__ void atomic_inc(atomic_t *v) +{ + v->counter++; +} + +static __inline__ void atomic_dec(atomic_t *v) +{ + v->counter--; +} + +static __inline__ int atomic_dec_and_test(atomic_t *v) +{ + int res; + v->counter--; + res = v->counter; + return res == 0; +} + +static __inline__ int atomic_inc_and_test(atomic_t *v) +{ + int res; + v->counter++; + res = v->counter; + return res == 0; +} + +# endif /* __NO_STRICT_ATOMIC */ +# endif /* m68k */ +# endif /* mips */ +# endif /* s390 */ +# endif /* alpha */ +# endif /* ia64 */ +# endif /* sparc */ +# endif /* i386 */ +# endif /* ppc */ + +#endif /* __libpbd_atomic_h__ */ + diff --git a/libs/pbd3/pbd/basename.h b/libs/pbd3/pbd/basename.h new file mode 100644 index 0000000000..01f40b6b6a --- /dev/null +++ b/libs/pbd3/pbd/basename.h @@ -0,0 +1,15 @@ +#ifndef __stupid_basename_h__ +#define __stupid_basename_h__ + +#include <string> + +namespace PBD +{ + +extern char *basename (const char *); +extern std::string basename (const std::string); +extern std::string basename_nosuffix (const std::string); + +}; + +#endif // __stupid_basename_h__ diff --git a/libs/pbd3/pbd/compose.h b/libs/pbd3/pbd/compose.h new file mode 100644 index 0000000000..9a65a3e0b1 --- /dev/null +++ b/libs/pbd3/pbd/compose.h @@ -0,0 +1,393 @@ +/* Defines String::compose(fmt, arg...) for easy, i18n-friendly + * composition of strings. + * + * Version 1.0. + * + * Copyright (c) 2002 Ole Laursen <olau@hardworking.dk>. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This program 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. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + */ + +// +// Basic usage is like +// +// std::cout << String::compose("This is a %1x%2 matrix.", rows, cols); +// +// See http://www.cs.auc.dk/~olau/compose/ or the included README.compose for +// more details. +// + +#ifndef STRING_COMPOSE_H +#define STRING_COMPOSE_H + +#include <sstream> +#include <string> +#include <list> +#include <map> // for multimap + +namespace StringPrivate +{ + // the actual composition class - using string::compose is cleaner, so we + // hide it here + class Composition + { + public: + // initialize and prepare format string on the form "text %1 text %2 etc." + explicit Composition(std::string fmt); + + // supply an replacement argument starting from %1 + template <typename T> + Composition &arg(const T &obj); + + // compose and return string + std::string str() const; + + private: + std::ostringstream os; + int arg_no; + + // we store the output as a list - when the output string is requested, the + // list is concatenated to a string; this way we can keep iterators into + // the list instead of into a string where they're possibly invalidated on + // inserting a specification string + typedef std::list<std::string> output_list; + output_list output; + + // the initial parse of the format string fills in the specification map + // with positions for each of the various %?s + typedef std::multimap<int, output_list::iterator> specification_map; + specification_map specs; + }; + + // helper for converting spec string numbers + inline int char_to_int(char c) + { + switch (c) { + case '0': return 0; + case '1': return 1; + case '2': return 2; + case '3': return 3; + case '4': return 4; + case '5': return 5; + case '6': return 6; + case '7': return 7; + case '8': return 8; + case '9': return 9; + default: return -1000; + } + } + + inline bool is_number(int n) + { + switch (n) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return true; + + default: + return false; + } + } + + + // implementation of class Composition + template <typename T> + inline Composition &Composition::arg(const T &obj) + { + os << obj; + + std::string rep = os.str(); + + if (!rep.empty()) { // manipulators don't produce output + for (specification_map::const_iterator i = specs.lower_bound(arg_no), + end = specs.upper_bound(arg_no); i != end; ++i) { + output_list::iterator pos = i->second; + ++pos; + + output.insert(pos, rep); + } + + os.str(std::string()); + //os.clear(); + ++arg_no; + } + + return *this; + } + + inline Composition::Composition(std::string fmt) + : arg_no(1) + { + std::string::size_type b = 0, i = 0; + + // fill in output with the strings between the %1 %2 %3 etc. and + // fill in specs with the positions + while (i < fmt.length()) { + if (fmt[i] == '%' && i + 1 < fmt.length()) { + if (fmt[i + 1] == '%') { // catch %% + fmt.replace(i, 2, "%"); + ++i; + } + else if (is_number(fmt[i + 1])) { // aha! a spec! + // save string + output.push_back(fmt.substr(b, i - b)); + + int n = 1; // number of digits + int spec_no = 0; + + do { + spec_no += char_to_int(fmt[i + n]); + spec_no *= 10; + ++n; + } while (i + n < fmt.length() && is_number(fmt[i + n])); + + spec_no /= 10; + output_list::iterator pos = output.end(); + --pos; // safe since we have just inserted a string> + + specs.insert(specification_map::value_type(spec_no, pos)); + + // jump over spec string + i += n; + b = i; + } + else + ++i; + } + else + ++i; + } + + if (i - b > 0) // add the rest of the string + output.push_back(fmt.substr(b, i - b)); + } + + inline std::string Composition::str() const + { + // assemble string + std::string str; + + for (output_list::const_iterator i = output.begin(), end = output.end(); + i != end; ++i) + str += *i; + + return str; + } +} + +// now for the real thing(s) +//namespace String +//{ + // a series of functions which accept a format string on the form "text %1 + // more %2 less %3" and a number of templated parameters and spits out the + // composited string + template <typename T1> + inline std::string compose(const std::string &fmt, const T1 &o1) + { + StringPrivate::Composition c(fmt); + c.arg(o1); + return c.str(); + } + + template <typename T1, typename T2> + inline std::string compose(const std::string &fmt, + const T1 &o1, const T2 &o2) + { + StringPrivate::Composition c(fmt); + c.arg(o1).arg(o2); + return c.str(); + } + + template <typename T1, typename T2, typename T3> + inline std::string compose(const std::string &fmt, + const T1 &o1, const T2 &o2, const T3 &o3) + { + StringPrivate::Composition c(fmt); + c.arg(o1).arg(o2).arg(o3); + return c.str(); + } + + template <typename T1, typename T2, typename T3, typename T4> + inline std::string compose(const std::string &fmt, + const T1 &o1, const T2 &o2, const T3 &o3, + const T4 &o4) + { + StringPrivate::Composition c(fmt); + c.arg(o1).arg(o2).arg(o3).arg(o4); + return c.str(); + } + + template <typename T1, typename T2, typename T3, typename T4, typename T5> + inline std::string compose(const std::string &fmt, + const T1 &o1, const T2 &o2, const T3 &o3, + const T4 &o4, const T5 &o5) + { + StringPrivate::Composition c(fmt); + c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5); + return c.str(); + } + + template <typename T1, typename T2, typename T3, typename T4, typename T5, + typename T6> + inline std::string compose(const std::string &fmt, + const T1 &o1, const T2 &o2, const T3 &o3, + const T4 &o4, const T5 &o5, const T6 &o6) + { + StringPrivate::Composition c(fmt); + c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6); + return c.str(); + } + + template <typename T1, typename T2, typename T3, typename T4, typename T5, + typename T6, typename T7> + inline std::string compose(const std::string &fmt, + const T1 &o1, const T2 &o2, const T3 &o3, + const T4 &o4, const T5 &o5, const T6 &o6, + const T7 &o7) + { + StringPrivate::Composition c(fmt); + c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7); + return c.str(); + } + + template <typename T1, typename T2, typename T3, typename T4, typename T5, + typename T6, typename T7, typename T8> + inline std::string compose(const std::string &fmt, + const T1 &o1, const T2 &o2, const T3 &o3, + const T4 &o4, const T5 &o5, const T6 &o6, + const T7 &o7, const T8 &o8) + { + StringPrivate::Composition c(fmt); + c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8); + return c.str(); + } + + template <typename T1, typename T2, typename T3, typename T4, typename T5, + typename T6, typename T7, typename T8, typename T9> + inline std::string compose(const std::string &fmt, + const T1 &o1, const T2 &o2, const T3 &o3, + const T4 &o4, const T5 &o5, const T6 &o6, + const T7 &o7, const T8 &o8, const T9 &o9) + { + StringPrivate::Composition c(fmt); + c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9); + return c.str(); + } + + template <typename T1, typename T2, typename T3, typename T4, typename T5, + typename T6, typename T7, typename T8, typename T9, typename T10> + inline std::string compose(const std::string &fmt, + const T1 &o1, const T2 &o2, const T3 &o3, + const T4 &o4, const T5 &o5, const T6 &o6, + const T7 &o7, const T8 &o8, const T9 &o9, + const T10 &o10) + { + StringPrivate::Composition c(fmt); + c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9) + .arg(o10); + return c.str(); + } + + template <typename T1, typename T2, typename T3, typename T4, typename T5, + typename T6, typename T7, typename T8, typename T9, typename T10, + typename T11> + inline std::string compose(const std::string &fmt, + const T1 &o1, const T2 &o2, const T3 &o3, + const T4 &o4, const T5 &o5, const T6 &o6, + const T7 &o7, const T8 &o8, const T9 &o9, + const T10 &o10, const T11 &o11) + { + StringPrivate::Composition c(fmt); + c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9) + .arg(o10).arg(o11); + return c.str(); + } + + template <typename T1, typename T2, typename T3, typename T4, typename T5, + typename T6, typename T7, typename T8, typename T9, typename T10, + typename T11, typename T12> + inline std::string compose(const std::string &fmt, + const T1 &o1, const T2 &o2, const T3 &o3, + const T4 &o4, const T5 &o5, const T6 &o6, + const T7 &o7, const T8 &o8, const T9 &o9, + const T10 &o10, const T11 &o11, const T12 &o12) + { + StringPrivate::Composition c(fmt); + c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9) + .arg(o10).arg(o11).arg(o12); + return c.str(); + } + + template <typename T1, typename T2, typename T3, typename T4, typename T5, + typename T6, typename T7, typename T8, typename T9, typename T10, + typename T11, typename T12, typename T13> + inline std::string compose(const std::string &fmt, + const T1 &o1, const T2 &o2, const T3 &o3, + const T4 &o4, const T5 &o5, const T6 &o6, + const T7 &o7, const T8 &o8, const T9 &o9, + const T10 &o10, const T11 &o11, const T12 &o12, + const T13 &o13) + { + StringPrivate::Composition c(fmt); + c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9) + .arg(o10).arg(o11).arg(o12).arg(o13); + return c.str(); + } + + template <typename T1, typename T2, typename T3, typename T4, typename T5, + typename T6, typename T7, typename T8, typename T9, typename T10, + typename T11, typename T12, typename T13, typename T14> + inline std::string compose(const std::string &fmt, + const T1 &o1, const T2 &o2, const T3 &o3, + const T4 &o4, const T5 &o5, const T6 &o6, + const T7 &o7, const T8 &o8, const T9 &o9, + const T10 &o10, const T11 &o11, const T12 &o12, + const T13 &o13, const T14 &o14) + { + StringPrivate::Composition c(fmt); + c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9) + .arg(o10).arg(o11).arg(o12).arg(o13).arg(o14); + return c.str(); + } + + template <typename T1, typename T2, typename T3, typename T4, typename T5, + typename T6, typename T7, typename T8, typename T9, typename T10, + typename T11, typename T12, typename T13, typename T14, + typename T15> + inline std::string compose(const std::string &fmt, + const T1 &o1, const T2 &o2, const T3 &o3, + const T4 &o4, const T5 &o5, const T6 &o6, + const T7 &o7, const T8 &o8, const T9 &o9, + const T10 &o10, const T11 &o11, const T12 &o12, + const T13 &o13, const T14 &o14, const T15 &o15) + { + StringPrivate::Composition c(fmt); + c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9) + .arg(o10).arg(o11).arg(o12).arg(o13).arg(o14).arg(o15); + return c.str(); + } +//} + + +#endif // STRING_COMPOSE_H diff --git a/libs/pbd3/pbd/datum.h b/libs/pbd3/pbd/datum.h new file mode 100644 index 0000000000..1f2704b429 --- /dev/null +++ b/libs/pbd3/pbd/datum.h @@ -0,0 +1,57 @@ +/* + Copyright (C) 1998-99 Paul Barton-Davis + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __qm_datum_h__ +#define __qm_datum_h__ + +/* A basic data type used whenever we want to represent + something that might be a string or a number. +*/ + +struct Datum { + enum Type { + String, + Numeric, + }; + Type type; + union { + const char *str; + float n; + }; + + Datum &operator=(float val) { + type = Numeric; + n = val; + return *this; + } + + Datum &operator=(int val) { + type = Numeric; + n=(float) val; + return *this; + } + + Datum &operator=(const char *val) { + type = String; + str = val; + return *this; + } +}; + +#endif // __qm_datum_h__ diff --git a/libs/pbd3/pbd/dirname.h b/libs/pbd3/pbd/dirname.h new file mode 100644 index 0000000000..5e63ddb55d --- /dev/null +++ b/libs/pbd3/pbd/dirname.h @@ -0,0 +1,11 @@ +#ifndef __stupid_dirname_h__ +#define __stupid_dirname_h__ + + +#include <string> + +namespace PBD { + extern char *dirname (const char *); + extern std::string dirname (const std::string); +} +#endif // __stupid_dirname_h__ diff --git a/libs/pbd3/pbd/ellipsoid.h b/libs/pbd3/pbd/ellipsoid.h new file mode 100644 index 0000000000..3758e415c2 --- /dev/null +++ b/libs/pbd3/pbd/ellipsoid.h @@ -0,0 +1,74 @@ +/* + Copyright (C) 1998-99 Paul Barton-Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __qm_ellipsoid_h__ +#define __qm_ellipsoid_h__ + +struct Arc +{ + int rect_x; + int rect_y; + int rect_h; + int rect_w; + int start_angle; + int arc_angle; + bool counter_clockwise; +}; + +class Ellipsoid +{ + int start_x; + int end_x; + int start_y; + int end_y; + static const unsigned int narcs; + + public: + Arc arc[2]; + + Ellipsoid () { + start_x = -1; + end_x = -1; + } + + bool ready() { return start_x != -1 && end_x != -1; } + void set_start (int x, int y); + void set_end (int x, int y); + void compute (); + + void set_start_angle (int n, int which_arc = -1) { + if (which_arc < 0) { + arc[0].start_angle = n * 64; + arc[1].start_angle = n * 64; + } else if (which_arc < (int) narcs) { + arc[which_arc].start_angle = n * 64; + } + } + void set_arc_angle (int n, int which_arc = -1) { + if (which_arc < 0) { + arc[0].arc_angle = n * 64; + arc[1].arc_angle = n * 64; + } else if (which_arc < (int) narcs) { + arc[which_arc].arc_angle = n * 64; + } + } +}; + +#endif // __qm_ellipsoid_h__ diff --git a/libs/pbd3/pbd/error.h b/libs/pbd3/pbd/error.h new file mode 100644 index 0000000000..cb822e6210 --- /dev/null +++ b/libs/pbd3/pbd/error.h @@ -0,0 +1,30 @@ +/* + Copyright (C) 1998-99 Paul Barton-Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ +#ifndef __libmisc_error_h__ +#define __libmisc_error_h__ + +#include "transmitter.h" + +extern Transmitter error; +extern Transmitter info; +extern Transmitter warning; +extern Transmitter fatal; + +#endif // __libmisc_error_h__ diff --git a/libs/pbd3/pbd/failed_constructor.h b/libs/pbd3/pbd/failed_constructor.h new file mode 100644 index 0000000000..62eb6c0d71 --- /dev/null +++ b/libs/pbd3/pbd/failed_constructor.h @@ -0,0 +1,11 @@ +#ifndef __pbd_failed_constructor_h__ +#define __pbd_failed_constructor_h__ + +#include <exception> + +class failed_constructor : public std::exception { + public: + virtual const char *what() const throw() { return "failed constructor"; } +}; + +#endif /* __pbd_failed_constructor_h__ */ diff --git a/libs/pbd3/pbd/fastlog.h b/libs/pbd3/pbd/fastlog.h new file mode 100644 index 0000000000..4e9050cb8b --- /dev/null +++ b/libs/pbd3/pbd/fastlog.h @@ -0,0 +1,38 @@ +/* Copyright unknown. Code by Laurent de Soras <laurent@ohmforce.com>. + */ + +#ifndef __pbd_fastlog_h__ +#define __pbd_fastlog_h__ + +#include <math.h> /* for HUGE_VAL */ + +static inline float fast_log2 (float val) +{ + /* don't use reinterpret_cast<> because that prevents this + from being used by pure C code (for example, GnomeCanvasItems) + */ + int * const exp_ptr = (int *)(&val); + int x = *exp_ptr; + const int log_2 = ((x >> 23) & 255) - 128; + x &= ~(255 << 23); + x += 127 << 23; + *exp_ptr = x; + + val = ((-1.0f/3) * val + 2) * val - 2.0f/3; // (1) + + return (val + log_2); +} + +static inline float fast_log (const float val) +{ + return (fast_log2 (val) * 0.69314718f); +} + +static inline float fast_log10 (const float val) +{ + return fast_log2(val) / 3.312500f; +} + +static inline float minus_infinity() { return -HUGE_VAL; } + +#endif /* __pbd_fastlog_h__ */ diff --git a/libs/pbd3/pbd/foreach.h b/libs/pbd3/pbd/foreach.h new file mode 100644 index 0000000000..5102d81bb0 --- /dev/null +++ b/libs/pbd3/pbd/foreach.h @@ -0,0 +1,42 @@ +/* + Copyright (C) 2002 Paul Barton-Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __lib_pbd_foreach_h__ +#define __lib_pbd_foreach_h__ + +template<class Iter, class T> void foreach (Iter first, Iter last, void (T::*method)()) { + for (; first != last; ++first) { + ((*first).*method)(); + } +} + +template<class Iter, class T, class A> void foreach (Iter first, Iter last, void (T::*method)(A a), A arg) { + for (; first != last; ++first) { + ((*first).*method)(arg); + } +} + +template<class Iter, class T, class A1, class A2> void foreach (Iter first, Iter last, void (T::*method)(A1, A2), A1 arg1, A2 arg2) { + for (; first != last; ++first) { + ((*first).*method)(arg1, arg2); + } +} + +#endif /* __lib_pbd_foreach_h__ */ diff --git a/libs/pbd3/pbd/forkexec.h b/libs/pbd3/pbd/forkexec.h new file mode 100644 index 0000000000..2af3711390 --- /dev/null +++ b/libs/pbd3/pbd/forkexec.h @@ -0,0 +1,9 @@ +#ifndef __forkexec_h__ +#define __forkexec_h__ + +#include <unistd.h> + +pid_t forkexec(char **argv, char **envp, int outpipe[2], int inpipe[2]); +pid_t forkexec_cmd(char *cmd, char **envp, int outpipe[2], int inpipe[2]); + +#endif // __forkexec_h__ diff --git a/libs/pbd3/pbd/ftw.h b/libs/pbd3/pbd/ftw.h new file mode 100644 index 0000000000..9acf8a6967 --- /dev/null +++ b/libs/pbd3/pbd/ftw.h @@ -0,0 +1,106 @@ +/* + Copyright (c) 2003 by Joel Baker. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the Author nor the names of any contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +#ifndef _FTW_H +#define _FTW_H + +#include <sys/stat.h> + +/* Enumerated values for 'flag' when calling [n]ftw */ + +enum { + FTW_D, /* Directories */ + FTW_DNR, /* Unreadable directory */ + FTW_F, /* Regular files */ + FTW_SL, /* Symbolic link */ + FTW_NS, /* stat(2) failed */ + +#ifdef __USE_XOPEN_EXTENDED /* X/Open */ + +/* Flags for nftw only */ + + FTW_DP, /* Directory, subdirs visited */ + FTW_SLN, /* Dangling symlink */ + +#endif /* __USE_XOPEN_EXTENDED */ +}; + +#ifdef __USE_XOPEN_EXTENDED /* X/Open */ + +/* Enumerated values for 'flags' when calling nftw */ + +enum { + FTW_CHDIR = 1, /* Do a chdir(2) when entering a directory */ + FTW_DEPTH = 2, /* Report files first (before directory) */ + FTW_MOUNT = 4, /* Single filesystem */ + FTW_PHYS = 8 /* Physical walk; ignore symlinks */ +}; + +#define FTW_PHYS FTW_PHYS +#define FTW_MOUNT FTW_MOUNT +#define FTW_CHDIR FTW_CHDIR +#define FTW_DEPTH FTW_DEPTH + +/* FTW struct for callbacks from nftw */ + +struct FTW { + int base; + int level; +}; + +#endif /* __USE_XOPEN_EXTENDED */ + +/* Typecasts for callback functions */ + +typedef int (*__ftw_func_t) \ + (const char *file, const struct stat *status, int flag); + +#ifdef __USE_XOPEN_EXTENDED /* X/Open */ + +typedef int (*__nftw_func_t) \ + (const char *file, const struct stat *status, int flag, struct FTW *detail); + +#endif /* __USE_XOPEN_EXTENDED */ + +/* ftw: walk a directory tree, calling a function for each element */ + +extern int ftw (const char *dir, __ftw_func_t func, int descr); + +#ifdef __USE_XOPEN_EXTENDED /* X/Open */ + +/* nftw: walk a directory tree, calling a function for each element; much + * like ftw, but with behavior flags and minty freshness. + */ + +extern int nftw (const char *dir, __nftw_func_t func, int descr, int flags); + +#endif /* __USE_XOPEN_EXTENDED */ + +#endif /* _FTW_H */ diff --git a/libs/pbd3/pbd/irix_platform.h b/libs/pbd3/pbd/irix_platform.h new file mode 100644 index 0000000000..f948554f26 --- /dev/null +++ b/libs/pbd3/pbd/irix_platform.h @@ -0,0 +1,20 @@ +#ifndef __irix_platform__ +#define __irix_platform__ + +#include <pbd/platform.h> + +class IrixPlatform : public Platform { + public: + IrixPlatform () : Platform () {}; + virtual ~IrixPlatform (); + + virtual int pre_config (); + virtual int post_config (); + virtual int pre_ui (); + virtual int post_ui (); + + virtual int dsp_startup(); +}; + + +#endif // __irix_platform__ diff --git a/libs/pbd3/pbd/linux_platform.h b/libs/pbd3/pbd/linux_platform.h new file mode 100644 index 0000000000..74822a9d89 --- /dev/null +++ b/libs/pbd3/pbd/linux_platform.h @@ -0,0 +1,41 @@ +/* + Copyright (C) 1999 Paul Barton-Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __linux_platform_h__ +#define __linux_platform_h__ + +#include <pbd/platform.h> + +class LinuxPlatform : public Platform + +{ + public: + LinuxPlatform (); + ~LinuxPlatform () {}; + + int pre_config (); + int post_config (); + int pre_ui (); + int post_ui (); + + int dsp_startup() { return 0; } +}; + +#endif // __linux_platform_h__ diff --git a/libs/pbd3/pbd/lock_free_fifo.h b/libs/pbd3/pbd/lock_free_fifo.h new file mode 100644 index 0000000000..cbe653fcb5 --- /dev/null +++ b/libs/pbd3/pbd/lock_free_fifo.h @@ -0,0 +1,86 @@ +/* + Copyright (C) 2000 Paul Barton-Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __pbd_lockfree_fifo_h__ +#define __pbd_lockfree_fifo_h__ + +#include <sys/types.h> +#include <cstdlib> + +template<class T> +class LockFreeFIFO +{ +public: + LockFreeFIFO (int sz) { + size = sz; + push_ptr = 0; + pop_ptr = 0; + buf = new T[size]; + }; + + virtual ~LockFreeFIFO() { + delete [] buf; + } + + + int pop (T& r) { + if (pop_ptr == push_ptr) { + return -1; + } else { + r = buf[pop_ptr]; + pop_ptr++; + if (pop_ptr >= size) { + pop_ptr = 0; + } + return 0; + } + } + + int top (T& r) { + if (pop_ptr == push_ptr) { + return -1; + } else { + r = buf[pop_ptr]; + return 0; + } + } + + int push (T& t) { + if ((size_t) abs (static_cast<int>(push_ptr - pop_ptr)) < size) { + buf[push_ptr] = t; + push_ptr++; + if (push_ptr >= size) { + push_ptr = 0; + } + return 0; + } else { + return -1; + } + } + + protected: + T *buf; + volatile size_t push_ptr; + volatile size_t pop_ptr; + size_t size; +}; + + +#endif /* __pbd_lockfree_fifo_h__ */ diff --git a/libs/pbd3/pbd/lockmonitor.h b/libs/pbd3/pbd/lockmonitor.h new file mode 100644 index 0000000000..8fad66f83e --- /dev/null +++ b/libs/pbd3/pbd/lockmonitor.h @@ -0,0 +1,194 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __pbd_lockmonitor_h__ +#define __pbd_lockmonitor_h__ + +#include <pthread.h> +#include <pbd/pthread_spinlock.h> + +#undef DEBUG_LOCK_MONITOR + +#ifdef DEBUG_LOCK_MONITOR +#include <iostream> +#include <ardour/cycles.h> +#endif + +namespace PBD +{ +class Lock { + public: + Lock() { pthread_mutex_init (&_mutex, 0); } + virtual ~Lock() {} + + virtual int lock () { return pthread_mutex_lock (&_mutex); } + virtual int unlock() { return pthread_mutex_unlock (&_mutex); } + + pthread_mutex_t *mutex() { return &_mutex; } + + protected: + pthread_mutex_t _mutex; +}; + +class NonBlockingLock : public Lock { + public: + NonBlockingLock() {} + ~NonBlockingLock(){} + + int lock () { return pthread_mutex_lock (&_mutex); } + int trylock () { return pthread_mutex_trylock (&_mutex); } + int unlock() { return pthread_mutex_unlock (&_mutex); } +}; + +class LockMonitor +{ + public: + LockMonitor (Lock& lck, unsigned long l, const char *f) + : lock (lck) +#ifdef DEBUG_LOCK_MONITOR + , line (l), file (f) +#endif + { + +#ifdef DEBUG_LOCK_MONITOR + unsigned long long when; + when = get_cycles(); + cerr << when << " lock " << &lock << " at " << line << " in " << file << endl; +#endif + lock.lock (); +#ifdef DEBUG_LOCK_MONITOR + when = get_cycles(); + cerr << '\t' << when + << " locked: " + << &lock << " at " + << line << " in " << file << endl; +#endif + } + + ~LockMonitor () { + lock.unlock (); +#ifdef DEBUG_LOCK_MONITOR + unsigned long long when; + when = get_cycles(); + cerr << '\t' << when << ' ' + << " UNLOCKED " + << &lock << " at " + << line << " in " << file << endl; +#endif + } + private: + Lock& lock; +#ifdef DEBUG_LOCK_MONITOR + unsigned long line; + const char * file; +#endif +}; + +class TentativeLockMonitor +{ + public: + TentativeLockMonitor (NonBlockingLock& lck, unsigned long l, const char *f) + : lock (lck) +#ifdef DEBUG_LOCK_MONITOR + , line (l), file (f) +#endif + { + +#ifdef DEBUG_LOCK_MONITOR + unsigned long long when; + when = get_cycles(); + cerr << when << " tentative lock " << &lock << " at " << line << " in " << file << endl; +#endif + _locked = (lock.trylock() == 0); + +#ifdef DEBUG_LOCK_MONITOR + when = get_cycles(); + cerr << '\t' << when << ' ' + << _locked + << " lock: " + << &lock << " at " + << line << " in " << file << endl; +#endif + } + + ~TentativeLockMonitor () { + if (_locked) { + lock.unlock (); +#ifdef DEBUG_LOCK_MONITOR + unsigned long long when; + when = get_cycles(); + cerr << '\t' << when << ' ' + << " UNLOCKED " + << &lock << " at " + << line << " in " << file << endl; +#endif + } + } + + bool locked() { return _locked; } + + private: + NonBlockingLock& lock; + bool _locked; +#ifdef DEBUG_LOCK_MONITOR + unsigned long line; + const char * file; +#endif +}; + +class SpinLockMonitor +{ + public: + SpinLockMonitor (pthread_mutex_t *lck, unsigned long l, const char *f) + : lock (lck) +#ifdef DEBUG_LOCK_MONITOR + , line (l), file (f) +#endif + { + +#ifdef DEBUG_LOCK_MONITOR + unsigned long long when; + when = get_cycles(); + cerr << when << " spinlock " << lck << " at " << line << " in " << file << endl; +#endif + pthread_mutex_spinlock (lck); +#ifdef DEBUG_LOCK_MONITOR + when = get_cycles(); + cerr << '\t' << when + << " locked at " + << &lock << " at " + << line << " in " << file << endl; +#endif + } + + ~SpinLockMonitor () { + pthread_mutex_unlock (lock); + } + private: + pthread_mutex_t *lock; +#ifdef DEBUG_LOCK_MONITOR + unsigned long line; + const char * file; +#endif +}; + +} /* namespace */ + +#endif /* __pbd_lockmonitor_h__*/ diff --git a/libs/pbd3/pbd/mountpoint.h b/libs/pbd3/pbd/mountpoint.h new file mode 100644 index 0000000000..86ccc58190 --- /dev/null +++ b/libs/pbd3/pbd/mountpoint.h @@ -0,0 +1,28 @@ +/* + Copyright (C) 1998-99 Paul Barton-Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __pbd_mountpoint_h__ +#define __pbd_mountpoint_h__ + +#include <string> + +std::string mountpoint (std::string path); + +#endif // __pbd_mountpoint_h__ diff --git a/libs/pbd3/pbd/pathscanner.h b/libs/pbd3/pbd/pathscanner.h new file mode 100644 index 0000000000..346e7858c4 --- /dev/null +++ b/libs/pbd3/pbd/pathscanner.h @@ -0,0 +1,66 @@ +#ifndef __libmisc_pathscanner_h__ +#define __libmisc_pathscanner_h__ + +#include <vector> +#include <string> +#include <regex.h> + +using std::string; +using std::vector; + +class PathScanner + +{ + public: + vector<string *> *operator() (const string &dirpath, + bool (*filter)(const string &, void *arg), + void *arg, + bool match_fullpath = true, + bool return_fullpath = true, + long limit = -1) { + return run_scan (dirpath, + (bool (PathScanner::*)(const string &)) 0, + filter, + arg, + match_fullpath, + return_fullpath, + limit); + } + + vector<string *> *operator() (const string &dirpath, + const string ®exp, + bool match_fullpath = true, + bool return_fullpath = true, + long limit = -1); + + + string *find_first (const string &dirpath, + const string ®exp, + bool match_fullpath = true, + bool return_fullpath = true); + + string *find_first (const string &dirpath, + bool (*filter)(const string &, void *), + void *arg, + bool match_fullpath = true, + bool return_fullpath = true); + + private: + regex_t compiled_pattern; + + bool regexp_filter (const string &str) { + return regexec (&compiled_pattern, str.c_str(), 0, 0, 0) == 0; + } + + vector<string *> *run_scan (const string &dirpath, + bool (PathScanner::*mfilter) (const string &), + bool (*filter)(const string &, void *), + void *arg, + bool match_fullpath, + bool return_fullpath, + long limit); + + +}; + +#endif // __libmisc_pathscanner_h__ diff --git a/libs/pbd3/pbd/platform.h b/libs/pbd3/pbd/platform.h new file mode 100644 index 0000000000..761195a31b --- /dev/null +++ b/libs/pbd3/pbd/platform.h @@ -0,0 +1,45 @@ +/* + Copyright (C) 1999 Paul Barton-Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __qm_platform_h__ +#define __qm_platform_h__ + +class Platform + +{ + public: + Platform () { + thePlatform = this; + } + virtual ~Platform () {} + + virtual int pre_config () { return 0;} + virtual int post_config () { return 0;} + virtual int pre_ui () { return 0; } + virtual int post_ui () { return 0; } + virtual int dsp_startup() { return 0; } + + static Platform *instance() { return thePlatform; } + + private: + static Platform *thePlatform; +}; + +#endif // __qm_platform_h__ diff --git a/libs/pbd3/pbd/platform_factory.h b/libs/pbd3/pbd/platform_factory.h new file mode 100644 index 0000000000..d5255ea212 --- /dev/null +++ b/libs/pbd3/pbd/platform_factory.h @@ -0,0 +1,12 @@ +#ifndef __platform_factory__ +#define __platform_factory__ + +#include <pbd/platform.h> + +class PlatformFactory { +public: + static Platform* create_platform (); +}; + + +#endif // __platform_factory__ diff --git a/libs/pbd3/pbd/pool.h b/libs/pbd3/pbd/pool.h new file mode 100644 index 0000000000..c8e9740acd --- /dev/null +++ b/libs/pbd3/pbd/pool.h @@ -0,0 +1,74 @@ +/* + Copyright (C) 1998-99 Paul Barton-Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __qm_pool_h__ +#define __qm_pool_h__ + +#include <vector> +#include <string> +#include <pthread.h> +#include <pbd/ringbuffer.h> + +class Pool +{ + public: + Pool (std::string name, unsigned long item_size, unsigned long nitems); + virtual ~Pool (); + + virtual void *alloc (); + virtual void release (void *); + + std::string name() const { return _name; } + + private: + RingBuffer<void*>* free_list; + std::string _name; + void *block; +}; + +class SingleAllocMultiReleasePool : public Pool +{ + public: + SingleAllocMultiReleasePool (std::string name, unsigned long item_size, unsigned long nitems); + ~SingleAllocMultiReleasePool (); + + virtual void *alloc (); + virtual void release (void *); + + private: + pthread_mutex_t lock; +}; + + +class MultiAllocSingleReleasePool : public Pool +{ + public: + MultiAllocSingleReleasePool (std::string name, unsigned long item_size, unsigned long nitems); + ~MultiAllocSingleReleasePool (); + + virtual void *alloc (); + virtual void release (void *); + + private: + pthread_mutex_t lock; +}; + + +#endif // __qm_pool_h__ diff --git a/libs/pbd3/pbd/position.h b/libs/pbd3/pbd/position.h new file mode 100644 index 0000000000..c8241af085 --- /dev/null +++ b/libs/pbd3/pbd/position.h @@ -0,0 +1,38 @@ +/* + Copyright (C) 1998-99 Paul Barton-Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __qui_position_h__ +#define __qui_position_h__ + +enum Position { + Top, + Left, + Right, + Bottom, + UpperLeft, + LowerLeft, + UpperRight, + LowerRight, + Center, + Nowhere, +}; + + +#endif // __qui_position_h__ diff --git a/libs/pbd3/pbd/precision_timer.h b/libs/pbd3/pbd/precision_timer.h new file mode 100644 index 0000000000..a103b4800d --- /dev/null +++ b/libs/pbd3/pbd/precision_timer.h @@ -0,0 +1,61 @@ +/* + Copyright (C) 1998-99 Paul Barton-Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __precision_timer_h__ +#define __precision_timer_h__ + +#include <pbd/cycles.h> + +typedef cycles_t precision_time_t; + +class PrecisionTimer { + public: + PrecisionTimer (); + + /* returns current time in microseconds since + the time base was created (which may be + the same as when the PrecisionTimer was + created or it may not). + */ + +#ifdef PBD_HAVE_CYCLE_COUNTER + + precision_time_t current () { + return get_cycles() / cycles_per_usec; + } + +#else /* !HAVE_CYCLE_COUNTER */ + + precision_time_t current () { + struct timeval now; + gettimeofday (&now, 0); + return (precision_time_t) ((now.tv_sec * 1000000) + now.tv_usec); + } + +#endif /* HAVE_CYCLE_COUNTER */ + + private: + int get_mhz(); + static precision_time_t cycles_per_usec; +}; + +#endif // __precision_timer.h + + diff --git a/libs/pbd3/pbd/pthread_spinlock.h b/libs/pbd3/pbd/pthread_spinlock.h new file mode 100644 index 0000000000..71835221fa --- /dev/null +++ b/libs/pbd3/pbd/pthread_spinlock.h @@ -0,0 +1,29 @@ +/* + Copyright (C) 1998-99 Paul Barton-Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ +#ifndef __pthread_mutex_spinlock_h__ +#define __pthread_mutex_spinlock_h__ + +#include <pthread.h> + +extern unsigned int pthread_calibrate_spinlimit (); +extern void pthread_set_spinlimit (unsigned int spins); +extern int pthread_mutex_spinlock (pthread_mutex_t *mp); + +#endif // __pthread_mutex_spinlock_h__ diff --git a/libs/pbd3/pbd/pthread_utils.h b/libs/pbd3/pbd/pthread_utils.h new file mode 100644 index 0000000000..9c7cefd3e4 --- /dev/null +++ b/libs/pbd3/pbd/pthread_utils.h @@ -0,0 +1,21 @@ +#ifndef __pbd_pthread_utils__ +#define __pbd_pthread_utils__ + +#include <pthread.h> +#include <signal.h> +#include <string> + +#include <sigc++/sigc++.h> + +int pthread_create_and_store (std::string name, pthread_t *thread, pthread_attr_t *attr, void * (*start_routine)(void *), void * arg); +void pthread_cancel_one (pthread_t thread); +void pthread_kill_all (int signum); +void pthread_cancel_all (); +void pthread_exit_pbd (void* status); +std::string pthread_name (); + +namespace PBD { + extern sigc::signal<void,pthread_t,std::string> ThreadCreated; +} + +#endif /* __pbd_pthread_utils__ */ diff --git a/libs/pbd3/pbd/rcpointer.h b/libs/pbd3/pbd/rcpointer.h new file mode 100644 index 0000000000..c634208437 --- /dev/null +++ b/libs/pbd3/pbd/rcpointer.h @@ -0,0 +1,61 @@ +/* + Copyright (C) 1998-99 Paul Barton-Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __qm_rcpointer_h__ +#define __qm_rcpointer_h__ + +template<class T> class RCPointer { + public: + T *operator->() { return _ptr; } + bool operator==(T *p) { return _ptr == p; } + bool operator!=(T *p) { return _ptr != p; } + + int refcount() { return _ptr->count; } + + RCPointer () { _ptr = 0; } + + RCPointer (T *p) : _ptr (p) { + if (_ptr) _ptr->count++; + } + + RCPointer (const RCPointer& r) : _ptr (r._ptr) { + if (_ptr) _ptr->count++; + } + + RCPointer &operator= (const RCPointer &r) { + if (_ptr == r._ptr) return *this; + if (_ptr && --_ptr->count == 0) { + delete _ptr; + } + _ptr = r._ptr; + if (_ptr) _ptr->count++; + return *this; + } + ~RCPointer () { + if (_ptr && --_ptr->count == 0) { + delete _ptr; + } + } + + private: + T *_ptr; +}; + +#endif // __qm_rcpointer_h__ diff --git a/libs/pbd3/pbd/receiver.h b/libs/pbd3/pbd/receiver.h new file mode 100644 index 0000000000..b55e28f5ee --- /dev/null +++ b/libs/pbd3/pbd/receiver.h @@ -0,0 +1,50 @@ +/* + Copyright (C) 1998-99 Paul Barton-Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __libmisc_receiver_h__ +#define __libmisc_receiver_h__ + +#include <vector> + +#include <sigc++/sigc++.h> + +#include "transmitter.h" + +using std::vector; + +class strstream; + +class Receiver : public sigc::trackable +{ + public: + Receiver (); + virtual ~Receiver (); + + void listen_to (Transmitter &); + void hangup (); + + protected: + virtual void receive (Transmitter::Channel, const char *) = 0; + + private: + vector<sigc::connection *> connections; +}; + +#endif // __libmisc_receiver_h__ diff --git a/libs/pbd3/pbd/relation.h b/libs/pbd3/pbd/relation.h new file mode 100644 index 0000000000..f28aaecfa1 --- /dev/null +++ b/libs/pbd3/pbd/relation.h @@ -0,0 +1,35 @@ +/* + Copyright (C) 1999 Paul Barton-Davis + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __pbd_relation_h__ +#define __pbd_relation_h__ + +enum RelationalCondition { + Equal = 0, + NotEqual, + LessThan, + LessThanOrEqual, + GreaterThan, + GreaterThanOrEqual, + Changed, + + NumConditions +}; + +#endif // __pbd_relation_h__ diff --git a/libs/pbd3/pbd/restartable_rw.h b/libs/pbd3/pbd/restartable_rw.h new file mode 100644 index 0000000000..ee84e4e295 --- /dev/null +++ b/libs/pbd3/pbd/restartable_rw.h @@ -0,0 +1,7 @@ +#ifndef __libmisc_restartable_rw__h__ +#define __libmisc_restartable_rw__h__ + +extern int restartable_write (int fd, unsigned char *buf, size_t cnt); +extern int restartable_read (int fd, unsigned char *buf, size_t cnt); + +#endif // __libmisc_restartable_rw__h__ diff --git a/libs/pbd3/pbd/ringbuffer.h b/libs/pbd3/pbd/ringbuffer.h new file mode 100644 index 0000000000..cca9cbfc01 --- /dev/null +++ b/libs/pbd3/pbd/ringbuffer.h @@ -0,0 +1,283 @@ +/* + Copyright (C) 2000 Paul Davis & Benno Senoner + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef ringbuffer_h +#define ringbuffer_h + +#include <sys/mman.h> +#include <pbd/atomic.h> + +template<class T> +class RingBuffer +{ + public: + RingBuffer (size_t sz) { + size_t power_of_two; + + for (power_of_two = 1; 1U<<power_of_two < sz; power_of_two++); + + size = 1<<power_of_two; + size_mask = size; + size_mask -= 1; + buf = new T[size]; + reset (); + + }; + + virtual ~RingBuffer() { + delete [] buf; + } + + void reset () { + /* !!! NOT THREAD SAFE !!! */ + atomic_set (&write_ptr, 0); + atomic_set (&read_ptr, 0); + } + + void set (size_t r, size_t w) { + /* !!! NOT THREAD SAFE !!! */ + atomic_set (&write_ptr, w); + atomic_set (&read_ptr, r); + } + + size_t read (T *dest, size_t cnt); + size_t write (T *src, size_t cnt); + + struct rw_vector { + T *buf[2]; + size_t len[2]; + }; + + void get_read_vector (rw_vector *); + void get_write_vector (rw_vector *); + + void decrement_read_ptr (size_t cnt) { + atomic_set (&read_ptr, (atomic_read(&read_ptr) - cnt) & size_mask); + } + + void increment_read_ptr (size_t cnt) { + atomic_set (&read_ptr, (atomic_read(&read_ptr) + cnt) & size_mask); + } + + void increment_write_ptr (size_t cnt) { + atomic_set (&write_ptr, (atomic_read(&write_ptr) + cnt) & size_mask); + } + + size_t write_space () { + size_t w, r; + + w = atomic_read (&write_ptr); + r = atomic_read (&read_ptr); + + if (w > r) { + return ((r - w + size) & size_mask) - 1; + } else if (w < r) { + return (r - w) - 1; + } else { + return size - 1; + } + } + + size_t read_space () { + size_t w, r; + + w = atomic_read (&write_ptr); + r = atomic_read (&read_ptr); + + if (w > r) { + return w - r; + } else { + return (w - r + size) & size_mask; + } + } + + T *buffer () { return buf; } + size_t get_write_ptr () const { return atomic_read (&write_ptr); } + size_t get_read_ptr () const { return atomic_read (&read_ptr); } + size_t bufsize () const { return size; } + + protected: + T *buf; + size_t size; + atomic_t write_ptr; + atomic_t read_ptr; + size_t size_mask; +}; + +template<class T> size_t +RingBuffer<T>::read (T *dest, size_t cnt) +{ + size_t free_cnt; + size_t cnt2; + size_t to_read; + size_t n1, n2; + size_t priv_read_ptr; + + priv_read_ptr=atomic_read(&read_ptr); + + if ((free_cnt = read_space ()) == 0) { + return 0; + } + + to_read = cnt > free_cnt ? free_cnt : cnt; + + cnt2 = priv_read_ptr + to_read; + + if (cnt2 > size) { + n1 = size - priv_read_ptr; + n2 = cnt2 & size_mask; + } else { + n1 = to_read; + n2 = 0; + } + + memcpy (dest, &buf[priv_read_ptr], n1 * sizeof (T)); + priv_read_ptr = (priv_read_ptr + n1) & size_mask; + + if (n2) { + memcpy (dest+n1, buf, n2 * sizeof (T)); + priv_read_ptr = n2; + } + + atomic_set(&read_ptr, priv_read_ptr); + return to_read; +} + +template<class T> size_t +RingBuffer<T>::write (T *src, size_t cnt) + +{ + size_t free_cnt; + size_t cnt2; + size_t to_write; + size_t n1, n2; + size_t priv_write_ptr; + + priv_write_ptr=atomic_read(&write_ptr); + + if ((free_cnt = write_space ()) == 0) { + return 0; + } + + to_write = cnt > free_cnt ? free_cnt : cnt; + + cnt2 = priv_write_ptr + to_write; + + if (cnt2 > size) { + n1 = size - priv_write_ptr; + n2 = cnt2 & size_mask; + } else { + n1 = to_write; + n2 = 0; + } + + memcpy (&buf[priv_write_ptr], src, n1 * sizeof (T)); + priv_write_ptr = (priv_write_ptr + n1) & size_mask; + + if (n2) { + memcpy (buf, src+n1, n2 * sizeof (T)); + priv_write_ptr = n2; + } + + atomic_set(&write_ptr, priv_write_ptr); + return to_write; +} + +template<class T> void +RingBuffer<T>::get_read_vector (RingBuffer<T>::rw_vector *vec) + +{ + size_t free_cnt; + size_t cnt2; + size_t w, r; + + w = atomic_read (&write_ptr); + r = atomic_read (&read_ptr); + + if (w > r) { + free_cnt = w - r; + } else { + free_cnt = (w - r + size) & size_mask; + } + + cnt2 = r + free_cnt; + + if (cnt2 > size) { + /* Two part vector: the rest of the buffer after the + current write ptr, plus some from the start of + the buffer. + */ + + vec->buf[0] = &buf[r]; + vec->len[0] = size - r; + vec->buf[1] = buf; + vec->len[1] = cnt2 & size_mask; + + } else { + + /* Single part vector: just the rest of the buffer */ + + vec->buf[0] = &buf[r]; + vec->len[0] = free_cnt; + vec->len[1] = 0; + } +} + +template<class T> void +RingBuffer<T>::get_write_vector (RingBuffer<T>::rw_vector *vec) + +{ + size_t free_cnt; + size_t cnt2; + size_t w, r; + + w = atomic_read (&write_ptr); + r = atomic_read (&read_ptr); + + if (w > r) { + free_cnt = ((r - w + size) & size_mask) - 1; + } else if (w < r) { + free_cnt = (r - w) - 1; + } else { + free_cnt = size - 1; + } + + cnt2 = w + free_cnt; + + if (cnt2 > size) { + + /* Two part vector: the rest of the buffer after the + current write ptr, plus some from the start of + the buffer. + */ + + vec->buf[0] = &buf[w]; + vec->len[0] = size - w; + vec->buf[1] = buf; + vec->len[1] = cnt2 & size_mask; + } else { + vec->buf[0] = &buf[w]; + vec->len[0] = free_cnt; + vec->len[1] = 0; + } +} + + +#endif /* __ringbuffer_h__ */ diff --git a/libs/pbd3/pbd/ringbufferNPT.h b/libs/pbd3/pbd/ringbufferNPT.h new file mode 100644 index 0000000000..d0562ec76b --- /dev/null +++ b/libs/pbd3/pbd/ringbufferNPT.h @@ -0,0 +1,272 @@ +/* + Copyright (C) 2000 Paul Davis & Benno Senoner + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef ringbuffer_npt_h +#define ringbuffer_npt_h + +#include <sys/mman.h> +#include <pbd/atomic.h> + +template<class T> +class RingBufferNPT +{ + public: + RingBufferNPT (size_t sz) { + size = sz; + buf = new T[size]; + reset (); + + }; + + virtual ~RingBufferNPT() { + delete [] buf; + } + + void reset () { + /* !!! NOT THREAD SAFE !!! */ + atomic_set (&write_ptr, 0); + atomic_set (&read_ptr, 0); + } + + void set (size_t r, size_t w) { + /* !!! NOT THREAD SAFE !!! */ + atomic_set (&write_ptr, w); + atomic_set (&read_ptr, r); + } + + size_t read (T *dest, size_t cnt); + size_t write (T *src, size_t cnt); + + struct rw_vector { + T *buf[2]; + size_t len[2]; + }; + + void get_read_vector (rw_vector *); + void get_write_vector (rw_vector *); + + void decrement_read_ptr (size_t cnt) { + atomic_set (&read_ptr, (atomic_read(&read_ptr) - cnt) % size); + } + + void increment_read_ptr (size_t cnt) { + atomic_set (&read_ptr, (atomic_read(&read_ptr) + cnt) % size); + } + + void increment_write_ptr (size_t cnt) { + atomic_set (&write_ptr, (atomic_read(&write_ptr) + cnt) % size); + } + + size_t write_space () { + size_t w, r; + + w = atomic_read (&write_ptr); + r = atomic_read (&read_ptr); + + if (w > r) { + return ((r - w + size) % size) - 1; + } else if (w < r) { + return (r - w) - 1; + } else { + return size - 1; + } + } + + size_t read_space () { + size_t w, r; + + w = atomic_read (&write_ptr); + r = atomic_read (&read_ptr); + + if (w > r) { + return w - r; + } else { + return (w - r + size) % size; + } + } + + T *buffer () { return buf; } + size_t get_write_ptr () const { return atomic_read (&write_ptr); } + size_t get_read_ptr () const { return atomic_read (&read_ptr); } + size_t bufsize () const { return size; } + + protected: + T *buf; + size_t size; + atomic_t write_ptr; + atomic_t read_ptr; +}; + +template<class T> size_t +RingBufferNPT<T>::read (T *dest, size_t cnt) +{ + size_t free_cnt; + size_t cnt2; + size_t to_read; + size_t n1, n2; + size_t priv_read_ptr; + + priv_read_ptr=atomic_read(&read_ptr); + + if ((free_cnt = read_space ()) == 0) { + return 0; + } + + to_read = cnt > free_cnt ? free_cnt : cnt; + + cnt2 = priv_read_ptr + to_read; + + if (cnt2 > size) { + n1 = size - priv_read_ptr; + n2 = cnt2 % size; + } else { + n1 = to_read; + n2 = 0; + } + + memcpy (dest, &buf[priv_read_ptr], n1 * sizeof (T)); + priv_read_ptr = (priv_read_ptr + n1) % size; + + if (n2) { + memcpy (dest+n1, buf, n2 * sizeof (T)); + priv_read_ptr = n2; + } + + atomic_set(&read_ptr, priv_read_ptr); + return to_read; +} + +template<class T> size_t +RingBufferNPT<T>::write (T *src, size_t cnt) +{ + size_t free_cnt; + size_t cnt2; + size_t to_write; + size_t n1, n2; + size_t priv_write_ptr; + + priv_write_ptr=atomic_read(&write_ptr); + + if ((free_cnt = write_space ()) == 0) { + return 0; + } + + to_write = cnt > free_cnt ? free_cnt : cnt; + + cnt2 = priv_write_ptr + to_write; + + if (cnt2 > size) { + n1 = size - priv_write_ptr; + n2 = cnt2 % size; + } else { + n1 = to_write; + n2 = 0; + } + + memcpy (&buf[priv_write_ptr], src, n1 * sizeof (T)); + priv_write_ptr = (priv_write_ptr + n1) % size; + + if (n2) { + memcpy (buf, src+n1, n2 * sizeof (T)); + priv_write_ptr = n2; + } + + atomic_set(&write_ptr, priv_write_ptr); + return to_write; +} + +template<class T> void +RingBufferNPT<T>::get_read_vector (RingBufferNPT<T>::rw_vector *vec) +{ + size_t free_cnt; + size_t cnt2; + size_t w, r; + + w = atomic_read (&write_ptr); + r = atomic_read (&read_ptr); + + if (w > r) { + free_cnt = w - r; + } else { + free_cnt = (w - r + size) % size; + } + + cnt2 = r + free_cnt; + + if (cnt2 > size) { + /* Two part vector: the rest of the buffer after the + current write ptr, plus some from the start of + the buffer. + */ + + vec->buf[0] = &buf[r]; + vec->len[0] = size - r; + vec->buf[1] = buf; + vec->len[1] = cnt2 % size; + + } else { + + /* Single part vector: just the rest of the buffer */ + + vec->buf[0] = &buf[r]; + vec->len[0] = free_cnt; + vec->len[1] = 0; + } +} + +template<class T> void +RingBufferNPT<T>::get_write_vector (RingBufferNPT<T>::rw_vector *vec) +{ + size_t free_cnt; + size_t cnt2; + size_t w, r; + + w = atomic_read (&write_ptr); + r = atomic_read (&read_ptr); + + if (w > r) { + free_cnt = ((r - w + size) % size) - 1; + } else if (w < r) { + free_cnt = (r - w) - 1; + } else { + free_cnt = size - 1; + } + + cnt2 = w + free_cnt; + + if (cnt2 > size) { + + /* Two part vector: the rest of the buffer after the + current write ptr, plus some from the start of + the buffer. + */ + + vec->buf[0] = &buf[w]; + vec->len[0] = size - w; + vec->buf[1] = buf; + vec->len[1] = cnt2 % size; + } else { + vec->buf[0] = &buf[w]; + vec->len[0] = free_cnt; + vec->len[1] = 0; + } +} + +#endif /* __ringbuffer_npt_h__ */ diff --git a/libs/pbd3/pbd/rt.h b/libs/pbd3/pbd/rt.h new file mode 100644 index 0000000000..aa954fcd42 --- /dev/null +++ b/libs/pbd3/pbd/rt.h @@ -0,0 +1,25 @@ +/* + Copyright (C) 1998-99 Paul Barton-Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ +#ifndef __libmisc_rt_h__ +#define __libmisc_rt_h__ + +extern int become_real_time_thread (int rt_priorty = 10, bool fifo = true); + +#endif // __libmisc_rt_h__ diff --git a/libs/pbd3/pbd/rtthread.h b/libs/pbd3/pbd/rtthread.h new file mode 100644 index 0000000000..b99c69ba79 --- /dev/null +++ b/libs/pbd3/pbd/rtthread.h @@ -0,0 +1,30 @@ +/* + Copyright (C) 1998-99 Paul Barton-Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ +#ifndef __rtthread_h__ +#define __rtthread_h__ + +#include <pthread.h> + +extern int pthread_create_realtime (pthread_t *new_thread, + void *(*start)(void *), void *arg, + int priority = 10); + + +#endif // __rtthread_h__ diff --git a/libs/pbd3/pbd/scale.h b/libs/pbd3/pbd/scale.h new file mode 100644 index 0000000000..0384ae52aa --- /dev/null +++ b/libs/pbd3/pbd/scale.h @@ -0,0 +1,53 @@ +/* + Copyright (C) 2000 Paul Barton-Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __pbd_scale_h__ +#define __pbd_scale_h__ + +#include <cmath> + +inline float +scale (float value, float lower, float upper) +{ + return fabs (lower + value) / (upper-lower); +} + +inline float +scale_with_range (float value, float lower, float range) +{ + return fabs (lower + value) / range; +} + + +inline float +scale_to (float value, float lower, float upper, float to) +{ + return (fabs (lower + value) / (upper-lower)) * to; +} + +inline float +scale_to_with_range (float value, float lower, float range, float to) +{ + return (fabs (lower + value) / range) * to; +} + +#endif /* __pbd_scale_h__ */ + + diff --git a/libs/pbd3/pbd/selectable.h b/libs/pbd3/pbd/selectable.h new file mode 100644 index 0000000000..470bc3cfcc --- /dev/null +++ b/libs/pbd3/pbd/selectable.h @@ -0,0 +1,102 @@ +/* + Copyright (C) 1998-99 Paul Barton-Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __selectable_h__ +#define __selectable_h__ + +#include <list> +#include <string> +#include <stdio.h> + +#include <sigc++/sigc++.h> + +#include <sys/types.h> + +namespace Select { + enum Condition { + Readable = 0x1, + Writable = 0x2, + Exception = 0x4 + }; + +class Selectable : public sigc::trackable + +{ + public: + Selectable (int fd); + Selectable (const std::string &, int flags, int mode = 0); + Selectable (FILE *); + ~Selectable (); + + sigc::signal<void,Selectable *,Select::Condition> readable; + sigc::signal<void,Selectable *,Select::Condition> writable; + sigc::signal<void,Selectable *,Select::Condition> exceptioned; + + int fd() { return _fd; } + bool ok() { return _ok; } + + protected: + void selected (unsigned int condition); + int condition; + int _fd; + + friend class Selector; + + private: + enum { + fromFD, + fromPath, + fromFILE + }; + + bool _ok; + int _type; + std::string path; +}; + +class Selector { + private: + int post_select (fd_set *, fd_set *, fd_set *); + int _max_fd; + + typedef std::list<Selectable *> Selectables; + Selectables selectables; + pthread_mutex_t list_lock; + + static bool use_list_lock; + + public: + Selector (); + + void multithreaded (bool yn) { + use_list_lock = yn; + } + + void add (int condition, Selectable *s); + void remove (Selectable *); + int select (unsigned long usecs); +}; + + + +} /* namespace */ + + +#endif // __selectable_h__ diff --git a/libs/pbd3/pbd/solaris_platform.h b/libs/pbd3/pbd/solaris_platform.h new file mode 100644 index 0000000000..6f39a77f73 --- /dev/null +++ b/libs/pbd3/pbd/solaris_platform.h @@ -0,0 +1,41 @@ +/* + Copyright (C) 1999 Paul Barton-Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __solaris_platform_h__ +#define __solaris_platform_h__ + +#include <pbd/platform.h> + +class SolarisPlatform : public Platform +{ + public: + SolarisPlatform () : Platform () {}; + ~SolarisPlatform () {}; + + int pre_config (); + int post_config (); + int pre_ui (); + int post_ui (); + + int dsp_startup() { return 0; } + +}; + +#endif // __solaris_platform_h__ diff --git a/libs/pbd3/pbd/stl_delete.h b/libs/pbd3/pbd/stl_delete.h new file mode 100644 index 0000000000..6e5bfa0734 --- /dev/null +++ b/libs/pbd3/pbd/stl_delete.h @@ -0,0 +1,89 @@ +/* + Copyright (C) 1998-99 Paul Barton-Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __libmisc_stl_delete_h__ +#define __libmisc_stl_delete_h__ + +/* To actually use any of these deletion functions, you need to + first include the revelant container type header. +*/ +#if defined(_CPP_VECTOR) || defined(_GLIBCXX_VECTOR) || defined(__SGI_STL_VECTOR) +template<class T> void vector_delete (std::vector<T *> *vec) +{ + typename std::vector<T *>::iterator i; + + for (i = vec->begin(); i != vec->end(); i++) { + delete *i; + } + vec->clear (); +} +#endif // _CPP_VECTOR || _GLIBCXX_VECTOR || __SGI_STL_VECTOR + +#if defined(_CPP_MAP) || defined(_GLIBCXX_MAP) || defined(__SGI_STL_MAP) +template<class K, class T> void map_delete (std::map<K, T *> *m) +{ + typename std::map<K, T *>::iterator i; + + for (i = m->begin(); i != m->end(); i++) { + delete (*i).second; + } + m->clear (); +} +#endif // _CPP_MAP || _GLIBCXX_MAP || __SGI_STL_MAP + +#if defined(_CPP_LIST) || defined(_GLIBCXX_LIST) || defined(__SGI_STL_LIST) +template<class T> void list_delete (std::list<T *> *l) +{ + typename std::list<T *>::iterator i; + + for (i = l->begin(); i != l->end(); i++) { + delete (*i); + } + + l->clear (); +} +#endif // _CPP_LIST || _GLIBCXX_LIST || __SGI_STL_LIST + +#if defined(_CPP_SLIST) || defined(_GLIBCXX_SLIST) || defined(__SGI_STL_SLIST) +template<class T> void slist_delete (std::slist<T *> *l) +{ + typename std::slist<T *>::iterator i; + + for (i = l->begin(); i != l->end(); i++) { + delete (*i); + } + + l->clear (); +} +#endif // _CPP_SLIST || _GLIBCXX_SLIST || __SGI_STL_SLIST + +#if defined(_CPP_SET) || defined(_GLIBCXX_SET) || defined(__SGI_STL_SET) +template<class T> void set_delete (std::set<T *> *sset) +{ + typename std::set<T *>::iterator i; + + for (i = sset->begin(); i != sset->end(); i++) { + delete *i; + } + sset->erase (sset->begin(), sset->end()); +} +#endif // _CPP_SET || _GLIBCXX_SET || __SGI_STL_SET + +#endif // __libmisc_stl_delete_h__ diff --git a/libs/pbd3/pbd/stl_functors.h b/libs/pbd3/pbd/stl_functors.h new file mode 100644 index 0000000000..4a96e91a28 --- /dev/null +++ b/libs/pbd3/pbd/stl_functors.h @@ -0,0 +1,93 @@ +/* + Copyright (C) 1998-99 Paul Barton-Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __stl_functors_h__ +#define __stl_functors_h__ + +#include <string> + +#ifndef LESS_STRING_P +struct less<std::string *> { + bool operator()(std::string *s1, std::string *s2) const { + return *s1 < *s2; + } +}; +#define LESS_STRING_P +#endif // LESS_STRING_P + +#ifndef LESS_CONST_STRING_P +struct less<const std::string *> { + bool operator()(const std::string *s1, const std::string *s2) const { + return *s1 < *s2; + } +}; +#define LESS_CONST_STRING_P +#endif // LESS_CONST_STRING_P + +#ifndef LESS_CONST_CHAR_P +struct less<const char *> +{ + bool operator()(const char* s1, const char* s2) const { + return strcmp(s1, s2) < 0; + } +}; +#define LESS_CONST_CHAR_P +#endif // LESS_CONST_CHAR_P + +#ifndef LESS_CONST_FLOAT_P +struct less<const float *> +{ + bool operator()(const float *n1, const float *n2) const { + return *n1 < *n2; + } +}; +#define LESS_CONST_FLOAT_P +#endif // LESS_CONST_FLOAT_P + +#ifndef EQUAL_TO_CONST_CHAR_P +struct equal_to<const char *> +{ + bool operator()(const char *s1, const char *s2) const { + return strcmp (s1, s2) == 0; + } +}; +#define EQUAL_TO_CONST_CHAR_P +#endif // EQUAL_TO_CONST_CHAR_P + +#ifndef EQUAL_TO_STRING_P +struct equal_to<std::string *> +{ + bool operator()(const std::string *s1, const std::string *s2) const { + return *s1 == *s2; + } +}; +#define EQUAL_TO_STRING_P +#endif // EQUAL_TO_STRING_P + +#ifndef LESS_CONST_STRING_R +struct less<const std::string &> { + bool operator() (const std::string &s1, const std::string &s2) { + return s1 < s2; + } +}; +#define LESS_CONST_STRING_R +#endif // EQUAL_TO_STRING_P + +#endif // __stl_functors_h__ diff --git a/libs/pbd3/pbd/strsplit.h b/libs/pbd3/pbd/strsplit.h new file mode 100644 index 0000000000..e55ad1c825 --- /dev/null +++ b/libs/pbd3/pbd/strsplit.h @@ -0,0 +1,9 @@ +#ifndef __pbd_strplit_h__ +#define __pbd_strplit_h__ + +#include <string> +#include <vector> + +extern void split (std::string, std::vector<std::string>&, char); + +#endif // __pbd_strplit_h__ diff --git a/libs/pbd3/pbd/strsub.h b/libs/pbd3/pbd/strsub.h new file mode 100644 index 0000000000..c5bfb1ade4 --- /dev/null +++ b/libs/pbd3/pbd/strsub.h @@ -0,0 +1,25 @@ +/* + Copyright (C) 1998-99 Paul Barton-Davis + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __libmisc_strsub_h__ +#define __libmisc_strsub_h__ + +extern char *strsub (char *str, const char *target, const char *replacement); + +#endif // __libmisc_strsub_h__ diff --git a/libs/pbd3/pbd/textreceiver.h b/libs/pbd3/pbd/textreceiver.h new file mode 100644 index 0000000000..b8bfe5bc78 --- /dev/null +++ b/libs/pbd3/pbd/textreceiver.h @@ -0,0 +1,44 @@ +/* + Copyright (C) 1998-99 Paul Barton-Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __libmisc_textreceiver_h__ +#define __libmisc_textreceiver_h__ + +#include <string> + +#include "receiver.h" + +using std::string; +using std::cout; +using std::endl; + +class TextReceiver : public Receiver +{ + public: + TextReceiver (const string &n); + + protected: + void receive (Transmitter::Channel, const char *); + + private: + string name; +}; + +#endif //__libmisc_textreceiver_h__ diff --git a/libs/pbd3/pbd/thread.h b/libs/pbd3/pbd/thread.h new file mode 100644 index 0000000000..c1d5c3c78d --- /dev/null +++ b/libs/pbd3/pbd/thread.h @@ -0,0 +1,127 @@ +/* + Copyright (C) 1998-99 Paul Barton-Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __qm_thread_h__ +#define __qm_thread_h__ + +#include <pthread.h> + +/* A generic base class for Quasimodo objects requiring their own + thread to do work. +*/ + +class QMThread + +{ + public: + QMThread (const char *name, + void *(start)(void *), void *, + bool realtime = false, int rt_priority = 10); + + virtual ~QMThread(); + + int run (); + void poke (); + void pause (); + void stop (); + void *wait (); + + /* This doesn't guarantee anything about the state of + the thread, but if you do things the right way, and + make sure that the do_work() routine checks + work_no_more() at the right times, and that the + thread is awake, then calling this will cause + the thread to exit fairly quickly. + */ + + void halt() { _must_exit = true ; } + + void exit (void *status); + pthread_t thread_id() { return _thread; } + + bool thread_ok () { return _have_thread; } + bool thread_active() { return _thread_active; } + + bool thread_running () { + /* XXX not atomic */ + return _running && _thread_active; + } + + bool thread_waiting () { return _thread_waiting; } + + static void try_to_kill_all_threads() { + all_threads_must_die = true; + } + + protected: + void *main (); + + bool work_no_more () { return (!_running || _must_exit || all_threads_must_die); } + + bool myself () { + return pthread_equal (_thread, pthread_self()); + } + + void suspend() { + _running = false; + } + + void lock (pthread_mutex_t *lock) { + pthread_mutex_lock (lock); + } + + void unlock (pthread_mutex_t *lock) { + pthread_mutex_unlock (lock); + } + + virtual void *do_work () = 0; + + private: + const char *_name; + bool _must_exit; + bool _running; + bool _thread_active; + bool _thread_waiting; + bool _have_thread; + + size_t work_cnt; + + pthread_mutex_t status_lock; + pthread_cond_t wake_up; /* protected by status_lock */ + pthread_cond_t asleep; /* protected by status_lock */ + pthread_cond_t running; /* protected by status_lock */ + pthread_cond_t exited; /* protected by status_lock */ + pthread_t _thread; + + void lock () { + pthread_mutex_lock (&status_lock); + } + + void unlock () { + pthread_mutex_unlock (&status_lock); + } + + static bool all_threads_must_die; + + static void signal_catcher (int sig); + void setup_signals (); +}; + +#endif // __qm_thread_h__ diff --git a/libs/pbd3/pbd/thrown_error.h b/libs/pbd3/pbd/thrown_error.h new file mode 100644 index 0000000000..83cf8acfac --- /dev/null +++ b/libs/pbd3/pbd/thrown_error.h @@ -0,0 +1,39 @@ +/* + Copyright (C) 1998-99 Paul Barton-Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ +#ifndef __qm_thrown_error_h__ +#define __qm_thrown_error_h__ + +#include "transmitter.h" + +#define SAFE_THROW(T) \ + T *sent = new T; \ + (*sent) << rdbuf(); \ + throw sent + +class ThrownError : public Transmitter { + public: + ThrownError () : Transmitter (Transmitter::Throw) {} + protected: + virtual void deliver () = 0; +}; + +#endif // __qm_thrown_error_h__ + + diff --git a/libs/pbd3/pbd/touchable.h b/libs/pbd3/pbd/touchable.h new file mode 100644 index 0000000000..0298574dfa --- /dev/null +++ b/libs/pbd3/pbd/touchable.h @@ -0,0 +1,89 @@ +/* + Copyright (C) 1999 Paul Barton-Davis + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __pbd_touchable_h__ +#define __pbd_touchable_h__ + +class Touchable +{ + public: + Touchable() : _delete_after_touch (false) {} + virtual ~Touchable() {} + + void set_delete_after_touch (bool yn) { _delete_after_touch = yn; } + bool delete_after_touch() const { return _delete_after_touch; } + + virtual void touch () = 0; + + protected: + bool _delete_after_touch; +}; + +template<class T> +class DynamicTouchable : public Touchable +{ + public: + DynamicTouchable (T& t, void (T::*m)(void)) + : object (t), method (m) { set_delete_after_touch (true); } + + void touch () { + (object.*method)(); + } + + protected: + T& object; + void (T::*method)(void); +}; + +template<class T1, class T2> +class DynamicTouchable1 : public Touchable +{ + public: + DynamicTouchable1 (T1& t, void (T1::*m)(T2), T2 a) + : object (t), method (m), arg (a) { set_delete_after_touch (true); } + + void touch () { + (object.*method)(arg); + } + + protected: + T1& object; + void (T1::*method)(T2); + T2 arg; +}; + +template<class T1, class T2, class T3> +class DynamicTouchable2 : public Touchable +{ + public: + DynamicTouchable2 (T1& t, void (T1::*m)(T2, T3), T2 a1, T3 a2) + : object (t), method (m), arg1 (a1), arg2 (a2) { set_delete_after_touch (true); } + + void touch () { + (object.*method)(arg1, arg2); + } + + protected: + T1& object; + void (T1::*method)(T2,T3); + T2 arg1; + T3 arg2; +}; + +#endif // __pbd_touchable_h__ diff --git a/libs/pbd3/pbd/transmitter.h b/libs/pbd3/pbd/transmitter.h new file mode 100644 index 0000000000..07fc266bce --- /dev/null +++ b/libs/pbd3/pbd/transmitter.h @@ -0,0 +1,109 @@ +/* + Copyright (C) 1998-99 Paul Barton-Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __libmisc_transmitter_h__ +#define __libmisc_transmitter_h__ + +#include <sstream> +#include <iostream> + +#include <sigc++/sigc++.h> + +using std::cout; +using std::cerr; +using std::endl; + +class Transmitter : public std::stringstream + +{ + public: + enum Channel { + Info, + Error, + Warning, + Fatal, + Throw + }; + + Transmitter (Channel); + + sigc::signal<void,Channel, const char *> &sender() { + return *send; + } + + bool does_not_return (); + + protected: + virtual void deliver (); + friend std::ostream& endmsg (std::ostream &); + + private: + Channel channel; + sigc::signal<void, Channel, const char *> *send; + + sigc::signal<void, Channel, const char *> info; + sigc::signal<void, Channel, const char *> warning; + sigc::signal<void, Channel, const char *> error; + sigc::signal<void, Channel, const char *> fatal; +}; + +/* for EGCS 2.91.66, if this function is not compiled within the same + compilation unit as the one where a ThrownError is thrown, then + nothing will catch the error. This is a pretty small function, so + inlining it here seems like a reasonable workaround. +*/ + +inline std::ostream & +endmsg (std::ostream &ostr) + +{ + Transmitter *t; + + /* There is a serious bug in the Cygnus/GCC libstdc++ library: + cout is not actually an ostream, but a trick was played + to make the compiler think that it is. This will cause + the dynamic_cast<> to fail with SEGV. So, first check to + see if ostr == cout, and handle it specially. + */ + + if (&ostr == &cout) { + cout << endl; + return ostr; + } else if (&ostr == &cerr) { + cerr << endl; + return ostr; + } + + if ((t = dynamic_cast<Transmitter *> (&ostr)) != 0) { + t->deliver (); + } else { + /* hmm. not a Transmitter, so just put a newline on + it and assume that that will be enough. + */ + + ostr << endl; + } + + return ostr; +} + +extern "C" { void pbd_c_error (const char *); } + +#endif // __libmisc_transmitter_h__ diff --git a/libs/pbd3/pbd/types.h b/libs/pbd3/pbd/types.h new file mode 100644 index 0000000000..52f067fd04 --- /dev/null +++ b/libs/pbd3/pbd/types.h @@ -0,0 +1,32 @@ +/* + Copyright (C) 1999 Paul Barton-Davis + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __pbd_types_h__ +#define __pbd_types_h__ + +typedef unsigned char byte; +typedef char int8; +typedef unsigned short uint16; +typedef short int16; +typedef unsigned int uint32; +typedef int int32; +typedef unsigned long long int uint64; +typedef long long int int64; + +#endif // __pbd_types_h__ diff --git a/libs/pbd3/pbd/undo.h b/libs/pbd3/pbd/undo.h new file mode 100644 index 0000000000..f067635ed3 --- /dev/null +++ b/libs/pbd3/pbd/undo.h @@ -0,0 +1,96 @@ +/* + Copyright (C) 2002 Brett Viren & Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __lib_pbd_undo_h__ +#define __lib_pbd_undo_h__ + +#include <string> +#include <list> +#include <sigc++/slot.h> +#include <sys/time.h> + +using std::string; +using std::list; + +typedef sigc::slot<void> UndoAction; + +class UndoCommand +{ + public: + UndoCommand (); + UndoCommand (const UndoCommand&); + UndoCommand& operator= (const UndoCommand&); + + void clear (); + + void add_undo (const UndoAction&); + void add_redo (const UndoAction&); + void add_redo_no_execute (const UndoAction&); + + void undo(); + void redo(); + + void set_name (const string& str) { + _name = str; + } + const string& name() const { return _name; } + + void set_timestamp (struct timeval &t) { + _timestamp = t; + } + + const struct timeval& timestamp() const { + return _timestamp; + } + + private: + list<UndoAction> redo_actions; + list<UndoAction> undo_actions; + struct timeval _timestamp; + string _name; +}; + +class UndoHistory +{ + public: + UndoHistory() {} + ~UndoHistory() {} + + void add (UndoCommand uc); + void undo (unsigned int n); + void redo (unsigned int n); + + unsigned long undo_depth() const { return UndoList.size(); } + unsigned long redo_depth() const { return RedoList.size(); } + + string next_undo() const { return (UndoList.empty() ? string("") : UndoList.back().name()); } + string next_redo() const { return (RedoList.empty() ? string("") : RedoList.back().name()); } + + void clear (); + void clear_undo (); + void clear_redo (); + + private: + list<UndoCommand> UndoList; + list<UndoCommand> RedoList; +}; + + +#endif /* __lib_pbd_undo_h__ */ diff --git a/libs/pbd3/pbd/unescape.h b/libs/pbd3/pbd/unescape.h new file mode 100644 index 0000000000..6596a86113 --- /dev/null +++ b/libs/pbd3/pbd/unescape.h @@ -0,0 +1,6 @@ +#ifndef __unescape_h__ +#define __unescape_h__ + +void unescape (char *); + +#endif // __unescape_h__ diff --git a/libs/pbd3/pbd/xml++.h b/libs/pbd3/pbd/xml++.h new file mode 100644 index 0000000000..993cb22fdf --- /dev/null +++ b/libs/pbd3/pbd/xml++.h @@ -0,0 +1,127 @@ +/* xml++.h + * libxml++ and this file are copyright (C) 2000 by Ari Johnson, and + * are covered by the GNU Lesser General Public License, which should be + * included with libxml++ as the file COPYING. + */ + +#include <string> +#include <list> +#include <map> +#include <cstdio> +#include <cstdarg> + +#include <libxml/parser.h> +#include <libxml/tree.h> + +#ifndef __XML_H +#define __XML_H + +using std::string; +using std::map; +using std::list; + +class XMLTree; +class XMLNode; +class XMLProperty; + +typedef list<XMLNode *> XMLNodeList; +typedef XMLNodeList::iterator XMLNodeIterator; +typedef XMLNodeList::const_iterator XMLNodeConstIterator; +typedef list<XMLProperty*> XMLPropertyList; +typedef XMLPropertyList::iterator XMLPropertyIterator; +typedef XMLPropertyList::const_iterator XMLPropertyConstIterator; +typedef map<string, XMLProperty*> XMLPropertyMap; + +class XMLTree { +private: + string _filename; + XMLNode *_root; + int _compression; + bool _initialized; + +public: + XMLTree(); + XMLTree(const string &fn); + XMLTree(const XMLTree *); + ~XMLTree(); + + bool initialized() const { return _initialized; }; + XMLNode *root() const { return _root; }; + XMLNode *set_root(XMLNode *n) { return _root = n; }; + + const string & filename() const { return _filename; }; + const string & set_filename(const string &fn) { return _filename = fn; }; + + int compression() const { return _compression; }; + int set_compression(int); + + bool read(); + bool read(const string &fn) { set_filename(fn); return read(); }; + bool read_buffer(const string &); + + bool write() const; + bool write(const string &fn) { set_filename(fn); return write(); }; + + void debug (FILE*) const; + + const string & write_buffer() const; +}; + +class XMLNode { +private: + bool _initialized; + string _name; + bool _is_content; + string _content; + XMLNodeList _children; + XMLPropertyList _proplist; + XMLPropertyMap _propmap; + +public: + XMLNode(const string &); + XMLNode(const string &, const string &); + XMLNode(const XMLNode&); + ~XMLNode(); + + bool initialized() const { return _initialized; }; + const string name() const { return _name; }; + + bool is_content() const { return _is_content; }; + const string & content() const { return _content; }; + const string & set_content(const string &); + XMLNode *add_content(const string & = string()); + + const XMLNodeList & children(const string & = string()) const; + XMLNode *add_child(const string &); + XMLNode *add_child_copy(const XMLNode&); + void add_child_nocopy (XMLNode&); + + const XMLPropertyList & properties() const { return _proplist; }; + XMLProperty *property(const string &); + const XMLProperty *property(const string &n) const + { return ((XMLNode *) this)->property(n); }; + XMLProperty *add_property(const string &, const string & = string()); + void remove_property(const string &); + + /** Remove all nodes with the name passed to remove_nodes */ + void remove_nodes(const string &); + /** Remove and delete all nodes with the name passed to remove_nodes */ + void remove_nodes_and_delete(const string &); +}; + +class XMLProperty { +private: + string _name; + string _value; + +public: + XMLProperty(const string &n, const string &v = string()); + ~XMLProperty(); + + const string & name() const { return _name; }; + const string & value() const { return _value; }; + const string & set_value(const string &v) { return _value = v; }; +}; + +#endif /* __XML_H */ + |