diff options
author | Taybin Rutkin <taybin@taybin.com> | 2006-06-29 22:21:30 +0000 |
---|---|---|
committer | Taybin Rutkin <taybin@taybin.com> | 2006-06-29 22:21:30 +0000 |
commit | 481f7c39655afec832ac10430dd61a3bb464aa58 (patch) | |
tree | cde736699cbe49374a6aaa079258f88c1d0c7059 /libs/pbd/pbd | |
parent | d1a4f74ef2c86042a0cbe0e83e611596df27575f (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')
35 files changed, 2635 insertions, 0 deletions
diff --git a/libs/pbd/pbd/.DS_Store b/libs/pbd/pbd/.DS_Store Binary files differnew file mode 100644 index 0000000000..5008ddfcf5 --- /dev/null +++ b/libs/pbd/pbd/.DS_Store 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 ®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/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 */ + |