summaryrefslogtreecommitdiff
path: root/libs/pbd/pbd
diff options
context:
space:
mode:
authorTaybin Rutkin <taybin@taybin.com>2006-06-29 22:21:30 +0000
committerTaybin Rutkin <taybin@taybin.com>2006-06-29 22:21:30 +0000
commit481f7c39655afec832ac10430dd61a3bb464aa58 (patch)
treecde736699cbe49374a6aaa079258f88c1d0c7059 /libs/pbd/pbd
parentd1a4f74ef2c86042a0cbe0e83e611596df27575f (diff)
Fixed i18n system.
Renamed pbd3 back to pbd, since it's version 4.1 now. Very minor fixes git-svn-id: svn://localhost/ardour2/trunk@656 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/pbd/pbd')
-rw-r--r--libs/pbd/pbd/.DS_Storebin0 -> 6148 bytes
-rw-r--r--libs/pbd/pbd/.cvsignore1
-rw-r--r--libs/pbd/pbd/abstract_ui.cc149
-rw-r--r--libs/pbd/pbd/abstract_ui.h79
-rw-r--r--libs/pbd/pbd/base_ui.h46
-rw-r--r--libs/pbd/pbd/basename.h13
-rw-r--r--libs/pbd/pbd/compose.h393
-rw-r--r--libs/pbd/pbd/convert.h40
-rw-r--r--libs/pbd/pbd/error.h32
-rw-r--r--libs/pbd/pbd/failed_constructor.h11
-rw-r--r--libs/pbd/pbd/fastlog.h40
-rw-r--r--libs/pbd/pbd/forkexec.h9
-rw-r--r--libs/pbd/pbd/mathfix.h34
-rw-r--r--libs/pbd/pbd/mountpoint.h28
-rw-r--r--libs/pbd/pbd/path.h113
-rw-r--r--libs/pbd/pbd/pathscanner.h66
-rw-r--r--libs/pbd/pbd/pool.h75
-rw-r--r--libs/pbd/pbd/pthread_utils.h23
-rw-r--r--libs/pbd/pbd/receiver.h50
-rw-r--r--libs/pbd/pbd/restartable_rw.h7
-rw-r--r--libs/pbd/pbd/ringbuffer.h284
-rw-r--r--libs/pbd/pbd/ringbufferNPT.h275
-rw-r--r--libs/pbd/pbd/selectable.h102
-rw-r--r--libs/pbd/pbd/stacktrace.h10
-rw-r--r--libs/pbd/pbd/stl_delete.h89
-rw-r--r--libs/pbd/pbd/stl_functors.h93
-rw-r--r--libs/pbd/pbd/strsplit.h9
-rw-r--r--libs/pbd/pbd/textreceiver.h44
-rw-r--r--libs/pbd/pbd/thrown_error.h39
-rw-r--r--libs/pbd/pbd/tokenizer.h49
-rw-r--r--libs/pbd/pbd/touchable.h89
-rw-r--r--libs/pbd/pbd/transmitter.h110
-rw-r--r--libs/pbd/pbd/undo.h96
-rw-r--r--libs/pbd/pbd/whitespace.h8
-rw-r--r--libs/pbd/pbd/xml++.h129
35 files changed, 2635 insertions, 0 deletions
diff --git a/libs/pbd/pbd/.DS_Store b/libs/pbd/pbd/.DS_Store
new file mode 100644
index 0000000000..5008ddfcf5
--- /dev/null
+++ b/libs/pbd/pbd/.DS_Store
Binary files differ
diff --git a/libs/pbd/pbd/.cvsignore b/libs/pbd/pbd/.cvsignore
new file mode 100644
index 0000000000..67020331ba
--- /dev/null
+++ b/libs/pbd/pbd/.cvsignore
@@ -0,0 +1 @@
+version.h
diff --git a/libs/pbd/pbd/abstract_ui.cc b/libs/pbd/pbd/abstract_ui.cc
new file mode 100644
index 0000000000..0e34787a2d
--- /dev/null
+++ b/libs/pbd/pbd/abstract_ui.cc
@@ -0,0 +1,149 @@
+#include <unistd.h>
+
+#include <pbd/abstract_ui.h>
+#include <pbd/pthread_utils.h>
+#include <pbd/failed_constructor.h>
+
+template <typename RequestObject>
+AbstractUI<RequestObject>::AbstractUI (string name, bool with_signal_pipes)
+ : BaseUI (name, with_signal_pipes)
+{
+ if (pthread_key_create (&thread_request_buffer_key, 0)) {
+ cerr << _("cannot create thread request buffer key") << endl;
+ throw failed_constructor();
+ }
+
+ PBD::ThreadCreated.connect (mem_fun (*this, &AbstractUI<RequestObject>::register_thread));
+ PBD::ThreadCreatedWithRequestSize.connect (mem_fun (*this, &AbstractUI<RequestObject>::register_thread_with_request_count));
+}
+
+template <typename RequestObject> void
+AbstractUI<RequestObject>::register_thread (pthread_t thread_id, string name)
+{
+ register_thread_with_request_count (thread_id, name, 256);
+}
+
+template <typename RequestObject> void
+AbstractUI<RequestObject>::register_thread_with_request_count (pthread_t thread_id, string thread_name, uint32_t num_requests)
+{
+ RequestBuffer* b = new RequestBuffer (num_requests);
+
+ {
+ Glib::Mutex::Lock lm (request_buffer_map_lock);
+ request_buffers[thread_id] = b;
+ }
+
+ pthread_setspecific (thread_request_buffer_key, b);
+}
+
+template <typename RequestObject> RequestObject*
+AbstractUI<RequestObject>::get_request (RequestType rt)
+{
+ RequestBuffer* rbuf = static_cast<RequestBuffer*>(pthread_getspecific (thread_request_buffer_key));
+
+ if (rbuf == 0) {
+ /* Cannot happen, but if it does we can't use the error reporting mechanism */
+ cerr << _("programming error: ")
+ << string_compose (X_("no %1-UI request buffer found for thread %2"), name(), pthread_name())
+ << endl;
+ abort ();
+ }
+
+ RequestBufferVector vec;
+
+ rbuf->get_write_vector (&vec);
+
+ if (vec.len[0] == 0) {
+ if (vec.len[1] == 0) {
+ cerr << string_compose (X_("no space in %1-UI request buffer for thread %2"), name(), pthread_name())
+ << endl;
+ return 0;
+ } else {
+ vec.buf[1]->type = rt;
+ return vec.buf[1];
+ }
+ } else {
+ vec.buf[0]->type = rt;
+ return vec.buf[0];
+ }
+}
+
+template <typename RequestObject> void
+AbstractUI<RequestObject>::handle_ui_requests ()
+{
+ RequestBufferMapIterator i;
+
+ request_buffer_map_lock.lock ();
+
+ for (i = request_buffers.begin(); i != request_buffers.end(); ++i) {
+
+ RequestBufferVector vec;
+
+ while (true) {
+
+ /* we must process requests 1 by 1 because
+ the request may run a recursive main
+ event loop that will itself call
+ handle_ui_requests. when we return
+ from the request handler, we cannot
+ expect that the state of queued requests
+ is even remotely consistent with
+ the condition before we called it.
+ */
+
+ i->second->get_read_vector (&vec);
+
+ if (vec.len[0] == 0) {
+ break;
+ } else {
+ /* request_factory/copy constructor does a deep
+ copy of the Request object,
+ unlike Ringbuffer::read()
+ */
+
+ RequestObject req (*vec.buf[0]);
+ i->second->increment_read_ptr (1);
+ request_buffer_map_lock.unlock ();
+ do_request (&req);
+ request_buffer_map_lock.lock ();
+ }
+ }
+ }
+
+ request_buffer_map_lock.unlock ();
+}
+
+template <typename RequestObject> void
+AbstractUI<RequestObject>::send_request (RequestObject *req)
+{
+ if (base_instance() == 0) {
+ return; /* XXX is this the right thing to do ? */
+ }
+
+ if (caller_is_ui_thread()) {
+ // cerr << "GUI thread sent request " << req << " type = " << req->type << endl;
+ do_request (req);
+ } else {
+ RequestBuffer* rbuf = static_cast<RequestBuffer*> (pthread_getspecific (thread_request_buffer_key));
+
+ if (rbuf == 0) {
+ /* can't use the error system to report this, because this
+ thread isn't registered!
+ */
+ cerr << _("programming error: ")
+ << string_compose (X_("AbstractUI::send_request() called from %1, but no request buffer exists for that thread"), pthread_name())
+ << endl;
+ abort ();
+ }
+
+ // cerr << "thread " << pthread_self() << " sent request " << req << " type = " << req->type << endl;
+
+ rbuf->increment_write_ptr (1);
+
+ if (signal_pipe[1] >= 0) {
+ const char c = 0;
+ write (signal_pipe[1], &c, 1);
+ }
+ }
+}
+
diff --git a/libs/pbd/pbd/abstract_ui.h b/libs/pbd/pbd/abstract_ui.h
new file mode 100644
index 0000000000..f80db7bf1a
--- /dev/null
+++ b/libs/pbd/pbd/abstract_ui.h
@@ -0,0 +1,79 @@
+/*
+ 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 <map>
+#include <string>
+#include <pthread.h>
+
+#include <sigc++/sigc++.h>
+
+#include <glibmm/thread.h>
+
+#include <pbd/receiver.h>
+#include <pbd/ringbufferNPT.h>
+#include <pbd/base_ui.h>
+
+class Touchable;
+
+template <class RequestObject>
+class AbstractUI : public BaseUI
+{
+ public:
+ AbstractUI (std::string name, bool with_signal_pipe);
+ virtual ~AbstractUI() {}
+
+ virtual bool caller_is_ui_thread() = 0;
+
+ void call_slot (sigc::slot<void> el_slot) {
+ RequestObject *req = get_request (BaseUI::CallSlot);
+
+ if (req == 0) {
+ return;
+ }
+
+ req->slot = el_slot;
+ send_request (req);
+ }
+
+ void register_thread (pthread_t, std::string);
+ void register_thread_with_request_count (pthread_t, std::string, uint32_t num_requests);
+
+ protected:
+ typedef RingBufferNPT<RequestObject> RequestBuffer;
+ typedef typename RequestBuffer::rw_vector RequestBufferVector;
+ typedef typename std::map<pthread_t,RequestBuffer*>::iterator RequestBufferMapIterator;
+
+ Glib::Mutex request_buffer_map_lock;
+ typedef std::map<pthread_t,RequestBuffer*> RequestBufferMap;
+ RequestBufferMap request_buffers;
+ pthread_key_t thread_request_buffer_key;
+ RequestObject* get_request (RequestType);
+ void handle_ui_requests ();
+ void send_request (RequestObject *);
+
+ virtual void do_request (RequestObject *) = 0;
+};
+
+#endif /* __pbd_abstract_ui_h__ */
+
+
diff --git a/libs/pbd/pbd/base_ui.h b/libs/pbd/pbd/base_ui.h
new file mode 100644
index 0000000000..b4570f8707
--- /dev/null
+++ b/libs/pbd/pbd/base_ui.h
@@ -0,0 +1,46 @@
+#ifndef __pbd_base_ui_h__
+#define __pbd_base_ui_h__
+
+#include <string>
+#include <stdint.h>
+
+#include <sigc++/slot.h>
+#include <sigc++/trackable.h>
+
+class BaseUI : virtual public sigc::trackable {
+ public:
+ BaseUI (std::string name, bool with_signal_pipes);
+ virtual ~BaseUI();
+
+ BaseUI* base_instance() { return base_ui_instance; }
+
+ std::string name() const { return _name; }
+
+ bool ok() const { return _ok; }
+
+ enum RequestType {
+ range_guarantee = ~0
+ };
+
+ struct BaseRequestObject {
+ RequestType type;
+ sigc::slot<void> the_slot;
+ };
+
+ static RequestType new_request_type();
+ static RequestType CallSlot;
+
+ protected:
+ int signal_pipe[2];
+ bool _ok;
+
+ private:
+ std::string _name;
+ BaseUI* base_ui_instance;
+
+ static uint32_t rt_bit;
+
+ int setup_signal_pipe ();
+};
+
+#endif /* __pbd_base_ui_h__ */
diff --git a/libs/pbd/pbd/basename.h b/libs/pbd/pbd/basename.h
new file mode 100644
index 0000000000..35aebe166c
--- /dev/null
+++ b/libs/pbd/pbd/basename.h
@@ -0,0 +1,13 @@
+#ifndef __stupid_basename_h__
+#define __stupid_basename_h__
+
+#include <string>
+
+namespace PBD
+{
+
+extern std::string basename_nosuffix (const std::string&);
+
+};
+
+#endif // __stupid_basename_h__
diff --git a/libs/pbd/pbd/compose.h b/libs/pbd/pbd/compose.h
new file mode 100644
index 0000000000..0df9519aaf
--- /dev/null
+++ b/libs/pbd/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 PBD
+//{
+ // 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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/pbd/pbd/convert.h b/libs/pbd/pbd/convert.h
new file mode 100644
index 0000000000..12e63ba6fc
--- /dev/null
+++ b/libs/pbd/pbd/convert.h
@@ -0,0 +1,40 @@
+/*
+ Copyright (C) 2002 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.
+
+*/
+
+#ifndef __pbd_convert_h__
+#define __pbd_convert_h__
+
+#include <string>
+#include <vector>
+
+namespace PBD {
+
+std::string short_version (std::string, std::string::size_type target_length);
+
+int atoi (const std::string&);
+double atof (const std::string&);
+void url_decode (std::string&);
+
+std::string length2string (const int32_t frames, const float sample_rate);
+
+std::vector<std::string> internationalize (const char **);
+
+} //namespace PBD
+
+#endif /* __pbd_convert_h__ */
diff --git a/libs/pbd/pbd/error.h b/libs/pbd/pbd/error.h
new file mode 100644
index 0000000000..4136f02ee2
--- /dev/null
+++ b/libs/pbd/pbd/error.h
@@ -0,0 +1,32 @@
+/*
+ Copyright (C) 1998-2006 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 __libpbd_error_h__
+#define __libpbd_error_h__
+
+#include "transmitter.h"
+
+namespace PBD {
+ extern Transmitter error;
+ extern Transmitter info;
+ extern Transmitter warning;
+ extern Transmitter fatal;
+}
+
+#endif // __libpbd_error_h__
diff --git a/libs/pbd/pbd/failed_constructor.h b/libs/pbd/pbd/failed_constructor.h
new file mode 100644
index 0000000000..62eb6c0d71
--- /dev/null
+++ b/libs/pbd/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/pbd/pbd/fastlog.h b/libs/pbd/pbd/fastlog.h
new file mode 100644
index 0000000000..4269705a44
--- /dev/null
+++ b/libs/pbd/pbd/fastlog.h
@@ -0,0 +1,40 @@
+/* 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)
+ */
+ union {float f; int i;} t;
+ t.f = val;
+ int * const exp_ptr = &t.i;
+ 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) * t.f + 2) * t.f - 2.0f/3;
+
+ 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/pbd/pbd/forkexec.h b/libs/pbd/pbd/forkexec.h
new file mode 100644
index 0000000000..2af3711390
--- /dev/null
+++ b/libs/pbd/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/pbd/pbd/mathfix.h b/libs/pbd/pbd/mathfix.h
new file mode 100644
index 0000000000..f0dc7e491e
--- /dev/null
+++ b/libs/pbd/pbd/mathfix.h
@@ -0,0 +1,34 @@
+/*
+ Copyright (C) 2005 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_mathfix_h__
+#define __pbd_mathfix_h__
+
+/* this is necessary to support older releases of OSX where
+ they moved around some of the standard math functions
+*/
+
+#ifdef __APPLE__
+#define powf pow
+#define sqrtf sqrt
+#endif
+
+
+#endif
diff --git a/libs/pbd/pbd/mountpoint.h b/libs/pbd/pbd/mountpoint.h
new file mode 100644
index 0000000000..86ccc58190
--- /dev/null
+++ b/libs/pbd/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/pbd/pbd/path.h b/libs/pbd/pbd/path.h
new file mode 100644
index 0000000000..0b77a7c237
--- /dev/null
+++ b/libs/pbd/pbd/path.h
@@ -0,0 +1,113 @@
+/*
+ Copyright (C) 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#ifndef PBD_PATH
+#define PBD_PATH
+
+#include <string>
+#include <vector>
+
+namespace PBD {
+
+using std::string;
+using std::vector;
+
+/**
+ The Path class is a helper class for getting a vector of absolute
+ paths contained in a path string where a path string contains
+ absolute directory paths separated by a colon(:) or a semi-colon(;)
+ on windows.
+ */
+class Path {
+public:
+
+ /**
+ Create an empty Path.
+ */
+ Path ();
+
+ /**
+ Initialize Path from a string, each absolute path contained
+ in the "path" will be accessed to ensure it exists and is
+ readable.
+ \param path A path string.
+ */
+ Path (const string& path);
+
+ /**
+ Initialize Path from a vector of path strings, each absolute
+ path contained in paths will be accessed to ensure it
+ exists and is readable.
+ \param path A path string.
+ */
+ Path (const vector<string>& paths);
+
+ Path(const Path& path);
+
+ /**
+ Indicate whether there are any directories in m_dirs, if Path is
+ initialized with an empty string as the result of for instance
+ calling Glib::getenv where the environment variable doesn't
+ exist or if none of the directories in the path string are
+ accessible then false is returned.
+
+ \return true if there are any paths in m_paths.
+ */
+ //operator bool () const { return !m_dirs.empty(); }
+
+ /**
+ \return vector containing the absolute paths to the directories
+ contained
+ */
+ operator const vector<string>& () const { return m_dirs; }
+
+ /**
+ \return vector containing the absolute paths to the directories
+ contained
+ */
+ const vector<string>& dirs () const { return m_dirs; }
+
+ const string path_string() const;
+
+ const Path& operator= (const Path& path);
+
+ const Path& operator+= (const string& directory_path);
+
+ Path& add_subdirectory_to_path (const string& subdirectory);
+
+protected:
+
+ friend const Path operator+ (const Path&, const Path&);
+
+ bool readable_directory (const string& directory_path);
+
+ void add_readable_directory (const string& directory_path);
+
+ void add_readable_directories (const vector<string>& paths);
+
+ vector<string> m_dirs;
+
+};
+
+bool find_file_in_path (const Path& path, const string& filename, string& resulting_path_to_file);
+
+} // namespace PBD
+
+#endif // PBD_PATH
+
+
diff --git a/libs/pbd/pbd/pathscanner.h b/libs/pbd/pbd/pathscanner.h
new file mode 100644
index 0000000000..346e7858c4
--- /dev/null
+++ b/libs/pbd/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 &regexp,
+ bool match_fullpath = true,
+ bool return_fullpath = true,
+ long limit = -1);
+
+
+ string *find_first (const string &dirpath,
+ const string &regexp,
+ 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/pbd/pbd/pool.h b/libs/pbd/pbd/pool.h
new file mode 100644
index 0000000000..f8e19e72fb
--- /dev/null
+++ b/libs/pbd/pbd/pool.h
@@ -0,0 +1,75 @@
+/*
+ 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 <glibmm/thread.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:
+ Glib::Mutex* m_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:
+ Glib::Mutex* m_lock;
+};
+
+#endif // __qm_pool_h__
diff --git a/libs/pbd/pbd/pthread_utils.h b/libs/pbd/pbd/pthread_utils.h
new file mode 100644
index 0000000000..482b5b54cf
--- /dev/null
+++ b/libs/pbd/pbd/pthread_utils.h
@@ -0,0 +1,23 @@
+#ifndef __pbd_pthread_utils__
+#define __pbd_pthread_utils__
+
+#include <pthread.h>
+#include <signal.h>
+#include <string>
+#include <stdint.h>
+
+#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;
+ extern sigc::signal<void,pthread_t,std::string,uint32_t> ThreadCreatedWithRequestSize;
+}
+
+#endif /* __pbd_pthread_utils__ */
diff --git a/libs/pbd/pbd/receiver.h b/libs/pbd/pbd/receiver.h
new file mode 100644
index 0000000000..5ce238df63
--- /dev/null
+++ b/libs/pbd/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 : virtual 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/pbd/pbd/restartable_rw.h b/libs/pbd/pbd/restartable_rw.h
new file mode 100644
index 0000000000..ee84e4e295
--- /dev/null
+++ b/libs/pbd/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/pbd/pbd/ringbuffer.h b/libs/pbd/pbd/ringbuffer.h
new file mode 100644
index 0000000000..1d9c9b04e3
--- /dev/null
+++ b/libs/pbd/pbd/ringbuffer.h
@@ -0,0 +1,284 @@
+/*
+ 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 <glib.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 !!! */
+ g_atomic_int_set (&write_ptr, 0);
+ g_atomic_int_set (&read_ptr, 0);
+ }
+
+ void set (size_t r, size_t w) {
+ /* !!! NOT THREAD SAFE !!! */
+ g_atomic_int_set (&write_ptr, w);
+ g_atomic_int_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) {
+ g_atomic_int_set (&read_ptr, (g_atomic_int_get(&read_ptr) - cnt) & size_mask);
+ }
+
+ void increment_read_ptr (size_t cnt) {
+ g_atomic_int_set (&read_ptr, (g_atomic_int_get(&read_ptr) + cnt) & size_mask);
+ }
+
+ void increment_write_ptr (size_t cnt) {
+ g_atomic_int_set (&write_ptr, (g_atomic_int_get(&write_ptr) + cnt) & size_mask);
+ }
+
+ size_t write_space () {
+ size_t w, r;
+
+ w = g_atomic_int_get (&write_ptr);
+ r = g_atomic_int_get (&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 = g_atomic_int_get (&write_ptr);
+ r = g_atomic_int_get (&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 g_atomic_int_get (&write_ptr); }
+ size_t get_read_ptr () const { return g_atomic_int_get (&read_ptr); }
+ size_t bufsize () const { return size; }
+
+ protected:
+ T *buf;
+ size_t size;
+ mutable gint write_ptr;
+ mutable gint 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=g_atomic_int_get(&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;
+ }
+
+ g_atomic_int_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=g_atomic_int_get(&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;
+ }
+
+ g_atomic_int_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 = g_atomic_int_get (&write_ptr);
+ r = g_atomic_int_get (&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 = g_atomic_int_get (&write_ptr);
+ r = g_atomic_int_get (&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/pbd/pbd/ringbufferNPT.h b/libs/pbd/pbd/ringbufferNPT.h
new file mode 100644
index 0000000000..fee2efce3d
--- /dev/null
+++ b/libs/pbd/pbd/ringbufferNPT.h
@@ -0,0 +1,275 @@
+/*
+ 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 <glib.h>
+
+/* ringbuffer class where the element size is not required to be a power of two */
+
+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 !!! */
+ g_atomic_int_set (&write_ptr, 0);
+ g_atomic_int_set (&read_ptr, 0);
+ }
+
+ void set (size_t r, size_t w) {
+ /* !!! NOT THREAD SAFE !!! */
+ g_atomic_int_set (&write_ptr, w);
+ g_atomic_int_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) {
+ g_atomic_int_set (&read_ptr, (g_atomic_int_get(&read_ptr) - cnt) % size);
+ }
+
+ void increment_read_ptr (size_t cnt) {
+ g_atomic_int_set (&read_ptr, (g_atomic_int_get(&read_ptr) + cnt) % size);
+ }
+
+ void increment_write_ptr (size_t cnt) {
+ g_atomic_int_set (&write_ptr, (g_atomic_int_get(&write_ptr) + cnt) % size);
+ }
+
+ size_t write_space () {
+ size_t w, r;
+
+ w = g_atomic_int_get (&write_ptr);
+ r = g_atomic_int_get (&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 = g_atomic_int_get (&write_ptr);
+ r = g_atomic_int_get (&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 g_atomic_int_get (&write_ptr); }
+ size_t get_read_ptr () const { return g_atomic_int_get (&read_ptr); }
+ size_t bufsize () const { return size; }
+
+ protected:
+ T *buf;
+ size_t size;
+ mutable gint write_ptr;
+ mutable gint 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=g_atomic_int_get(&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;
+ }
+
+ g_atomic_int_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=g_atomic_int_get(&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;
+ }
+
+ g_atomic_int_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 = g_atomic_int_get (&write_ptr);
+ r = g_atomic_int_get (&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 = g_atomic_int_get (&write_ptr);
+ r = g_atomic_int_get (&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/pbd/pbd/selectable.h b/libs/pbd/pbd/selectable.h
new file mode 100644
index 0000000000..470bc3cfcc
--- /dev/null
+++ b/libs/pbd/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/pbd/pbd/stacktrace.h b/libs/pbd/pbd/stacktrace.h
new file mode 100644
index 0000000000..d7278bd35a
--- /dev/null
+++ b/libs/pbd/pbd/stacktrace.h
@@ -0,0 +1,10 @@
+#ifndef __libpbd_stacktrace_h__
+#define __libpbd_stacktrace_h__
+
+#include <ostream>
+
+namespace PBD {
+ void stacktrace (std::ostream& out);
+}
+
+#endif /* __libpbd_stacktrace_h__ */
diff --git a/libs/pbd/pbd/stl_delete.h b/libs/pbd/pbd/stl_delete.h
new file mode 100644
index 0000000000..6e5bfa0734
--- /dev/null
+++ b/libs/pbd/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/pbd/pbd/stl_functors.h b/libs/pbd/pbd/stl_functors.h
new file mode 100644
index 0000000000..4a96e91a28
--- /dev/null
+++ b/libs/pbd/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/pbd/pbd/strsplit.h b/libs/pbd/pbd/strsplit.h
new file mode 100644
index 0000000000..e55ad1c825
--- /dev/null
+++ b/libs/pbd/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/pbd/pbd/textreceiver.h b/libs/pbd/pbd/textreceiver.h
new file mode 100644
index 0000000000..b8bfe5bc78
--- /dev/null
+++ b/libs/pbd/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/pbd/pbd/thrown_error.h b/libs/pbd/pbd/thrown_error.h
new file mode 100644
index 0000000000..83cf8acfac
--- /dev/null
+++ b/libs/pbd/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/pbd/pbd/tokenizer.h b/libs/pbd/pbd/tokenizer.h
new file mode 100644
index 0000000000..a976b79341
--- /dev/null
+++ b/libs/pbd/pbd/tokenizer.h
@@ -0,0 +1,49 @@
+#ifndef PBD_TOKENIZER
+#define PBD_TOKENIZER
+
+#include <iterator>
+#include <string>
+
+namespace PBD {
+
+/**
+ Tokenize string, this should work for standard
+ strings aswell as Glib::ustring. This is a bit of a hack,
+ there are much better string tokenizing patterns out there.
+*/
+template<typename StringType, typename Iter>
+unsigned int
+tokenize(const StringType& str,
+ const StringType& delims,
+ Iter it)
+{
+ typename StringType::size_type start_pos = 0;
+ typename StringType::size_type end_pos = 0;
+ unsigned int token_count = 0;
+
+ do {
+ start_pos = str.find_first_not_of(delims, start_pos);
+ end_pos = str.find_first_of(delims, start_pos);
+ if (start_pos != end_pos) {
+ if (end_pos == str.npos) {
+ end_pos = str.length();
+ }
+ *it++ = str.substr(start_pos, end_pos - start_pos);
+ ++token_count;
+ start_pos = str.find_first_not_of(delims, end_pos + 1);
+ }
+ } while (start_pos != str.npos);
+
+ if (start_pos != str.npos) {
+ *it++ = str.substr(start_pos, str.length() - start_pos);
+ ++token_count;
+ }
+
+ return token_count;
+}
+
+} // namespace PBD
+
+#endif // PBD_TOKENIZER
+
+
diff --git a/libs/pbd/pbd/touchable.h b/libs/pbd/pbd/touchable.h
new file mode 100644
index 0000000000..0298574dfa
--- /dev/null
+++ b/libs/pbd/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/pbd/pbd/transmitter.h b/libs/pbd/pbd/transmitter.h
new file mode 100644
index 0000000000..357cb9965f
--- /dev/null
+++ b/libs/pbd/pbd/transmitter.h
@@ -0,0 +1,110 @@
+/*
+ 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/pbd/pbd/undo.h b/libs/pbd/pbd/undo.h
new file mode 100644
index 0000000000..f067635ed3
--- /dev/null
+++ b/libs/pbd/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/pbd/pbd/whitespace.h b/libs/pbd/pbd/whitespace.h
new file mode 100644
index 0000000000..6620a8fb50
--- /dev/null
+++ b/libs/pbd/pbd/whitespace.h
@@ -0,0 +1,8 @@
+#ifndef __pbd_whitespace_h__
+#define __pbd_whitespace_h__
+
+#include <string>
+
+extern void strip_whitespace_edges (std::string& str);
+
+#endif // __pbd_whitespace_h__
diff --git a/libs/pbd/pbd/xml++.h b/libs/pbd/pbd/xml++.h
new file mode 100644
index 0000000000..afb896e1d5
--- /dev/null
+++ b/libs/pbd/pbd/xml++.h
@@ -0,0 +1,129 @@
+/* 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) { _initialized = true; 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 char *);
+ XMLNode *add_child_copy(const XMLNode&);
+ void add_child_nocopy (XMLNode&);
+
+ const XMLPropertyList & properties() const { return _proplist; };
+ XMLProperty *property(const char * );
+ const XMLProperty *property(const char * n) const
+ { return ((XMLNode *) this)->property(n); };
+ XMLProperty *add_property(const char *, const string &);
+ XMLProperty *add_property(const char *, const char * = "");
+
+ 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 */
+