summaryrefslogtreecommitdiff
path: root/libs/pbd
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2014-01-10 16:07:57 -0500
committerPaul Davis <paul@linuxaudiosystems.com>2014-01-10 16:07:57 -0500
commit3020b224fa2d6e1b6b8a576e8e8e211e0585f2a2 (patch)
tree314c3099bcc57d9af09d249e1e7dd8e45baca642 /libs/pbd
parentd15fda6d751a465d278f477923075d4783f3b1ca (diff)
parent897fbdc652434d3aa1e67223c3c3ef7ae9be2318 (diff)
Merge windows+cc branch into cairocanvas branch. Not finished, need to now merge windows branch to get changes from there
Diffstat (limited to 'libs/pbd')
-rw-r--r--libs/pbd/base_ui.cc73
-rw-r--r--libs/pbd/clear_dir.cc13
-rw-r--r--libs/pbd/debug.cc26
-rw-r--r--libs/pbd/debug_rt_alloc.c3
-rw-r--r--libs/pbd/epa.cc15
-rw-r--r--libs/pbd/fallback_folders.cc591
-rw-r--r--libs/pbd/ffs.cc49
-rw-r--r--libs/pbd/file_manager.cc33
-rw-r--r--libs/pbd/file_utils.cc42
-rw-r--r--libs/pbd/fpu.cc6
-rw-r--r--libs/pbd/glib_semaphore.cc68
-rw-r--r--libs/pbd/localeguard.cc34
-rw-r--r--libs/pbd/localtime_r.cc41
-rw-r--r--libs/pbd/mountpoint.cc14
-rw-r--r--libs/pbd/msvc/fpu.cc124
-rw-r--r--libs/pbd/msvc/getopt.c118
-rw-r--r--libs/pbd/msvc/getopt.h110
-rw-r--r--libs/pbd/msvc/getopt_long.c546
-rw-r--r--libs/pbd/msvc/mountpoint.cc166
-rw-r--r--libs/pbd/msvc/msvc_pbd.cc914
-rw-r--r--libs/pbd/msvc/msvc_poll.cc215
-rw-r--r--libs/pbd/pathexpand.cc28
-rw-r--r--libs/pbd/pathscanner.cc10
-rw-r--r--libs/pbd/pbd/abstract_ui.cc35
-rw-r--r--libs/pbd/pbd/abstract_ui.h16
-rw-r--r--libs/pbd/pbd/atomic_counter.h99
-rw-r--r--libs/pbd/pbd/base_ui.h18
-rw-r--r--libs/pbd/pbd/cartesian.h2
-rw-r--r--libs/pbd/pbd/compose.h30
-rw-r--r--libs/pbd/pbd/convert.h2
-rw-r--r--libs/pbd/pbd/debug.h1
-rw-r--r--libs/pbd/pbd/demangle.h2
-rw-r--r--libs/pbd/pbd/fallback_folders.h62
-rw-r--r--libs/pbd/pbd/ffs.h (renamed from libs/pbd/uuid_boost.cc)24
-rw-r--r--libs/pbd/pbd/file_utils.h8
-rw-r--r--libs/pbd/pbd/floating.h4
-rw-r--r--libs/pbd/pbd/functor_command.h2
-rw-r--r--libs/pbd/pbd/glib_semaphore.h57
-rw-r--r--libs/pbd/pbd/localeguard.h37
-rw-r--r--libs/pbd/pbd/localtime_r.h13
-rw-r--r--libs/pbd/pbd/memento_command.h6
-rw-r--r--libs/pbd/pbd/msvc_pbd.h256
-rw-r--r--libs/pbd/pbd/pathexpand.h1
-rw-r--r--libs/pbd/pbd/pathscanner.h4
-rw-r--r--libs/pbd/pbd/properties.h12
-rw-r--r--libs/pbd/pbd/property_basics.h17
-rw-r--r--libs/pbd/pbd/pthread_utils.h4
-rw-r--r--libs/pbd/pbd/rcu.h6
-rw-r--r--libs/pbd/pbd/resource.h49
-rw-r--r--libs/pbd/pbd/ringbuffer.h14
-rw-r--r--libs/pbd/pbd/ringbufferNPT.h14
-rw-r--r--libs/pbd/pbd/search_path.h46
-rw-r--r--libs/pbd/pbd/semaphore.h13
-rw-r--r--libs/pbd/pbd/semutils.h16
-rw-r--r--libs/pbd/pbd/sequence_property.h12
-rw-r--r--libs/pbd/pbd/signals.h2
-rw-r--r--libs/pbd/pbd/stacktrace.h8
-rw-r--r--libs/pbd/pbd/stl_delete.h10
-rw-r--r--libs/pbd/pbd/timersub.h32
-rw-r--r--libs/pbd/pbd/tokenizer.h2
-rw-r--r--libs/pbd/pbd/touchable.h8
-rw-r--r--libs/pbd/pbd/undo.h4
-rw-r--r--libs/pbd/pbd/unknown_type.h4
-rw-r--r--libs/pbd/pbd/unwind.h2
-rw-r--r--libs/pbd/pbd/uuid.h40
-rw-r--r--libs/pbd/pool.cc7
-rw-r--r--libs/pbd/pthread_utils.cc15
-rw-r--r--libs/pbd/resource.cc77
-rw-r--r--libs/pbd/search_path.cc36
-rw-r--r--libs/pbd/semutils.cc30
-rw-r--r--libs/pbd/sndfile_manager.cc1
-rw-r--r--libs/pbd/stacktrace.cc3
-rw-r--r--libs/pbd/stateful.cc4
-rw-r--r--libs/pbd/test/filesystem_test.cc2
-rw-r--r--libs/pbd/test/mutex_test.cc24
-rw-r--r--libs/pbd/test/mutex_test.h17
-rw-r--r--libs/pbd/test/test_common.cc4
-rw-r--r--libs/pbd/test/test_common.h2
-rw-r--r--libs/pbd/test/testrunner.cc4
-rw-r--r--libs/pbd/transmitter.cc8
-rw-r--r--libs/pbd/uuid.cc15
-rw-r--r--libs/pbd/wscript15
-rw-r--r--libs/pbd/xml++.cc2
83 files changed, 4232 insertions, 267 deletions
diff --git a/libs/pbd/base_ui.cc b/libs/pbd/base_ui.cc
index a7e148c839..3a4257ebdd 100644
--- a/libs/pbd/base_ui.cc
+++ b/libs/pbd/base_ui.cc
@@ -19,7 +19,11 @@
#include <cstring>
#include <stdint.h>
+#ifdef COMPILER_MSVC
+#include <io.h> // Microsoft's nearest equivalent to <unistd.h>
+#else
#include <unistd.h>
+#endif
#include <fcntl.h>
#include <cerrno>
#include <cstring>
@@ -33,6 +37,8 @@
#include "i18n.h"
+#include "pbd/debug.h"
+
using namespace std;
using namespace PBD;
using namespace Glib;
@@ -42,13 +48,18 @@ BaseUI::RequestType BaseUI::CallSlot = BaseUI::new_request_type();
BaseUI::RequestType BaseUI::Quit = BaseUI::new_request_type();
BaseUI::BaseUI (const string& str)
- : request_channel (true)
+ : m_context(MainContext::get_default())
, run_loop_thread (0)
, _name (str)
+#ifndef PLATFORM_WINDOWS
+ , request_channel (true)
+#endif
{
base_ui_instance = this;
+#ifndef PLATFORM_WINDOWS
request_channel.ios()->connect (sigc::mem_fun (*this, &BaseUI::request_handler));
+#endif
/* derived class must set _ok */
}
@@ -73,7 +84,7 @@ BaseUI::new_request_type ()
void
BaseUI::main_thread ()
{
- DEBUG_TRACE (DEBUG::EventLoop, string_compose ("%1: event loop running in thread %2\n", name(), pthread_self()));
+ DEBUG_TRACE (DEBUG::EventLoop, string_compose ("%1: event loop running in thread %2\n", name(), pthread_name()));
set_event_loop_for_thread (this);
thread_init ();
_main_loop->get_context()->signal_idle().connect (sigc::mem_fun (*this, &BaseUI::signal_running));
@@ -95,11 +106,9 @@ BaseUI::run ()
/* to be called by UI's that need/want their own distinct, self-created event loop thread.
*/
- _main_loop = MainLoop::create (MainContext::create());
- request_channel.ios()->attach (_main_loop->get_context());
-
- /* glibmm hack - drop the refptr to the IOSource now before it can hurt */
- request_channel.drop_ios ();
+ m_context = MainContext::create();
+ _main_loop = MainLoop::create (m_context);
+ attach_request_source ();
Glib::Threads::Mutex::Lock lm (_run_lock);
run_loop_thread = Glib::Threads::Thread::create (mem_fun (*this, &BaseUI::main_thread));
@@ -115,6 +124,24 @@ BaseUI::quit ()
}
}
+#ifdef PLATFORM_WINDOWS
+gboolean
+BaseUI::_request_handler (gpointer data)
+{
+ BaseUI* ui = static_cast<BaseUI*>(data);
+ return ui->request_handler ();
+}
+
+bool
+BaseUI::request_handler ()
+{
+ DEBUG_TRACE (DEBUG::EventLoop, "BaseUI::request_handler\n");
+ handle_ui_requests ();
+ // keep calling indefinitely at the timeout interval
+ return true;
+}
+
+#else
bool
BaseUI::request_handler (Glib::IOCondition ioc)
{
@@ -133,9 +160,39 @@ BaseUI::request_handler (Glib::IOCondition ioc)
/* handle requests */
+ DEBUG_TRACE (DEBUG::EventLoop, "BaseUI::request_handler\n");
handle_ui_requests ();
}
return true;
}
-
+#endif
+
+void
+BaseUI::signal_new_request ()
+{
+ DEBUG_TRACE (DEBUG::EventLoop, "BaseUI::signal_new_request\n");
+#ifdef PLATFORM_WINDOWS
+ // handled in timeout, how to signal...?
+#else
+ request_channel.wakeup ();
+#endif
+}
+
+/**
+ * This method relies on the caller having already set m_context
+ */
+void
+BaseUI::attach_request_source ()
+{
+ DEBUG_TRACE (DEBUG::EventLoop, "BaseUI::attach_request_source\n");
+#ifdef PLATFORM_WINDOWS
+ GSource* request_source = g_timeout_source_new(200);
+ g_source_set_callback (request_source, &BaseUI::_request_handler, this, NULL);
+ g_source_attach (request_source, m_context->gobj());
+#else
+ request_channel.ios()->attach (m_context);
+ /* glibmm hack - drop the refptr to the IOSource now before it can hurt */
+ request_channel.drop_ios ();
+#endif
+}
diff --git a/libs/pbd/clear_dir.cc b/libs/pbd/clear_dir.cc
index 29410d41e5..2f9c7b772d 100644
--- a/libs/pbd/clear_dir.cc
+++ b/libs/pbd/clear_dir.cc
@@ -17,13 +17,22 @@
*/
-#include <string>
+#ifdef COMPILER_MSVC
+#include <io.h> // Microsoft's nearest equivalent to <unistd.h>
+using PBD::readdir;
+using PBD::opendir;
+using PBD::closedir;
+#else
#include <dirent.h>
#include <unistd.h>
+#endif
+
+#include <string>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
+#include <glib/gstdio.h>
#include <glibmm/miscutils.h>
#include "pbd/error.h"
@@ -66,7 +75,7 @@ PBD::clear_directory (const string& dir, size_t* size, vector<string>* paths)
continue;
}
- if (::unlink (fullpath.c_str())) {
+ if (::g_unlink (fullpath.c_str())) {
error << string_compose (_("cannot remove file %1 (%2)"), fullpath, strerror (errno))
<< endmsg;
ret = 1;
diff --git a/libs/pbd/debug.cc b/libs/pbd/debug.cc
index c86afbe87e..fba457c83e 100644
--- a/libs/pbd/debug.cc
+++ b/libs/pbd/debug.cc
@@ -24,6 +24,8 @@
#include <vector>
#include <algorithm>
+#include <boost/tokenizer.hpp>
+
#include "pbd/debug.h"
#include "i18n.h"
@@ -47,6 +49,7 @@ uint64_t PBD::DEBUG::FileManager = PBD::new_debug_bit ("filemanager");
uint64_t PBD::DEBUG::Pool = PBD::new_debug_bit ("pool");
uint64_t PBD::DEBUG::EventLoop = PBD::new_debug_bit ("eventloop");
uint64_t PBD::DEBUG::AbstractUI = PBD::new_debug_bit ("abstractui");
+uint64_t PBD::DEBUG::FileUtils = PBD::new_debug_bit ("fileutils");
uint64_t PBD::debug_bits = 0x0;
@@ -75,36 +78,31 @@ PBD::set_debug_bits (uint64_t bits)
int
PBD::parse_debug_options (const char* str)
{
- char* p;
- char* sp;
+ typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
+ boost::char_separator<char> sep (",");
+ tokenizer tokens (string(str), sep);
uint64_t bits = 0;
- char* copy = strdup (str);
-
- p = strtok_r (copy, ",", &sp);
- while (p) {
- if (strcasecmp (p, "list") == 0) {
+ for (tokenizer::iterator tok_iter = tokens.begin(); tok_iter != tokens.end(); ++tok_iter) {
+ if (*tok_iter == "list") {
list_debug_options ();
- free (copy);
return 1;
}
- if (strcasecmp (p, "all") == 0) {
+ if (*tok_iter == "all") {
PBD::set_debug_bits (~0ULL);
- free (copy);
return 0;
}
for (map<const char*,uint64_t>::iterator i = _debug_bit_map().begin(); i != _debug_bit_map().end(); ++i) {
- if (strncasecmp (p, i->first, strlen (p)) == 0) {
+ const char* cstr = (*tok_iter).c_str();
+
+ if (strncasecmp (cstr, i->first, strlen (cstr)) == 0) {
bits |= i->second;
}
}
-
- p = strtok_r (0, ",", &sp);
}
- free (copy);
PBD::set_debug_bits (bits);
return 0;
}
diff --git a/libs/pbd/debug_rt_alloc.c b/libs/pbd/debug_rt_alloc.c
index 81e640b66d..7e578a2367 100644
--- a/libs/pbd/debug_rt_alloc.c
+++ b/libs/pbd/debug_rt_alloc.c
@@ -22,9 +22,10 @@
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
-#include <pthread.h>
#include <stdlib.h>
+#include "pbd/pthread_utils.h"
+
int (*pbd_alloc_allowed) () = 0;
/** Thread-local key whose value is set to 1 if malloc checking is disabled
diff --git a/libs/pbd/epa.cc b/libs/pbd/epa.cc
index 8b8a23491b..c7a1d41b0e 100644
--- a/libs/pbd/epa.cc
+++ b/libs/pbd/epa.cc
@@ -17,12 +17,19 @@
*/
+#include <glib.h>
+
#include <cstdlib>
#include "pbd/epa.h"
#include "pbd/strsplit.h"
+#ifdef COMPILER_MSVC
+#define environ _environ
+_CRTIMP extern char ** _environ;
+#else
extern char** environ;
+#endif
using namespace PBD;
using namespace std;
@@ -61,7 +68,7 @@ EnvironmentalProtectionAgency::save ()
/* fetch environment from named environment variable, rather than "environ"
*/
- const char* estr = getenv (_envname.c_str());
+ const char* estr = g_getenv (_envname.c_str());
if (!estr) {
return;
@@ -117,7 +124,7 @@ EnvironmentalProtectionAgency::restore () const
clear ();
for (map<string,string>::const_iterator i = e.begin(); i != e.end(); ++i) {
- setenv (i->first.c_str(), i->second.c_str(), 1);
+ g_setenv (i->first.c_str(), i->second.c_str(), 1);
}
}
@@ -137,6 +144,6 @@ EnvironmentalProtectionAgency::clear () const
}
string before = estring.substr (0, equal);
- unsetenv(before.c_str());
+ g_unsetenv(before.c_str());
}
-}
+}
diff --git a/libs/pbd/fallback_folders.cc b/libs/pbd/fallback_folders.cc
new file mode 100644
index 0000000000..f17e69e417
--- /dev/null
+++ b/libs/pbd/fallback_folders.cc
@@ -0,0 +1,591 @@
+/*
+ Copyright (C) 2008 John Emmas
+
+ 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.
+
+*/
+
+#include <pbd/fallback_folders.h>
+#include <glib.h>
+#include <glibmm.h>
+#include <string.h>
+
+
+
+#ifdef PLATFORM_WINDOWS // Would not be relevant for Cygwin!!
+#include <shlobj.h>
+#include <winreg.h>
+
+//***************************************************************
+//
+// get_win_special_folder()
+//
+// Gets the full path name that corresponds of one of the Windows
+// special folders, such as "My Documents" and the like. The input
+// parameter must be one of the corresponding CSIDL values, such
+// as CSIDL_SYSTEM etc.
+//
+// Returns:
+//
+// On Success: A pointer to a newly allocated string containing
+// the name of the special folder (must later be freed).
+// On Failure: NULL
+//
+gchar *
+get_win_special_folder (int csidl)
+{
+wchar_t path[PATH_MAX+1];
+HRESULT hr;
+LPITEMIDLIST pidl = 0;
+gchar *retval = 0;
+
+ if (S_OK == (hr = SHGetSpecialFolderLocation (0, csidl, &pidl)))
+ {
+ if (SHGetPathFromIDListW (pidl, path))
+ retval = g_utf16_to_utf8 ((const gunichar2*)path, -1, 0, 0, 0);
+ CoTaskMemFree (pidl);
+ }
+
+ return retval;
+}
+#endif // PLATFORM_WINDOWS
+
+namespace PBD {
+
+static gchar **fallback_folders = 0;
+
+//***************************************************************
+//
+// get_platform_fallback_folders()
+//
+// Returns an array of folders to fall back to if the folders
+// weren't named at build time and subsequently couldn't be found
+// in the user's environment. This might not be needed any more
+// because the function 'fixup_bundle_environment()' (in the
+// gtk2_ardour branch) now explicitly sets up any environment
+// paths that the program will need at run time. However, having
+// the folders here might help us to simplify the above function
+// which would be useful (currently, there are different versions
+// of 'fixup_bundle_environment()' for each supported platform).
+// Twelve fallback folders are currently catered for, corresponding to:-
+//
+// LOCALEDIR
+// GTK_DIR
+// CONFIG_DIR
+// ARDOUR_DIR
+// MODULE_DIR
+// DATA_DIR
+// ICONS_DIR
+// PIXMAPS_DIR
+// CONTROL_SURFACES_DIR
+// VAMP_DIR
+// LADSPA_PATH - note that there's only one entry in the path
+// VST_PATH - note that there may only be one entry in the path
+//
+// Returns:
+//
+// On Success: A pointer to an array containing the above dirs.
+// On Failure: NULL
+//
+#ifdef PLATFORM_WINDOWS // Would not be relevant for Cygwin!!
+
+static gchar**
+get_platform_fallback_folders ()
+{
+gchar **fallback_dir_vector = 0;
+const gchar *pUsrHome = 0; // Do not free !!
+
+ if (!fallback_folders)
+ {
+ GArray *pFallbackDirs;
+ gchar *pAppData = 0;
+ gchar *pMyAppData = 0;
+ gchar *pExeRoot = 0;
+ gchar *pPersonal = 0;
+
+ pFallbackDirs = g_array_new (TRUE, TRUE, sizeof (char *));
+
+ if (pFallbackDirs)
+ {
+ /* Get the path for the user's personal folder */
+ gchar *pPersonalTemp = get_win_special_folder (CSIDL_PERSONAL);
+
+ /* and the path for the user's personal application data */
+ gchar *pMyAppDataTemp = get_win_special_folder (CSIDL_LOCAL_APPDATA);
+
+ /* and the path for common application data ("Documents and Settings\All Users\Application Data") */
+ gchar *pAppDataTemp = get_win_special_folder (CSIDL_COMMON_APPDATA);
+
+ if (0 == pAppDataTemp)
+ pAppData = g_build_filename("C:\\", "Documents and Settings", "All Users", "Application Data", PROGRAM_NAME, "local", 0);
+ else
+ {
+ pAppData = g_build_filename(pAppDataTemp, PROGRAM_NAME, "local", 0);
+ g_free (pAppDataTemp);
+ }
+
+ if (0 == pMyAppDataTemp)
+ {
+ pMyAppData = g_build_filename(g_get_home_dir(), "Application Data", "local", 0);
+ }
+ else
+ {
+ pMyAppData = g_build_filename(pMyAppDataTemp, 0);
+ g_free (pMyAppDataTemp);
+ }
+
+ if (0 == pPersonalTemp)
+ pPersonal = g_build_filename(g_get_home_dir(), 0);
+ else
+ {
+ pPersonal = g_build_filename(pPersonalTemp, 0);
+ g_free (pPersonalTemp);
+ }
+
+ /* Get the path to the running application */
+ pExeRoot = g_win32_get_package_installation_directory_of_module (0);
+
+ if (0 == pExeRoot)
+ {
+ pExeRoot = g_build_filename("C:\\", "Program Files", PROGRAM_NAME, 0);
+ }
+
+ if ((pExeRoot) && (pAppData) && (pMyAppData) && (pPersonal))
+ {
+ gchar tmp[PATH_MAX+1];
+ gchar* p;
+
+ // Build our LOCALEDIR entry
+ if (0 != (p = g_build_filename(pAppData, "share", "locale", 0)))
+ {
+ g_array_append_val (pFallbackDirs, p);
+
+ // Build our GTK_DIR entry
+ if (0 != (p = g_build_filename(pPersonal, ".gtk-2.0", 0)))
+ {
+ g_array_append_val (pFallbackDirs, p);
+
+ // Build our CONFIG_DIR entry
+ if (0 != (p = g_build_filename(pAppData, "etc", 0)))
+ {
+ g_array_append_val (pFallbackDirs, p);
+
+ // Build our ARDOUR_DIR entry
+ p = g_build_filename(pMyAppData, PROGRAM_NAME, 0);
+
+ if (0 != p)
+ {
+ g_array_append_val (pFallbackDirs, p);
+
+ // Build our MODULE_DIR entry
+ strcpy(tmp, pExeRoot);
+ if (0 != (p = strrchr (tmp, G_DIR_SEPARATOR)))
+ {
+ *p = '\0';
+
+ if (0 != (p = g_build_filename(tmp, 0)))
+ {
+ g_array_append_val (pFallbackDirs, p);
+
+ // Build our DATA_DIR entry
+ if (0 != (p = g_build_filename(pAppData, "share", 0)))
+ {
+ g_array_append_val (pFallbackDirs, p);
+
+ // Build our ICONS_DIR entry
+ if (0 != (p = g_build_filename(pAppData, "share", "icons", 0)))
+ {
+ g_array_append_val (pFallbackDirs, p);
+
+ // Build our PIXMAPS_DIR entry
+ if (0 != (p = g_build_filename(pAppData, "share", "pixmaps", 0)))
+ {
+ g_array_append_val (pFallbackDirs, p);
+
+ // Build our CONTROL_SURFACES_DIR entry
+ if (0 != (p = g_build_filename(pExeRoot, "bin", "surfaces", 0)))
+ {
+ g_array_append_val (pFallbackDirs, p);
+
+ // Build our VAMP_DIR entry
+ p = g_build_filename(pExeRoot, "bin", "vamp", 0);
+ if (p)
+ g_array_append_val (pFallbackDirs, p);
+ else
+ g_array_append_val (pFallbackDirs, "");
+
+ // Next, build our LADSPA_PATH entry
+ p = g_build_filename(pExeRoot, "bin", "plugins", 0);
+ if (p)
+ g_array_append_val (pFallbackDirs, p);
+ else
+ g_array_append_val (pFallbackDirs, "");
+
+ // And finally, build our VST_PATH entry
+ DWORD dwType = REG_SZ; HKEY hKey;
+ DWORD dwSize = PATH_MAX; p = 0;
+ if (ERROR_SUCCESS == RegOpenKeyExA (HKEY_CURRENT_USER, "Software\\VST", 0, KEY_READ, &hKey))
+ {
+ // Look for the user's VST Registry entry
+ if (ERROR_SUCCESS == RegQueryValueExA (hKey, "VSTPluginsPath", 0, &dwType, (LPBYTE)tmp, &dwSize))
+ p = g_build_filename (Glib::locale_to_utf8(tmp).c_str(), 0);
+
+ RegCloseKey (hKey);
+ }
+
+ if (p == 0)
+ if (ERROR_SUCCESS == RegOpenKeyExA (HKEY_LOCAL_MACHINE, "Software\\VST", 0, KEY_READ, &hKey))
+ {
+ // Look for a global VST Registry entry
+ if (ERROR_SUCCESS == RegQueryValueExA (hKey, "VSTPluginsPath", 0, &dwType, (LPBYTE)tmp, &dwSize))
+ p = g_build_filename (Glib::locale_to_utf8(tmp).c_str(), 0);
+
+ RegCloseKey (hKey);
+ }
+
+ if (p == 0)
+ {
+ gchar *pVSTx86 = 0;
+ gchar *pProgFilesX86 = get_win_special_folder (CSIDL_PROGRAM_FILESX86);
+
+ if (pProgFilesX86)
+ {
+ // Look for a VST folder under C:\Program Files (x86)
+ if (pVSTx86 = g_build_filename (pProgFilesX86, "Steinberg", "VSTPlugins", 0))
+ {
+ if (Glib::file_test (pVSTx86, Glib::FILE_TEST_EXISTS))
+ if (Glib::file_test (pVSTx86, Glib::FILE_TEST_IS_DIR))
+ p = g_build_filename (pVSTx86, 0);
+
+ g_free (pVSTx86);
+ }
+
+ g_free (pProgFilesX86);
+ }
+
+ if (p == 0)
+ {
+ // Look for a VST folder under C:\Program Files
+ gchar *pVST = 0;
+ gchar *pProgFiles = get_win_special_folder (CSIDL_PROGRAM_FILES);
+
+ if (pProgFiles)
+ {
+ if (pVST = g_build_filename (pProgFiles, "Steinberg", "VSTPlugins", 0))
+ {
+ if (Glib::file_test (pVST, Glib::FILE_TEST_EXISTS))
+ if (Glib::file_test (pVST, Glib::FILE_TEST_IS_DIR))
+ p = g_build_filename (pVST, 0);
+
+ g_free (pVST);
+ }
+
+ g_free (pProgFiles);
+ }
+ }
+ }
+
+ if (p == 0)
+ {
+ // If all else failed, assume the plugins are under "My Documents"
+ pUsrHome = g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS);
+ if (pUsrHome)
+ p = g_build_filename (pUsrHome, "Plugins", "VST", 0);
+ else
+ {
+ pUsrHome = g_build_filename(g_get_home_dir(), "My Documents", 0);
+ if (pUsrHome)
+ p = g_build_filename (pUsrHome, "Plugins", "VST", 0);
+ }
+ }
+ else
+ {
+ gchar* q = 0;
+
+ // Concatenate the registry path with the user's personal path
+ pUsrHome = g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS);
+
+ if (pUsrHome)
+ {
+ q = p;
+ p = g_build_path (";", q, g_build_filename(pUsrHome, "Plugins", "VST", 0), 0);
+ }
+ else
+ {
+ pUsrHome = g_build_filename(g_get_home_dir(), "My Documents", 0);
+ if (pUsrHome)
+ {
+ q = p;
+ p = g_build_path (";", q, g_build_filename (pUsrHome, "Plugins", "VST", 0), 0);
+ }
+ }
+ }
+
+ if (p) //VST
+ g_array_append_val (pFallbackDirs, p);
+ else
+ g_array_append_val (pFallbackDirs, "");
+
+ // BUNDLED_LV2
+ p = g_build_filename(pExeRoot, "bin", "lv2", 0);
+ if (p)
+ g_array_append_val (pFallbackDirs, p);
+ else
+ g_array_append_val (pFallbackDirs, "");
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ g_free (pAppData);
+ g_free (pMyAppData);
+ g_free (pExeRoot);
+ g_free (pPersonal);
+ }
+
+ fallback_dir_vector = fallback_folders = (gchar **) g_array_free (pFallbackDirs, FALSE);
+ }
+ }
+ else
+ fallback_dir_vector = fallback_folders;
+
+ return (fallback_dir_vector);
+}
+
+#else
+// Assume Linux, Cygwin or OS-X. Note that in all 3 cases we only
+// need to cater for unbundled releases (those built by a user from
+// source). Bundled releases of Ardour and Mixbus now specifically
+// write their folders and paths to the user's environment at startup.
+// See the function 'fixup_bundle_environment()'.
+
+static gchar**
+get_platform_fallback_folders ()
+{
+gchar **fallback_dir_vector = 0;
+gchar *pUsrHome = 0;
+
+ if (!fallback_folders)
+ {
+ GArray *pFallbackDirs;
+ gchar *pAppData = 0;
+ gchar *pExeRoot = 0;
+ gchar *pPersonal = 0;
+
+ pFallbackDirs = g_array_new (TRUE, TRUE, sizeof (char *));
+
+ if (pFallbackDirs)
+ {
+ pAppData = g_build_filename("/usr", "local", 0);
+ pExeRoot = g_build_filename("/usr", "local", "lib", "ardour2", 0);
+ pPersonal = g_build_filename(g_get_home_dir(), 0);
+
+ if ((pExeRoot) && (pAppData) && (pPersonal))
+ {
+ gchar tmp[PATH_MAX+1];
+ gchar* p;
+
+ // Build our LOCALEDIR entry
+ if (0 != (p = g_build_filename(pAppData, "share", "locale", 0)))
+ {
+ g_array_append_val (pFallbackDirs, p);
+
+ // Build our GTK_DIR entry
+ if (0 != (p = g_build_filename(pPersonal, ".gtk-2.0", 0)))
+ {
+ g_array_append_val (pFallbackDirs, p);
+
+ // Build our CONFIG_DIR entry
+ if (0 != (p = g_build_filename(pAppData, "etc", 0)))
+ {
+ g_array_append_val (pFallbackDirs, p);
+
+ // Build our ARDOUR_DIR entry
+ p = ""; // Empty string (temporary)
+ if (0 != p)
+ {
+ g_array_append_val (pFallbackDirs, p);
+
+ // Build our MODULE_DIR entry
+ strcpy(tmp, pExeRoot);
+ if (0 != (p = strrchr (tmp, G_DIR_SEPARATOR)))
+ {
+ *p = '\0';
+
+ if (0 != (p = g_build_filename(tmp, 0)))
+ {
+ g_array_append_val (pFallbackDirs, p);
+
+ // Build our DATA_DIR entry
+ if (0 != (p = g_build_filename(pAppData, "share", 0)))
+ {
+ g_array_append_val (pFallbackDirs, p);
+
+ // Build our ICONS_DIR entry (re-use 'tmp')
+ strcpy(tmp, "/usr/local/share/ardour2");
+ if (0 != (p = g_build_filename(tmp, "icons", 0)))
+ {
+ g_array_append_val (pFallbackDirs, p);
+
+ // Build our PIXMAPS_DIR entry
+ if (0 != (p = g_build_filename(tmp, "pixmaps", 0)))
+ {
+ g_array_append_val (pFallbackDirs, p);
+
+ // Build our CONTROL_SURFACES_DIR entry
+ if (0 != (p = g_build_filename(pExeRoot, "surfaces", 0)))
+ {
+ g_array_append_val (pFallbackDirs, p);
+
+ // Build our VAMP_DIR entry
+ p = g_build_filename(pExeRoot, "vamp", 0);
+ if (p)
+ g_array_append_val (pFallbackDirs, p);
+
+ // Next, build our LADSPA_PATH entry
+ p = g_build_filename(Glib::path_get_dirname(pExeRoot).c_str(), "plugins", 0);
+ if (p)
+ g_array_append_val (pFallbackDirs, p);
+
+ // And finally, build our VST_PATH entry
+ if (g_getenv("HOME"))
+ p = g_build_filename(g_getenv("HOME"), "VST", "plugins", 0);
+ else
+ p = g_build_filename(g_get_home_dir(), "VST", "plugins", 0);
+
+ if (p)
+ g_array_append_val (pFallbackDirs, p);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ g_free (pAppData);
+ g_free (pExeRoot);
+ g_free (pPersonal);
+ }
+
+ fallback_dir_vector = fallback_folders = (gchar **) g_array_free (pFallbackDirs, FALSE);
+ }
+ }
+ else
+ fallback_dir_vector = fallback_folders;
+
+ if (pUsrHome)
+ g_free (pUsrHome);
+
+ return (fallback_dir_vector);
+}
+#endif
+
+
+//***************************************************************
+//
+// get_platform_fallback_folder()
+//
+// Returns a const gchar* which points to a string describing
+// the full path to the Ardour fallback folder corresponding to
+// the supplied index. See 'get_platform_fallback_folders()' for a
+// complete list of the supported index enumerations. Calling this
+// function will initialize the fallback folder array if it wasn't
+// already initiaized. The array should then (eventually) be freed
+// using 'free_platform_fallback_folders()'.
+//
+// Returns:
+//
+// On Success: A pointer to the path string contained at the
+// relevant index.
+// On Failure: NULL
+//
+LIBPBD_API G_CONST_RETURN gchar* PBD_APICALLTYPE
+get_platform_fallback_folder (PBD::fallback_folder_t index)
+{
+ if ((index >= 0) && (index < FALLBACK_FOLDER_MAX))
+ return ((G_CONST_RETURN gchar *)get_platform_fallback_folders ()[index]);
+ else
+ return (G_CONST_RETURN gchar *) 0;
+}
+
+
+//***************************************************************
+//
+// alloc_platform_fallback_folders()
+//
+// Calls 'get_platform_fallback_folders()' to ensure that memory
+// for the fallback folder array is already allocated before the
+// array gets used. It doesn't cause any problems if the array gets
+// used prior to calling this function (since the memory will get
+// allocated anyway, on fist usage). Either way however, the momory
+// must later be freed using 'free_platform_fallback_folders()'.
+//
+// Returns:
+//
+// The value obtained from 'get_platform_fallback_folders()'
+//
+LIBPBD_API G_CONST_RETURN gchar* G_CONST_RETURN * PBD_APICALLTYPE
+alloc_platform_fallback_folders ()
+{
+ return ((G_CONST_RETURN gchar* G_CONST_RETURN *)get_platform_fallback_folders ());
+}
+
+
+//***************************************************************
+//
+// free_platform_fallback_folders()
+//
+// Frees the memory that was previously allocated for the Ardour
+// fallback folder array.
+//
+// Returns:
+//
+// NONE.
+//
+LIBPBD_API void PBD_APICALLTYPE
+free_platform_fallback_folders ()
+{
+int index = FOLDER_LOCALE;
+
+ if (fallback_folders)
+ {
+ gchar *p = get_platform_fallback_folders()[(fallback_folder_t)index++];
+
+ while (index < (FALLBACK_FOLDER_MAX+1)) {
+ if (p)
+ g_free (p);
+
+ if (index < FALLBACK_FOLDER_MAX)
+ p = get_platform_fallback_folders()[(fallback_folder_t)index++];
+ else
+ break;
+ }
+
+ fallback_folders = 0;
+ }
+}
+
+} // namespace PBD
+
diff --git a/libs/pbd/ffs.cc b/libs/pbd/ffs.cc
new file mode 100644
index 0000000000..557504f14e
--- /dev/null
+++ b/libs/pbd/ffs.cc
@@ -0,0 +1,49 @@
+/*
+ Copyright (C) 2013 Tim Mayberry
+
+ 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.
+
+*/
+
+#include "pbd/ffs.h"
+
+#ifndef COMPILER_MSVC
+#include <strings.h>
+#endif
+
+namespace PBD {
+int
+ffs (int x)
+{
+#if defined (COMPILER_MINGW)
+ return __builtin_ffs(x);
+#elif defined (COMPILER_MSVC)
+ unsigned long index;
+#ifdef WIN64
+ if (0 != _BitScanForward64(&index, (__int64)x))
+#else
+ if (0 != _BitScanForward(&index, (unsigned long)x))
+#endif
+ index++; // Make the result 1-based
+ else
+ index = 0; // All bits were zero
+
+ return (int)index;
+#else
+ return ::ffs(x);
+#endif
+}
+
+}
diff --git a/libs/pbd/file_manager.cc b/libs/pbd/file_manager.cc
index a71ffca190..2cfa63ae39 100644
--- a/libs/pbd/file_manager.cc
+++ b/libs/pbd/file_manager.cc
@@ -18,19 +18,22 @@
*/
#include <sys/time.h>
-#include <sys/resource.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <cassert>
#include <cstdio>
+#include <glib.h>
+#include <glib/gstdio.h>
+
#ifdef __APPLE__
#include <mach/mach_time.h>
#endif
#include "pbd/compose.h"
#include "pbd/file_manager.h"
+#include "pbd/resource.h"
#include "pbd/debug.h"
using namespace std;
@@ -41,12 +44,11 @@ FileManager* FileDescriptor::_manager;
FileManager::FileManager ()
: _open (0)
{
- struct rlimit rl;
- int const r = getrlimit (RLIMIT_NOFILE, &rl);
+ struct ResourceLimit rl;
/* XXX: this is a bit arbitrary */
- if (r == 0) {
- _max_open = rl.rlim_cur - 64;
+ if (get_resource_limit (OpenFiles, rl)) {
+ _max_open = rl.current_limit - 64;
} else {
_max_open = 256;
}
@@ -116,10 +118,14 @@ FileManager::allocate (FileDescriptor* d)
#ifdef __APPLE__
d->_last_used = mach_absolute_time();
-#else
+#elif defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK)
struct timespec t;
clock_gettime (CLOCK_MONOTONIC, &t);
d->_last_used = t.tv_sec + (double) t.tv_nsec / 10e9;
+#else
+ struct timeval now;
+ gettimeofday (&now, NULL);
+ d->_last_used = now.tv_sec + (double) now.tv_usec / 10e6;
#endif
d->_refcount++;
@@ -222,8 +228,19 @@ bool
FdFileDescriptor::open ()
{
/* we must have a lock on the FileManager's mutex */
-
- _fd = ::open (_path.c_str(), _writeable ? (O_RDWR | O_CREAT) : O_RDONLY, _mode);
+
+ /* files must be opened with O_BINARY flag on windows
+ * or it treats the file as a text stream and puts in
+ * line endings in etc
+ */
+#ifdef WIN32
+#define WRITE_FLAGS O_RDWR | O_CREAT | O_BINARY
+#define READ_FLAGS O_RDONLY | O_BINARY
+#else
+#define WRITE_FLAGS O_RDWR | O_CREAT
+#define READ_FLAGS O_RDONLY
+#endif
+ _fd = ::g_open (_path.c_str(), _writeable ? WRITE_FLAGS : READ_FLAGS, _mode);
return (_fd == -1);
}
diff --git a/libs/pbd/file_utils.cc b/libs/pbd/file_utils.cc
index bb290fa6aa..44254989c1 100644
--- a/libs/pbd/file_utils.cc
+++ b/libs/pbd/file_utils.cc
@@ -23,6 +23,10 @@
#include <glib.h>
#include <glib/gstdio.h>
+#ifdef COMPILER_MINGW
+#include <io.h> // For W_OK
+#endif
+
#include <glibmm/fileutils.h>
#include <glibmm/miscutils.h>
#include <glibmm/pattern.h>
@@ -31,6 +35,7 @@
#include "pbd/compose.h"
#include "pbd/file_utils.h"
+#include "pbd/debug.h"
#include "pbd/error.h"
#include "pbd/pathscanner.h"
#include "pbd/stl_delete.h"
@@ -76,6 +81,11 @@ find_matching_files_in_directory (const std::string& directory,
std::string full_path(directory);
full_path = Glib::build_filename (full_path, *file_iter);
+ DEBUG_TRACE (
+ DEBUG::FileUtils,
+ string_compose("Found file %1\n", full_path)
+ );
+
result.push_back(full_path);
}
}
@@ -94,7 +104,7 @@ find_matching_files_in_directories (const vector<std::string>& paths,
}
void
-find_matching_files_in_search_path (const SearchPath& search_path,
+find_matching_files_in_search_path (const Searchpath& search_path,
const Glib::PatternSpec& pattern,
vector<std::string>& result)
{
@@ -102,7 +112,7 @@ find_matching_files_in_search_path (const SearchPath& search_path,
}
bool
-find_file_in_search_path(const SearchPath& search_path,
+find_file_in_search_path(const Searchpath& search_path,
const string& filename,
std::string& result)
{
@@ -113,24 +123,28 @@ find_file_in_search_path(const SearchPath& search_path,
if (tmp.size() == 0)
{
+ DEBUG_TRACE (
+ DEBUG::FileUtils,
+ string_compose("No file matching %1 found in Path: %2\n", filename, search_path.to_string())
+ );
return false;
}
-#if 0
if (tmp.size() != 1)
{
- info << string_compose
- (
- "Found more than one file matching %1 in search path %2",
- filename,
- search_path ()
- )
- << endmsg;
+ DEBUG_TRACE (
+ DEBUG::FileUtils,
+ string_compose("Found more that one file matching %1 in Path: %2\n", filename, search_path.to_string())
+ );
}
-#endif
result = tmp.front();
+ DEBUG_TRACE (
+ DEBUG::FileUtils,
+ string_compose("Found file %1 in Path: %2\n", filename, search_path.to_string())
+ );
+
return true;
}
@@ -188,9 +202,9 @@ get_absolute_path (const std::string & p)
bool
equivalent_paths (const std::string& a, const std::string& b)
{
- struct stat bA;
+ GStatBuf bA;
int const rA = g_stat (a.c_str(), &bA);
- struct stat bB;
+ GStatBuf bB;
int const rB = g_stat (b.c_str(), &bB);
return (rA == 0 && rB == 0 && bA.st_dev == bB.st_dev && bA.st_ino == bB.st_ino);
@@ -221,7 +235,7 @@ exists_and_writable (const std::string & p)
make us unwritable.
*/
- struct stat statbuf;
+ GStatBuf statbuf;
if (g_stat (p.c_str(), &statbuf) != 0) {
/* doesn't exist - not writable */
diff --git a/libs/pbd/fpu.cc b/libs/pbd/fpu.cc
index 8929491cd9..73bc7e599d 100644
--- a/libs/pbd/fpu.cc
+++ b/libs/pbd/fpu.cc
@@ -16,7 +16,7 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-
+#ifndef COMPILER_MSVC
#include "libpbd-config.h"
#define _XOPEN_SOURCE 600
@@ -141,3 +141,7 @@ FPU::FPU ()
FPU::~FPU ()
{
}
+
+#else // COMPILER_MSVC
+ const char* pbd_fpu = "pbd/msvc/fpu.cc takes precedence over this file";
+#endif // COMPILER_MSVC
diff --git a/libs/pbd/glib_semaphore.cc b/libs/pbd/glib_semaphore.cc
new file mode 100644
index 0000000000..7565e0c069
--- /dev/null
+++ b/libs/pbd/glib_semaphore.cc
@@ -0,0 +1,68 @@
+/*
+ Copyright (C) 2010 Tim Mayberry
+
+ 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.
+
+*/
+
+#include "pbd/glib_semaphore.h"
+
+namespace PBD {
+
+GlibSemaphore::GlibSemaphore (gint initial_val)
+ :
+ m_counter(initial_val)
+{ }
+
+void
+GlibSemaphore::wait ()
+{
+ Glib::Threads::Mutex::Lock guard (m_mutex);
+
+ while (m_counter.get() < 1) {
+ m_cond.wait(m_mutex);
+ }
+
+ // this shouldn't need to be inside the lock
+ --m_counter;
+}
+
+bool
+GlibSemaphore::try_wait ()
+{
+ if (!m_mutex.trylock())
+ {
+ return false;
+ }
+ // lock successful
+ while (m_counter.get() < 1) {
+ m_cond.wait(m_mutex);
+ }
+
+ // the order of these should not matter
+ --m_counter;
+ m_mutex.unlock();
+ return true;
+}
+
+void
+GlibSemaphore::post ()
+{
+ // atomic, no locking required
+ ++m_counter;
+ m_cond.signal();
+}
+
+} // namespace PBD
diff --git a/libs/pbd/localeguard.cc b/libs/pbd/localeguard.cc
new file mode 100644
index 0000000000..12093beeaa
--- /dev/null
+++ b/libs/pbd/localeguard.cc
@@ -0,0 +1,34 @@
+#include <cstring>
+#include <locale.h>
+#include <stdlib.h>
+
+#include "pbd/localeguard.h"
+
+// JE - added temporarily, to reduce the delay effects when calling
+// setlocale() recursively in a Windows GUI thread (we should think
+// about moving the caller(s) into a dedicated worker thread).
+std::string PBD::LocaleGuard::current;
+
+PBD::LocaleGuard::LocaleGuard (const char* str)
+ : old(0)
+{
+ if (current != str) {
+ old = strdup (setlocale (LC_NUMERIC, NULL));
+ if (strcmp (old, str)) {
+ if (setlocale (LC_NUMERIC, str))
+ current = str;
+ }
+ }
+}
+
+PBD::LocaleGuard::~LocaleGuard ()
+{
+ if (old) {
+ if (setlocale (LC_NUMERIC, old))
+ current = old;
+
+ free ((char*)old);
+ }
+}
+
+
diff --git a/libs/pbd/localtime_r.cc b/libs/pbd/localtime_r.cc
new file mode 100644
index 0000000000..c72e3eb458
--- /dev/null
+++ b/libs/pbd/localtime_r.cc
@@ -0,0 +1,41 @@
+#ifdef WAF_BUILD
+#include "libpbd-config.h"
+#endif
+
+#ifndef HAVE_LOCALTIME_R
+#include <time.h>
+#include <string.h>
+
+#include "pbd/pthread_utils.h"
+#include "pbd/localtime_r.h"
+
+#ifdef localtime_r
+#undef localtime_r
+#endif
+
+struct tm *
+localtime_r(const time_t *const timep, struct tm *p_tm)
+{
+ static pthread_mutex_t time_mutex;
+ static int time_mutex_inited = 0;
+ struct tm *tmp;
+
+ if (!time_mutex_inited)
+ {
+ time_mutex_inited = 1;
+ pthread_mutex_init(&time_mutex, NULL);
+ }
+
+ pthread_mutex_lock(&time_mutex);
+ tmp = localtime(timep);
+ if (tmp)
+ {
+ memcpy(p_tm, tmp, sizeof(struct tm));
+ tmp = p_tm;
+ }
+ pthread_mutex_unlock(&time_mutex);
+
+ return tmp;
+}
+
+#endif
diff --git a/libs/pbd/mountpoint.cc b/libs/pbd/mountpoint.cc
index 46cea42e0a..65f011c745 100644
--- a/libs/pbd/mountpoint.cc
+++ b/libs/pbd/mountpoint.cc
@@ -17,7 +17,7 @@
$Id$
*/
-
+#ifndef COMPILER_MSVC
#include <cstdio>
#include <cstring>
#include <string>
@@ -94,6 +94,14 @@ mountpoint (string path)
return best;
}
+#elif defined(PLATFORM_WINDOWS)
+
+string
+mountpoint (string path)
+{
+ // TODO ... if needed
+}
+
#else // !HAVE_GETMNTENT
#include <sys/param.h>
@@ -164,3 +172,7 @@ main (int argc, char *argv[])
}
#endif // TEST_MOUNTPOINT
+
+#else // COMPILER_MSVC
+ const char* pbd_mountpoint = "pbd/msvc/mountpoint.cc takes precedence over this file";
+#endif // COMPILER_MSVC
diff --git a/libs/pbd/msvc/fpu.cc b/libs/pbd/msvc/fpu.cc
new file mode 100644
index 0000000000..6997405928
--- /dev/null
+++ b/libs/pbd/msvc/fpu.cc
@@ -0,0 +1,124 @@
+#ifdef COMPILER_MSVC // Added by JE - 05-12-2009. Inline assembler instructions
+ // have been changed to Intel format and (in the case of
+ // cpuid) was replaced by the equivalent VC++ system call).
+#define _XOPEN_SOURCE 600
+#include <cstdlib>
+#include <stdint.h>
+#include <intrin.h> // Added by JE - 05-12-2009
+
+#include <pbd/fpu.h>
+#include <pbd/error.h>
+
+#include "i18n.h"
+
+using namespace PBD;
+using namespace std;
+
+FPU::FPU ()
+{
+ unsigned long cpuflags = 0;
+
+ _flags = (Flags)0;
+
+#ifndef ARCH_X86
+ return;
+
+#else
+
+#ifndef USE_X86_64_ASM
+int cpuInfo[4];
+
+ __cpuid (cpuInfo, 1);
+ cpuflags = cpuInfo[3];
+/*
+ __asm { // This is how the original section would look if converted to Intel syntax.
+ // However, I have grave doubts about whether it's doing the right thing.
+ // It seems as if the intention was to retrieve feature information from
+ // the processor. However, feature information is returned in the ebx register
+ // (if you believe Wikipedia) or in edx (if you believe Microsoft). Unfortunately,
+ // both registers get ignored in the original code!! Confused?? Join the club!!
+ mov eax, 1
+ push ebx
+ cpuid
+ mov edx, 0
+ pop ebx
+ mov cpuflags, ecx // This can't be right, surely???
+ }; */
+#else
+// Note that this syntax is currently still in AT&T format !
+ asm volatile (
+ "pushq %%rbx\n"
+ "movq $1, %%rax\n"
+ "cpuid\n"
+ "movq %%rdx, %0\n"
+ "popq %%rbx\n"
+ : "=r" (cpuflags)
+ :
+ : "%rax", "%rcx", "%rdx", "memory"
+ );
+
+#endif /* USE_X86_64_ASM */
+
+ if (cpuflags & (1<<25)) {
+ _flags = Flags (_flags | (HasSSE|HasFlushToZero));
+ }
+
+ if (cpuflags & (1<<26)) {
+ _flags = Flags (_flags | HasSSE2);
+ }
+
+ if (cpuflags & (1 << 24)) {
+ bool aligned_malloc = false; // Added by JE - 05-12-2009
+ char* fxbuf = 0;
+// This section changed by JE - 05-12-2009
+#ifdef NO_POSIX_MEMALIGN
+#if defined(COMPILER_MSVC) || defined(COMPILER_MINGW) // All of these support '_aligned_malloc()'
+ fxbuf = (char *) _aligned_malloc(512, 16); // (note that they all need at least MSVC runtime 7.0)
+ aligned_malloc = true;
+#else
+ fxbuf = (char *) malloc(512);
+#endif
+#else
+ fxbuf = posix_memalign ((void**)&fxbuf, 16, 512);
+#endif
+ // Verify that fxbuf is correctly aligned
+ unsigned long buf_addr = (unsigned long)(void*)fxbuf;
+ if ((0 == buf_addr) || (buf_addr % 16))
+ error << _("cannot allocate 16 byte aligned buffer for h/w feature detection") << endmsg;
+ else
+ {
+ memset(fxbuf, 0, 512); // Initialize the buffer !!! Added by JE - 12-12-2009
+
+ __asm {
+ mov eax, fxbuf
+ fxsave [eax]
+ };
+
+ uint32_t mxcsr_mask = *((uint32_t*) &fxbuf[28]);
+
+ /* if the mask is zero, set its default value (from intel specs) */
+
+ if (mxcsr_mask == 0) {
+ mxcsr_mask = 0xffbf;
+ }
+
+ if (mxcsr_mask & (1<<6)) {
+ _flags = Flags (_flags | HasDenormalsAreZero);
+ }
+
+ if (aligned_malloc)
+ _aligned_free (fxbuf);
+ else
+ free (fxbuf);
+ }
+ }
+#endif // ARCH_X86
+}
+
+FPU::~FPU ()
+{
+}
+
+#else // !COMPILER_MSVC
+ const char* pbd_fpu = "original pbd/fpu.cc takes precedence over this file";
+#endif // COMPILER_MSVC
diff --git a/libs/pbd/msvc/getopt.c b/libs/pbd/msvc/getopt.c
new file mode 100644
index 0000000000..2f539a59cf
--- /dev/null
+++ b/libs/pbd/msvc/getopt.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 1987, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef COMPILER_MSVC
+#include "pbd/msvc_pbd.h"
+#endif
+#include "getopt.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define BADCH (int)'?'
+#define BADARG (int)':'
+#define EMSG ""
+
+__BEGIN_DECLS // Added by JE - 31-01-2010
+// All 'GETOPT_API' declarations added by JE - 31-01-2010
+GETOPT_API int opterr = 1; /* if error message should be printed */
+GETOPT_API int optind = 1; /* index into parent argv vector */
+GETOPT_API int optopt; /* character checked for validity */
+GETOPT_API int optreset; /* reset getopt */
+GETOPT_API char *optarg; /* argument associated with option */
+
+/*
+ * getopt --
+ * Parse argc/argv argument vector.
+ */
+int
+getopt(int nargc, // Argument list ratified by JE - 03-01-2010
+ char * const *nargv,
+ const char *ostr)
+{
+ static char *place = EMSG; /* option letter processing */
+ char *oli; /* option letter list index */
+
+ if (optreset || !*place) { /* update scanning pointer */
+ optreset = 0;
+ if (optind >= nargc || *(place = nargv[optind]) != '-') {
+ place = EMSG;
+ return (-1);
+ }
+ if (place[1] && *++place == '-') { /* found "--" */
+ ++optind;
+ place = EMSG;
+ return (-1);
+ }
+ } /* option letter okay? */
+ if ((optopt = (int)*place++) == (int)':' ||
+ !(oli = (char*)strchr(ostr, optopt))) {
+ /*
+ * if the user didn't specify '-' as an option,
+ * assume it means -1.
+ */
+ if (optopt == (int)'-')
+ return (-1);
+ if (!*place)
+ ++optind;
+ if (opterr && *ostr != ':' && optopt != BADCH)
+ (void)fprintf(stderr, "%s: illegal option -- %c\n",
+ "progname", optopt);
+ return (BADCH);
+ }
+ if (*++oli != ':') { /* don't need argument */
+ optarg = NULL;
+ if (!*place)
+ ++optind;
+ }
+ else { /* need an argument */
+ if (*place) /* no white space */
+ optarg = place;
+ else if (nargc <= ++optind) { /* no arg */
+ place = EMSG;
+ if (*ostr == ':')
+ return (BADARG);
+ if (opterr)
+ (void)fprintf(stderr,
+ "%s: option requires an argument -- %c\n",
+ "progname", optopt);
+ return (BADCH);
+ }
+ else /* white space */
+ optarg = nargv[optind];
+ place = EMSG;
+ ++optind;
+ }
+ return (optopt); /* dump back option letter */
+}
+__END_DECLS // Added by JE - 31-01-2010
diff --git a/libs/pbd/msvc/getopt.h b/libs/pbd/msvc/getopt.h
new file mode 100644
index 0000000000..233a0eefa6
--- /dev/null
+++ b/libs/pbd/msvc/getopt.h
@@ -0,0 +1,110 @@
+/* $NetBSD: getopt.h,v 1.4 2000/07/07 10:43:54 ad Exp $ */
+/* $FreeBSD: src/include/getopt.h,v 1.1 2002/09/29 04:14:30 eric Exp $ */
+
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Dieter Baron and Thomas Klausner.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _GETOPT_H_
+#define _GETOPT_H_
+
+#ifdef PLATFORM_WINDOWS
+/* from <sys/cdefs.h> */
+# ifdef __cplusplus
+# define __BEGIN_DECLS extern "C" {
+# define __END_DECLS }
+# else
+# define __BEGIN_DECLS
+# define __END_DECLS
+# endif
+# define __P(args) args
+#endif
+
+/*#ifndef PLATFORM_WINDOWS
+#include <sys/cdefs.h>
+#include <unistd.h>
+#endif*/
+
+#ifdef PLATFORM_WINDOWS
+# if !defined(GETOPT_API)
+# define GETOPT_API __declspec(dllimport)
+# endif
+#endif
+
+/*
+ * Gnu like getopt_long() and BSD4.4 getsubopt()/optreset extensions
+ */
+#if !defined(_POSIX_SOURCE) && !defined(_XOPEN_SOURCE)
+#define no_argument 0
+#define required_argument 1
+#define optional_argument 2
+
+struct option {
+ /* name of long option */
+ const char *name;
+ /*
+ * one of no_argument, required_argument, and optional_argument:
+ * whether option takes an argument
+ */
+ int has_arg;
+ /* if not NULL, set *flag to val when option found */
+ int *flag;
+ /* if flag not NULL, value to set *flag to; else return value */
+ int val;
+};
+
+__BEGIN_DECLS
+GETOPT_API int getopt_long __P((int, char * const *, const char *,
+ const struct option *, int *));
+__END_DECLS
+#endif
+
+#ifdef PLATFORM_WINDOWS
+/* These are global getopt variables */
+__BEGIN_DECLS
+
+GETOPT_API extern int opterr, /* if error message should be printed */
+ optind, /* index into parent argv vector */
+ optopt, /* character checked for validity */
+ optreset; /* reset getopt */
+GETOPT_API extern char* optarg; /* argument associated with option */
+
+/* Original getopt */
+GETOPT_API int getopt __P((int, char * const *, const char *));
+
+__END_DECLS
+#endif
+
+#endif /* !_GETOPT_H_ */
diff --git a/libs/pbd/msvc/getopt_long.c b/libs/pbd/msvc/getopt_long.c
new file mode 100644
index 0000000000..06c459ab84
--- /dev/null
+++ b/libs/pbd/msvc/getopt_long.c
@@ -0,0 +1,546 @@
+/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */
+/* $FreeBSD: src/lib/libc/stdlib/getopt_long.c,v 1.2 2002/10/16 22:18:42 alfred Exp $ */
+
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Dieter Baron and Thomas Klausner.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef PLATFORM_WINDOWS
+#ifdef COMPILER_MSVC
+#include "pbd/msvc_pbd.h" // Defines 'GETOPT_API'
+#endif
+/* Windows needs warnx(). We change the definition though:
+ * 1. (another) global is defined, opterrmsg, which holds the error message
+ * 2. errors are always printed out on stderr w/o the program name
+ * Note that opterrmsg always gets set no matter what opterr is set to. The
+ * error message will not be printed if opterr is 0 as usual.
+ */
+
+#include "getopt.h"
+#include <stdio.h>
+#include <stdarg.h>
+
+GETOPT_API extern char opterrmsg[128];
+char opterrmsg[128]; /* last error message is stored here */
+
+static void warnx(int print_error, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ if (fmt != NULL)
+ _vsnprintf(opterrmsg, 128, fmt, ap);
+ else
+ opterrmsg[0]='\0';
+ va_end(ap);
+ if (print_error) {
+ fprintf(stderr, opterrmsg);
+ fprintf(stderr, "\n");
+ }
+}
+
+#endif /*PLATFORM_WINDOWS*/
+
+/* not part of the original file */
+#ifndef _DIAGASSERT
+#define _DIAGASSERT(X)
+#endif
+
+#if HAVE_CONFIG_H && !HAVE_GETOPT_LONG && !HAVE_DECL_OPTIND
+#define REPLACE_GETOPT
+#endif
+
+#ifdef REPLACE_GETOPT
+#ifdef __weak_alias
+__weak_alias(getopt,_getopt)
+#endif
+int opterr = 1; /* if error message should be printed */
+int optind = 1; /* index into parent argv vector */
+int optopt = '?'; /* character checked for validity */
+int optreset; /* reset getopt */
+char *optarg; /* argument associated with option */
+#elif HAVE_CONFIG_H && !HAVE_DECL_OPTRESET
+static int optreset;
+#endif
+
+#ifdef __weak_alias
+__weak_alias(getopt_long,_getopt_long)
+#endif
+
+#if !HAVE_GETOPT_LONG
+#define IGNORE_FIRST (*options == '-' || *options == '+')
+#define PRINT_ERROR ((opterr) && ((*options != ':') \
+ || (IGNORE_FIRST && options[1] != ':')))
+#define IS_POSIXLY_CORRECT (getenv("POSIXLY_CORRECT") != NULL)
+#define PERMUTE (!IS_POSIXLY_CORRECT && !IGNORE_FIRST)
+/* XXX: GNU ignores PC if *options == '-' */
+#define IN_ORDER (!IS_POSIXLY_CORRECT && *options == '-')
+
+/* return values */
+#define BADCH (int)'?'
+#define BADARG ((IGNORE_FIRST && options[1] == ':') \
+ || (*options == ':') ? (int)':' : (int)'?')
+#define INORDER (int)1
+
+#define EMSG ""
+
+static int getopt_internal(int, char * const *, const char *);
+static int gcd(int, int);
+static void permute_args(int, int, int, char * const *);
+
+static char *place = EMSG; /* option letter processing */
+
+/* XXX: set optreset to 1 rather than these two */
+static int nonopt_start = -1; /* first non option argument (for permute) */
+static int nonopt_end = -1; /* first option after non options (for permute) */
+
+/* Error messages */
+static const char recargchar[] = "option requires an argument -- %c";
+static const char recargstring[] = "option requires an argument -- %s";
+static const char ambig[] = "ambiguous option -- %.*s";
+static const char noarg[] = "option doesn't take an argument -- %.*s";
+static const char illoptchar[] = "unknown option -- %c";
+static const char illoptstring[] = "unknown option -- %s";
+
+
+/*
+ * Compute the greatest common divisor of a and b.
+ */
+static int
+gcd(int a, int b)
+{
+ int c;
+
+ c = a % b;
+ while (c != 0) {
+ a = b;
+ b = c;
+ c = a % b;
+ }
+
+ return b;
+}
+
+/*
+ * Exchange the block from nonopt_start to nonopt_end with the block
+ * from nonopt_end to opt_end (keeping the same order of arguments
+ * in each block).
+ */
+static void
+permute_args(int panonopt_start,
+ int panonopt_end,
+ int opt_end,
+ char * const *nargv)
+{
+ int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
+ char *swap;
+
+ _DIAGASSERT(nargv != NULL);
+
+ /*
+ * compute lengths of blocks and number and size of cycles
+ */
+ nnonopts = panonopt_end - panonopt_start;
+ nopts = opt_end - panonopt_end;
+ ncycle = gcd(nnonopts, nopts);
+ cyclelen = (opt_end - panonopt_start) / ncycle;
+
+ for (i = 0; i < ncycle; i++) {
+ cstart = panonopt_end+i;
+ pos = cstart;
+ for (j = 0; j < cyclelen; j++) {
+ if (pos >= panonopt_end)
+ pos -= nnonopts;
+ else
+ pos += nopts;
+ swap = nargv[pos];
+ /* LINTED const cast */
+ ((char **) nargv)[pos] = nargv[cstart];
+ /* LINTED const cast */
+ ((char **)nargv)[cstart] = swap;
+ }
+ }
+}
+
+/*
+ * getopt_internal --
+ * Parse argc/argv argument vector. Called by user level routines.
+ * Returns -2 if -- is found (can be long option or end of options marker).
+ */
+static int
+getopt_internal(int nargc,
+ char * const *nargv,
+ const char *options)
+{
+ char *oli; /* option letter list index */
+ int optchar;
+
+ _DIAGASSERT(nargv != NULL);
+ _DIAGASSERT(options != NULL);
+
+ optarg = NULL;
+
+ /*
+ * XXX Some programs (like rsyncd) expect to be able to
+ * XXX re-initialize optind to 0 and have getopt_long(3)
+ * XXX properly function again. Work around this braindamage.
+ */
+ if (optind == 0)
+ optind = 1;
+
+ if (optreset)
+ nonopt_start = nonopt_end = -1;
+start:
+ if (optreset || !*place) { /* update scanning pointer */
+ optreset = 0;
+ if (optind >= nargc) { /* end of argument vector */
+ place = EMSG;
+ if (nonopt_end != -1) {
+ /* do permutation, if we have to */
+ permute_args(nonopt_start, nonopt_end,
+ optind, nargv);
+ optind -= nonopt_end - nonopt_start;
+ }
+ else if (nonopt_start != -1) {
+ /*
+ * If we skipped non-options, set optind
+ * to the first of them.
+ */
+ optind = nonopt_start;
+ }
+ nonopt_start = nonopt_end = -1;
+ return -1;
+ }
+ if ((*(place = nargv[optind]) != '-')
+ || (place[1] == '\0')) { /* found non-option */
+ place = EMSG;
+ if (IN_ORDER) {
+ /*
+ * GNU extension:
+ * return non-option as argument to option 1
+ */
+ optarg = nargv[optind++];
+ return INORDER;
+ }
+ if (!PERMUTE) {
+ /*
+ * if no permutation wanted, stop parsing
+ * at first non-option
+ */
+ return -1;
+ }
+ /* do permutation */
+ if (nonopt_start == -1)
+ nonopt_start = optind;
+ else if (nonopt_end != -1) {
+ permute_args(nonopt_start, nonopt_end,
+ optind, nargv);
+ nonopt_start = optind -
+ (nonopt_end - nonopt_start);
+ nonopt_end = -1;
+ }
+ optind++;
+ /* process next argument */
+ goto start;
+ }
+ if (nonopt_start != -1 && nonopt_end == -1)
+ nonopt_end = optind;
+ if (place[1] && *++place == '-') { /* found "--" */
+ place++;
+ return -2;
+ }
+ }
+ if ((optchar = (int)*place++) == (int)':' ||
+ (oli = (char*)strchr(options + (IGNORE_FIRST ? 1 : 0), optchar)) == NULL) {
+ /* option letter unknown or ':' */
+ if (!*place)
+ ++optind;
+#ifndef PLATFORM_WINDOWS
+ if (PRINT_ERROR)
+ warnx(illoptchar, optchar);
+#else
+ warnx(PRINT_ERROR, illoptchar, optchar);
+#endif
+ optopt = optchar;
+ return BADCH;
+ }
+ if (optchar == 'W' && oli[1] == ';') { /* -W long-option */
+ /* XXX: what if no long options provided (called by getopt)? */
+ if (*place)
+ return -2;
+
+ if (++optind >= nargc) { /* no arg */
+ place = EMSG;
+#ifndef PLATFORM_WINDOWS
+ if (PRINT_ERROR)
+ warnx(recargchar, optchar);
+#else
+ warnx(PRINT_ERROR, recargchar, optchar);
+#endif
+ optopt = optchar;
+ return BADARG;
+ } else /* white space */
+ place = nargv[optind];
+ /*
+ * Handle -W arg the same as --arg (which causes getopt to
+ * stop parsing).
+ */
+ return -2;
+ }
+ if (*++oli != ':') { /* doesn't take argument */
+ if (!*place)
+ ++optind;
+ } else { /* takes (optional) argument */
+ optarg = NULL;
+ if (*place) /* no white space */
+ optarg = place;
+ /* XXX: disable test for :: if PC? (GNU doesn't) */
+ else if (oli[1] != ':') { /* arg not optional */
+ if (++optind >= nargc) { /* no arg */
+ place = EMSG;
+#ifndef PLATFORM_WINDOWS
+ if (PRINT_ERROR)
+ warnx(recargchar, optchar);
+#else
+ warnx(PRINT_ERROR, recargchar, optchar);
+#endif
+ optopt = optchar;
+ return BADARG;
+ } else
+ optarg = nargv[optind];
+ }
+ place = EMSG;
+ ++optind;
+ }
+ /* dump back option letter */
+ return optchar;
+}
+
+__BEGIN_DECLS // Added by JE - 31-01-2010
+#ifdef REPLACE_GETOPT
+/*
+ * getopt --
+ * Parse argc/argv argument vector.
+ *
+ * [eventually this will replace the real getopt]
+ */
+GETOPT_API int // 'GETOPT_API' declaration added by JE - 31-01-2010
+getopt(int nargc,
+ char * const *nargv,
+ const char *options)
+{
+ int retval;
+
+ _DIAGASSERT(nargv != NULL);
+ _DIAGASSERT(options != NULL);
+
+ if ((retval = getopt_internal(nargc, nargv, options)) == -2) {
+ ++optind;
+ /*
+ * We found an option (--), so if we skipped non-options,
+ * we have to permute.
+ */
+ if (nonopt_end != -1) {
+ permute_args(nonopt_start, nonopt_end, optind,
+ nargv);
+ optind -= nonopt_end - nonopt_start;
+ }
+ nonopt_start = nonopt_end = -1;
+ retval = -1;
+ }
+ return retval;
+}
+#endif
+
+/*
+ * getopt_long --
+ * Parse argc/argv argument vector.
+ */
+GETOPT_API int // 'GETOPT_API' declaration added by JE - 31-01-2010
+getopt_long(int nargc,
+ char * const *nargv,
+ const char *options,
+ const struct option *long_options,
+ int *idx)
+{
+ int retval;
+
+ _DIAGASSERT(nargv != NULL);
+ _DIAGASSERT(options != NULL);
+ _DIAGASSERT(long_options != NULL);
+ /* idx may be NULL */
+
+ if ((retval = getopt_internal(nargc, nargv, options)) == -2) {
+ char *current_argv, *has_equal;
+ size_t current_argv_len;
+ int i, match;
+
+ current_argv = place;
+ match = -1;
+
+ optind++;
+ place = EMSG;
+
+ if (*current_argv == '\0') { /* found "--" */
+ /*
+ * We found an option (--), so if we skipped
+ * non-options, we have to permute.
+ */
+ if (nonopt_end != -1) {
+ permute_args(nonopt_start, nonopt_end,
+ optind, nargv);
+ optind -= nonopt_end - nonopt_start;
+ }
+ nonopt_start = nonopt_end = -1;
+ return -1;
+ }
+ if ((has_equal = strchr(current_argv, '=')) != NULL) {
+ /* argument found (--option=arg) */
+ current_argv_len = has_equal - current_argv;
+ has_equal++;
+ } else
+ current_argv_len = strlen(current_argv);
+
+ for (i = 0; long_options[i].name; i++) {
+ /* find matching long option */
+ if (strncmp(current_argv, long_options[i].name,
+ current_argv_len))
+ continue;
+
+ if (strlen(long_options[i].name) ==
+ (unsigned)current_argv_len) {
+ /* exact match */
+ match = i;
+ break;
+ }
+ if (match == -1) /* partial match */
+ match = i;
+ else {
+ /* ambiguous abbreviation */
+#ifndef PLATFORM_WINDOWS
+ if (PRINT_ERROR)
+ warnx(ambig, (int)current_argv_len,
+ current_argv);
+#else
+ warnx(PRINT_ERROR, ambig, (int)current_argv_len,
+ current_argv);
+#endif
+ optopt = 0;
+ return BADCH;
+ }
+ }
+ if (match != -1) { /* option found */
+ if (long_options[match].has_arg == no_argument
+ && has_equal) {
+#ifndef PLATFORM_WINDOWS
+ if (PRINT_ERROR)
+ warnx(noarg, (int)current_argv_len,
+ current_argv);
+#else
+ warnx(PRINT_ERROR, noarg, (int)current_argv_len,
+ current_argv);
+#endif
+ /*
+ * XXX: GNU sets optopt to val regardless of
+ * flag
+ */
+ if (long_options[match].flag == NULL)
+ optopt = long_options[match].val;
+ else
+ optopt = 0;
+ return BADARG;
+ }
+ if (long_options[match].has_arg == required_argument ||
+ long_options[match].has_arg == optional_argument) {
+ if (has_equal)
+ optarg = has_equal;
+ else if (long_options[match].has_arg ==
+ required_argument) {
+ /*
+ * optional argument doesn't use
+ * next nargv
+ */
+ optarg = nargv[optind++];
+ }
+ }
+ if ((long_options[match].has_arg == required_argument)
+ && (optarg == NULL)) {
+ /*
+ * Missing argument; leading ':'
+ * indicates no error should be generated
+ */
+#ifndef PLATFORM_WINDOWS
+ if (PRINT_ERROR)
+ warnx(recargstring, current_argv);
+#else
+ warnx(PRINT_ERROR, recargstring, current_argv);
+#endif
+ /*
+ * XXX: GNU sets optopt to val regardless
+ * of flag
+ */
+ if (long_options[match].flag == NULL)
+ optopt = long_options[match].val;
+ else
+ optopt = 0;
+ --optind;
+ return BADARG;
+ }
+ } else { /* unknown option */
+#ifndef PLATFORM_WINDOWS
+ if (PRINT_ERROR)
+ warnx(illoptstring, current_argv);
+#else
+ warnx(PRINT_ERROR, illoptstring, current_argv);
+#endif
+ optopt = 0;
+ return BADCH;
+ }
+ if (long_options[match].flag) {
+ *long_options[match].flag = long_options[match].val;
+ retval = 0;
+ } else
+ retval = long_options[match].val;
+ if (idx)
+ *idx = match;
+ }
+ return retval;
+}
+__END_DECLS // Added by JE - 31-01-2010
+
+#endif /* !GETOPT_LONG */
diff --git a/libs/pbd/msvc/mountpoint.cc b/libs/pbd/msvc/mountpoint.cc
new file mode 100644
index 0000000000..d30b24462f
--- /dev/null
+++ b/libs/pbd/msvc/mountpoint.cc
@@ -0,0 +1,166 @@
+/*
+ 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.
+
+ $Id: mountpoint.cc 3920 2008-10-11 12:34:46Z paul $
+*/
+
+#ifdef COMPILER_MSVC
+
+/* TODO - Still to be implemented */
+
+#include <cstdio>
+#include <cstring>
+#include <string>
+#include <cstring>
+#include <limits.h>
+
+#include <pbd/mountpoint.h>
+
+using std::string;
+
+#if HAVE_GETMNTENT
+#include <mntent.h>
+
+struct mntent_sorter {
+ bool operator() (const mntent *a, const mntent *b) {
+ return strcmp (a->mnt_dir, b->mnt_dir);
+ }
+};
+
+string
+mountpoint (string path)
+{
+ FILE *mntf;
+ mntent *mnt;
+ unsigned int maxmatch = 0;
+ unsigned int matchlen;
+ const char *cpath = path.c_str();
+ char best[PATH_MAX+1];
+
+ if ((mntf = setmntent ("/etc/mtab", "r")) == 0) {
+ return "";
+ }
+
+ best[0] = '\0';
+
+ while ((mnt = getmntent (mntf))) {
+ unsigned int n;
+
+ n = 0;
+ matchlen = 0;
+
+ /* note: strcmp's semantics are not
+ strict enough to use for this.
+ */
+
+ while (cpath[n] && mnt->mnt_dir[n]) {
+ if (cpath[n] != mnt->mnt_dir[n]) {
+ break;
+ }
+ matchlen++;
+ n++;
+ }
+
+ if (cpath[matchlen] == '\0') {
+
+ endmntent (mntf);
+ return mnt->mnt_dir;
+
+ } else {
+
+ if (matchlen > maxmatch) {
+ snprintf (best, sizeof(best), "%s", mnt->mnt_dir);
+ maxmatch = matchlen;
+ }
+ }
+ }
+
+ endmntent (mntf);
+
+ return best;
+}
+
+#else // !HAVE_GETMNTENT
+
+string
+mountpoint (string path)
+{
+return "";
+
+/* // The rest is commented out temporarily by JE - 30-11-2009
+ // (I think this must be the implementation for MacOS).
+ struct statfs *mntbufp = 0;
+ int count;
+ unsigned int maxmatch = 0;
+ unsigned int matchlen;
+ const char *cpath = path.c_str();
+ char best[PATH_MAX+1];
+
+ if ((count = getmntinfo(&mntbufp, MNT_NOWAIT)) == 0) {
+ free(mntbufp);
+ return "\0";
+ }
+
+ best[0] = '\0';
+
+ for (int i = 0; i < count; ++i) {
+ unsigned int n = 0;
+ matchlen = 0;
+
+ // note: strcmp's semantics are not
+ // strict enough to use for this.
+
+ while (cpath[n] && mntbufp[i].f_mntonname[n]) {
+ if (cpath[n] != mntbufp[i].f_mntonname[n]) {
+ break;
+ }
+ matchlen++;
+ n++;
+ }
+
+ if (cpath[matchlen] == '\0') {
+ snprintf(best, sizeof(best), "%s", mntbufp[i].f_mntonname);
+ free(mntbufp);
+ return best;
+
+ } else {
+
+ if (matchlen > maxmatch) {
+ snprintf (best, sizeof(best), "%s", mntbufp[i].f_mntonname);
+ maxmatch = matchlen;
+ }
+ }
+ }
+
+ return best;
+*/
+}
+#endif // HAVE_GETMNTENT
+
+#ifdef TEST_MOUNTPOINT
+
+main (int argc, char *argv[])
+{
+ printf ("mp of %s = %s\n", argv[1], mountpoint (argv[1]).c_str());
+ exit (0);
+}
+
+#endif // TEST_MOUNTPOINT
+
+#else // !COMPILER_MSVC
+ const char* pbd_mountpoint = "original pbd/mountpoint.cc takes precedence over this file";
+#endif // COMPILER_MSVC
diff --git a/libs/pbd/msvc/msvc_pbd.cc b/libs/pbd/msvc/msvc_pbd.cc
new file mode 100644
index 0000000000..5b9c9d449a
--- /dev/null
+++ b/libs/pbd/msvc/msvc_pbd.cc
@@ -0,0 +1,914 @@
+/*
+ Copyright (C) 2009 John Emmas
+
+ 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.
+
+*/
+
+#ifdef COMPILER_MSVC
+
+#include <WTypes.h>
+
+extern "C" WINBASEAPI BOOL WINAPI
+CreateHardLinkA( LPCSTR lpFileName,
+ LPCSTR lpExistingFileName,
+ LPSECURITY_ATTRIBUTES lpSecurityAttributes ); // Needs kernel32.lib on anything higher than Win2K
+
+#include <algorithm>
+#include <string>
+#include <io.h>
+#include <math.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <pbd/error.h>
+#include <ardourext/misc.h>
+#include <ardourext/pthread.h> // Should ensure that we include the right
+ // version - but we'll check anyway, later
+
+#include <glibmm.h>
+
+#define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
+
+struct timezone
+{
+ int tz_minuteswest; /* minutes W of Greenwich */
+ int tz_dsttime; /* type of dst correction */
+};
+
+LIBPBD_API int PBD_APICALLTYPE
+gettimeofday(struct timeval *__restrict tv, __timezone_ptr_t tz) // Does this need to be exported ?
+{
+FILETIME ft;
+unsigned __int64 tmpres = 0;
+static int tzflag = 0;
+
+ if (NULL != tv)
+ {
+ GetSystemTimeAsFileTime(&ft);
+
+ tmpres |= ft.dwHighDateTime;
+ tmpres <<= 32;
+ tmpres |= ft.dwLowDateTime;
+
+ /*converting file time to unix epoch*/
+ tmpres /= 10; /*convert into microseconds*/
+ tmpres -= DELTA_EPOCH_IN_MICROSECS;
+ tv->tv_sec = (long)(tmpres / 1000000UL);
+ tv->tv_usec = (long)(tmpres % 1000000UL);
+ }
+
+ if (NULL != tz)
+ {
+ struct timezone *ptz = static_cast<struct timezone*> (tz);
+ if (!tzflag)
+ {
+ _tzset();
+ tzflag++;
+ }
+ if (ptz)
+ {
+ ptz->tz_minuteswest = _timezone / 60;
+ ptz->tz_dsttime = _daylight;
+ }
+ }
+
+ return 0;
+}
+
+// Define the default comparison operators for Windows (ptw32) 'pthread_t' (not used
+// by Ardour AFAIK but would be needed if an array of 'pthread_t' had to be sorted).
+#ifndef PTHREAD_H // Defined by PTW32 (Linux and other versions define _PTHREAD_H)
+#error "An incompatible version of 'pthread.h' is #included. Use only the Windows (ptw32) version!"
+#else
+LIBPBD_API bool operator> (const pthread_t& lhs, const pthread_t& rhs)
+{
+ return (std::greater<void*>()(lhs.p, rhs.p));
+}
+
+LIBPBD_API bool operator< (const pthread_t& lhs, const pthread_t& rhs)
+{
+ return (std::less<void*>()(lhs.p, rhs.p));
+}
+
+LIBPBD_API bool operator!= (const pthread_t& lhs, const pthread_t& rhs)
+{
+ return (std::not_equal_to<void*>()(lhs.p, rhs.p));
+}
+
+LIBPBD_API bool operator== (const pthread_t& lhs, const pthread_t& rhs)
+{
+ return (!(lhs != rhs));
+}
+#endif
+
+// Functions supplied (later) to std::transform
+//***************************************************************
+//
+// invert_backslash()
+//
+// Examines a supplied ASCII character and (if the character is
+// a backslash) converts it to a forward slash,
+//
+// Returns:
+//
+// The supplied character (converted, if it was a backslash)
+//
+char invert_backslash(char character)
+{
+ if ('\\' == character)
+ character = '/';
+
+ return (character);
+}
+
+//***************************************************************
+//
+// invert_forwardslash()
+//
+// Examines a supplied ASCII character and (if the character is
+// a forward slash) converts it to a backslash,
+//
+// Returns:
+//
+// The supplied character (converted, if it was a fwd slash)
+//
+char invert_forwardslash(char character)
+{
+ if ('/' == character)
+ character = '\\';
+
+ return (character);
+}
+
+
+//***************************************************************
+//
+// pread()
+//
+// Emulates pread() using _lseek()/_read()/_lseek().
+//
+// Returns:
+//
+// On Success: The number of bytes read from the file
+// On Failure: -1
+//
+LIBPBD_API ssize_t PBD_APICALLTYPE
+pread(int handle, void *buf, size_t nbytes, off_t offset)
+{
+int old_errno;
+ssize_t ret;
+
+ off_t old_offset = _tell(handle);
+
+ if (0 > old_offset)
+ ret = (-1);
+ else
+ {
+ _lseek(handle, offset, SEEK_SET);
+ ret = _read(handle, buf, nbytes);
+
+ old_errno = errno;
+ _lseek(handle, old_offset, SEEK_SET);
+ errno = old_errno;
+ }
+
+ return (ret);
+}
+
+
+//***************************************************************
+//
+// pwrite()
+//
+// Emulates pwrite() using _lseek()/_write()/_lseek().
+//
+// Returns:
+//
+// On Success: The number of bytes written to the file
+// On Failure: -1
+//
+LIBPBD_API ssize_t PBD_APICALLTYPE
+pwrite(int handle, const void *buf, size_t nbytes, off_t offset)
+{
+int old_errno;
+ssize_t ret;
+
+ off_t old_offset = _lseek(handle, offset, SEEK_SET);
+
+ if (0 > old_offset)
+ ret = (-1);
+ else
+ {
+ ret = _write(handle, buf, nbytes);
+
+ old_errno = errno;
+ _lseek(handle, old_offset, SEEK_SET);
+ errno = old_errno;
+ }
+
+ return (ret);
+}
+
+//***************************************************************
+//
+// round()
+//
+// Emulates round() using floor().
+//
+// Returns:
+//
+// On Success: The largest integer that is less than or
+// equal to 'x'.
+// On Failure: None
+//
+LIBPBD_API double PBD_APICALLTYPE
+round(double x)
+{
+ return (floor(x));
+}
+
+namespace PBD {
+
+//***************************************************************
+//
+// TestForMinimumSpecOS()
+//
+// Tests the user's OS to see if it is Win2K or later (could be
+// expanded quite easily to accommodate other OS's)
+//
+// Returns:
+//
+// On Success: TRUE (if the user's OS matches the minimum spec)
+// On Failure: FALSE otherwise
+//
+LIBPBD_API bool PBD_APICALLTYPE
+TestForMinimumSpecOS(char *revision /* currently ignored */)
+{
+bool bRet = true;
+#ifdef PLATFORM_WINDOWS
+ bRet = false;
+ HINSTANCE hKernelDll = (HINSTANCE)dlopen("kernel32.dll", RTLD_NOW);
+
+ if (hKernelDll)
+ {
+ // 'CreateHardLink()' is only available from Win2K onwards.
+ if (NULL != dlsym(hKernelDll, "CreateHardLinkA"))
+ bRet = true;
+
+ dlclose(hKernelDll);
+ }
+#endif
+ // Other OS's could be accommodated here
+
+ return (bRet);
+}
+
+
+//***************************************************************
+//
+// realpath()
+//
+// Emulates POSIX realpath() using Win32 _fullpath().
+//
+// Returns:
+//
+// On Success: A pointer to the resolved (absolute) path
+// On Failure: NULL
+//
+LIBPBD_API char* PBD_APICALLTYPE
+realpath (const char *original_path, char resolved_path[_MAX_PATH+1])
+{
+char *pRet = NULL;
+bool bIsSymLink = 0; // We'll probably need to test the incoming path
+ // to find out if it points to a Windows shortcut
+ // (or a hard link) and set this appropriately.
+ if (bIsSymLink)
+ {
+ // At the moment I'm not sure if Windows '_fullpath()' is directly
+ // equivalent to POSIX 'realpath()' - in as much as the latter will
+ // resolve the supplied path if it happens to point to a symbolic
+ // link ('_fullpath()' probably DOESN'T do this but I'm not really
+ // sure if Ardour needs such functionality anyway). Therefore we'll
+ // possibly need to add that functionality here at a later date.
+ }
+ else
+ {
+ char temp[(MAX_PATH+1)*6]; // Allow for maximum length of a path in UTF8 characters
+
+ // POSIX 'realpath()' requires that the buffer size is at
+ // least PATH_MAX+1, so assume that the user knew this !!
+ pRet = _fullpath(temp, Glib::locale_from_utf8(original_path).c_str(), _MAX_PATH);
+ if (NULL != pRet)
+ strcpy(resolved_path, Glib::locale_to_utf8(temp).c_str());
+ }
+
+ return (pRet);
+}
+
+
+//***************************************************************
+//
+// opendir()
+//
+// Creates a pointer to a DIR structure, appropriately filled in
+// and ready to begin a directory search iteration.
+//
+// Returns:
+//
+// On Success: Pointer to a (heap based) DIR structure
+// On Failure: NULL
+//
+LIBPBD_API DIR* PBD_APICALLTYPE
+opendir (const char *szPath)
+{
+wchar_t wpath[PATH_MAX+1];
+unsigned int rc;
+DIR *pDir = 0;
+
+ errno = 0;
+
+ if (!szPath)
+ errno = EFAULT;
+
+ if ((!errno) && ('\0' == szPath[0]))
+ errno = ENOTDIR;
+
+ // Determine if the given path really is a directory
+
+ if (!errno)
+ if (0 == MultiByteToWideChar (CP_UTF8, 0, (LPCSTR)szPath, -1, (LPWSTR)wpath, sizeof(wpath)))
+ errno = EFAULT;
+
+ if ((!errno) && ((rc = GetFileAttributesW(wpath)) == -1))
+ errno = ENOENT;
+
+ if ((!errno) && (!(rc & FILE_ATTRIBUTE_DIRECTORY)))
+ // Error. Entry exists but not a directory. */
+ errno = ENOTDIR;
+
+ if (!errno)
+ {
+ // Allocate enough memory to store DIR structure, plus
+ // the complete directory path originally supplied.
+ pDir = (DIR *)malloc(sizeof(DIR) + strlen(szPath) + strlen("\\") + strlen ("*"));
+
+ if (!pDir)
+ {
+ // Error - out of memory
+ errno = ENOMEM;
+ }
+ }
+
+ if (!errno)
+ {
+ // Create the search expression
+ strcpy(pDir->dd_name, szPath);
+
+ // Add a backslash if the path doesn't already end with one
+ if (pDir->dd_name[0] != '\0' &&
+ pDir->dd_name[strlen(pDir->dd_name) - 1] != '/' &&
+ pDir->dd_name[strlen(pDir->dd_name) - 1] != '\\')
+ {
+ strcat (pDir->dd_name, "\\");
+ }
+
+ // Add the search pattern
+ strcat(pDir->dd_name, "*");
+
+ // Initialize handle to -1 so that a premature closedir()
+ // doesn't try to call _findclose() on it.
+ pDir->dd_handle = (-1);
+
+ // Initialize the status
+ pDir->dd_stat = 0;
+
+ // Initialize the dirent structure. 'ino' and 'reclen' are invalid under Win32
+ // and 'name' simply points at the appropriate part of the findfirst_t struct.
+ pDir->dd_dir.d_ino = 0;
+ pDir->dd_dir.d_reclen = 0;
+ pDir->dd_dir.d_namlen = 0;
+ strcpy(pDir->dd_dir.d_name, pDir->dd_dta.name);
+
+ return (pDir); // Succeeded
+ }
+
+ if (pDir)
+ free (pDir);
+ return (DIR *) 0; // Failed
+}
+
+
+//***************************************************************
+//
+// readdir()
+//
+// Return a pointer to a dirent struct, filled with information
+// about the next entry in the directory.
+//
+// Returns:
+//
+// On Success: A pointer to the supplied DIR's 'dirent' struct
+// On Failure: NULL
+//
+LIBPBD_API struct dirent* PBD_APICALLTYPE
+readdir (DIR* pDir)
+{
+int old_errno = 0;
+errno = 0;
+
+ // Check for valid DIR struct
+ if (!pDir)
+ errno = EFAULT;
+
+ if ((strcmp(pDir->dd_dir.d_name, pDir->dd_dta.name)) && (!errno))
+ // The structure does not seem to be set up correctly
+ errno = EINVAL;
+ else
+ {
+ if (pDir->dd_stat < 0)
+ {
+ // We have already returned all files in this directory
+ // (or the structure has an invalid dd_stat).
+ return (struct dirent *)0;
+ }
+ else if (pDir->dd_stat == 0)
+ {
+ // We haven't started the search yet.
+ // Start the search
+ pDir->dd_handle = _findfirst (Glib::locale_from_utf8(pDir->dd_name).c_str(), &(pDir->dd_dta));
+
+ if (pDir->dd_handle == -1)
+ // The directory is empty
+ pDir->dd_stat = -1;
+ else
+ pDir->dd_stat = 1;
+ }
+ else
+ {
+ // Do not return ENOENT on last file in directory
+ old_errno = errno;
+
+ // Get the next search entry
+ if (_findnext (pDir->dd_handle, &(pDir->dd_dta)))
+ {
+ // We are off the end or otherwise error
+ errno = old_errno;
+ _findclose (pDir->dd_handle);
+ pDir->dd_handle = -1;
+ pDir->dd_stat = -1;
+ }
+ else
+ // Update to indicate the correct status number
+ pDir->dd_stat++;
+ }
+
+ if (pDir->dd_stat > 0)
+ {
+ // We successfully got an entry. Details about the file are
+ // already appropriately filled in except for the length of
+ // file name.
+ strcpy(pDir->dd_dir.d_name, pDir->dd_dta.name);
+ pDir->dd_dir.d_namlen = strlen (pDir->dd_dir.d_name);
+ return (&pDir->dd_dir); // Succeeded
+ }
+ }
+
+ return (struct dirent *) 0; // Failed
+}
+
+
+//***************************************************************
+//
+// closedir()
+//
+// Frees the resources allocated by opendir().
+//
+// Returns:
+//
+// On Success: 0
+// On Failure: -1
+//
+LIBPBD_API int PBD_APICALLTYPE
+closedir (DIR *pDir)
+{
+int rc = 0;
+
+ errno = 0;
+
+ if (!pDir)
+ errno = EFAULT;
+ else
+ {
+ if ((-1) != pDir->dd_handle)
+ rc = _findclose (pDir->dd_handle);
+
+ // Free the DIR structure
+ free (pDir);
+
+ return rc; // Succeeded
+ }
+
+ return (-1); // Failed
+}
+
+//***************************************************************
+//
+// mkstemp()
+//
+// Emulates Linux mkstemp() using Win32 _mktemp() and _open() etc.
+//
+// Returns:
+//
+// On Success: A file descriptor for the opened file.
+// On Failure: (-1)
+//
+LIBPBD_API int PBD_APICALLTYPE
+mkstemp (char *template_name)
+{
+int ret = (-1);
+char *szFileName;
+char szTempPath[PATH_MAX+100]; // Just ensure we have plenty of buffer space
+
+ if (NULL != (szFileName = _mktemp(template_name)))
+ {
+ if (0 != ::GetTempPathA(sizeof(szTempPath), szTempPath))
+ {
+ strcat(szTempPath, szFileName);
+ ret = _open(szTempPath, (_O_CREAT|_O_BINARY|_O_TEMPORARY|_O_RDWR|_O_TRUNC), _S_IWRITE);
+ }
+ }
+
+ return (ret);
+}
+
+
+//***************************************************************
+//
+// ntfs_link()
+//
+// Emulates Linux link() using Win32 CreateHardLink()(NTFS only).
+//
+// Returns:
+//
+// On Success: Non-zero.
+// On Failure: Zero (call 'GetLastError()' to retrieve info)
+//
+LIBPBD_API int PBD_APICALLTYPE
+ntfs_link (const char *existing_filepath, const char *link_filepath)
+{
+int ret = 1; // 'ERROR_INVALID_FUNCTION'
+bool bValidPath = false;
+
+ // Make sure we've been sent a valid input string
+ if (existing_filepath && link_filepath)
+ {
+ std::string strRoot = existing_filepath;
+
+ if ((1 < strRoot.length()) && ('\\' == existing_filepath[0]) && ('\\' == existing_filepath[1]))
+ {
+ int slashcnt = 0;
+
+ // We've been sent a network path. Convert backslashes to forward slashes temporarily.
+ std::transform(strRoot.begin(), strRoot.end(), strRoot.begin(), invert_backslash);
+
+ // Now, if there are less than four slashes, add a fourth one or abort
+ std::string::iterator iter = strRoot.begin();
+ while ((slashcnt < 4) && (iter != strRoot.end()))
+ {
+ if ('/' == (*iter))
+ slashcnt++;
+
+ ++iter;
+ }
+
+ if (slashcnt > 2)
+ {
+ // If only 3 slashes were counted, add a trailing slash
+ if (slashcnt == 3)
+ strRoot += '/';
+
+ // Now find the position of the fourth slash
+ iter = strRoot.begin();
+ int charcnt = 0;
+ for (slashcnt=0; slashcnt<4;)
+ {
+ charcnt++;
+
+ if ('/' == (*iter))
+ slashcnt++;
+
+ if (++iter == strRoot.end())
+ break;
+ }
+
+ strRoot.resize(charcnt);
+ bValidPath = true;
+ }
+ }
+ else
+ {
+ // Assume a standard Windows style path
+ if (1 < strRoot.length() && (':' == existing_filepath[1]))
+ {
+ // Convert backslashes to forward slashes temporarily.
+ std::transform(strRoot.begin(), strRoot.end(), strRoot.begin(), invert_backslash);
+
+ if (2 == strRoot.length())
+ strRoot += '/';
+
+ if ('/' == strRoot[2])
+ {
+ strRoot.resize(3);
+ bValidPath = true;
+ }
+ }
+ }
+
+ if (bValidPath)
+ {
+ char szFileSystemType[_MAX_PATH+1];
+
+ // Restore the original backslashes
+ std::transform(strRoot.begin(), strRoot.end(), strRoot.begin(), invert_forwardslash);
+
+ // Windows only supports hard links for the NTFS filing
+ // system, so let's make sure that's what we're using!!
+ if (::GetVolumeInformationA(strRoot.c_str(), NULL, 0, NULL, NULL, NULL, szFileSystemType, _MAX_PATH+1))
+ {
+ std::string strRootFileSystemType = szFileSystemType;
+ std::transform(strRootFileSystemType.begin(), strRootFileSystemType.end(), strRootFileSystemType.begin(), ::toupper);
+#if (_WIN32_WINNT >= 0x0500)
+ if (0 == strRootFileSystemType.compare("NTFS"))
+ {
+ if (TestForMinimumSpecOS()) // Hard links were only available from Win2K onwards
+ if (0 == CreateHardLinkA(link_filepath, existing_filepath, NULL))
+ { // Note that the above API call cannot create a link to a directory, so
+ // should we also be checking that the supplied path was actually a file?
+ ret = GetLastError();
+ }
+ else
+ SetLastError(ret = 0); // 'NO_ERROR'
+ }
+ else
+ {
+ ret = 4300; // 'ERROR_INVALID_MEDIA'
+ }
+#endif
+ }
+ }
+ else
+ ret = 123; // 'ERROR_INVALID_NAME'
+ }
+ else
+ ret = 161; // 'ERROR_BAD_PATHNAME'
+
+ if (ret)
+ {
+ SetLastError(ret);
+ return (-1);
+ }
+ else
+ return (0);
+}
+
+
+//***************************************************************
+//
+// ntfs_unlink()
+//
+// Emulates Linux unlink() using Win32 DeleteFile()(NTFS only).
+//
+// Returns:
+//
+// On Success: Non-zero.
+// On Failure: Zero (call 'GetLastError()' to retrieve info)
+//
+LIBPBD_API int PBD_APICALLTYPE
+ntfs_unlink (const char *link_filepath)
+{
+int ret = 1; // 'ERROR_INVALID_FUNCTION'
+bool bValidPath = false;
+
+ // Make sure we've been sent a valid input string
+ if (link_filepath)
+ {
+ std::string strRoot = link_filepath;
+
+ if ((1 < strRoot.length()) && ('\\' == link_filepath[0]) && ('\\' == link_filepath[1]))
+ {
+ int slashcnt = 0;
+
+ // We've been sent a network path. Convert backslashes to forward slashes temporarily.
+ std::transform(strRoot.begin(), strRoot.end(), strRoot.begin(), invert_backslash);
+
+ // Now, if there are less than four slashes, add a fourth one or abort
+ std::string::iterator iter = strRoot.begin();
+ while ((slashcnt < 4) && (iter != strRoot.end()))
+ {
+ if ('/' == (*iter))
+ slashcnt++;
+
+ ++iter;
+ }
+
+ if (slashcnt > 2)
+ {
+ // If only 3 slashes were counted, add a trailing slash
+ if (slashcnt == 3)
+ strRoot += '/';
+
+ // Now find the position of the fourth slash
+ iter = strRoot.begin();
+ int charcnt = 0;
+ for (slashcnt=0; slashcnt<4;)
+ {
+ charcnt++;
+
+ if ('/' == (*iter))
+ slashcnt++;
+
+ if (++iter == strRoot.end())
+ break;
+ }
+
+ strRoot.resize(charcnt);
+ bValidPath = true;
+ }
+ }
+ else
+ {
+ // Assume a standard Windows style path
+ if (1 < strRoot.length() && (':' == link_filepath[1]))
+ {
+ // Convert backslashes to forward slashes temporarily.
+ std::transform(strRoot.begin(), strRoot.end(), strRoot.begin(), invert_backslash);
+
+ if (2 == strRoot.length())
+ strRoot += '/';
+
+ if ('/' == strRoot[2])
+ {
+ strRoot.resize(3);
+ bValidPath = true;
+ }
+ }
+ }
+
+ if (bValidPath)
+ {
+ char szFileSystemType[_MAX_PATH+1];
+
+ // Restore the original backslashes
+ std::transform(strRoot.begin(), strRoot.end(), strRoot.begin(), invert_forwardslash);
+
+ // Windows only supports hard links for the NTFS filing
+ // system, so let's make sure that's what we're using!!
+ if (::GetVolumeInformationA(strRoot.c_str(), NULL, 0, NULL, NULL, NULL, szFileSystemType, _MAX_PATH+1))
+ {
+ std::string strRootFileSystemType = szFileSystemType;
+ std::transform(strRootFileSystemType.begin(), strRootFileSystemType.end(), strRootFileSystemType.begin(), ::toupper);
+#if (_WIN32_WINNT >= 0x0500)
+ if (0 == strRootFileSystemType.compare("NTFS"))
+ if (TestForMinimumSpecOS()) // Hard links were only available from Win2K onwards
+ if (0 == DeleteFileA(link_filepath))
+ ret = GetLastError();
+ else
+ ret = 0; // 'NO_ERROR'
+#endif
+ }
+ }
+ else
+ ret = 123; // 'ERROR_INVALID_NAME'
+ }
+ else
+ ret = 161; // 'ERROR_BAD_PATHNAME'
+
+ if (ret)
+ {
+ SetLastError(ret);
+ return (-1);
+ }
+ else
+ return (0);
+}
+
+} // namespace PBD
+
+
+//***************************************************************
+//
+// dlopen()
+//
+// Emulates POSIX dlopen() using Win32 LoadLibrary().
+//
+// Returns:
+//
+// On Success: A handle to the opened DLL
+// On Failure: NULL
+//
+LIBPBD_API void* PBD_APICALLTYPE
+dlopen (const char *file_name, int mode)
+{
+ // Note that 'mode' is ignored in Win32
+ return(::LoadLibraryA(Glib::locale_from_utf8(file_name).c_str()));
+}
+
+
+//***************************************************************
+//
+// dlclose()
+//
+// Emulates POSIX dlclose() using Win32 FreeLibrary().
+//
+// Returns:
+//
+// On Success: A non-zero number
+// On Failure: 0
+//
+LIBPBD_API int PBD_APICALLTYPE
+dlclose (void *handle)
+{
+ return (::FreeLibrary((HMODULE)handle));
+}
+
+
+//***************************************************************
+//
+// dlsym()
+//
+// Emulates POSIX dlsym() using Win32 GetProcAddress().
+//
+// Returns:
+//
+// On Success: A pointer to the found function or symbol
+// On Failure: NULL
+//
+LIBPBD_API void* PBD_APICALLTYPE
+dlsym (void *handle, const char *symbol_name)
+{
+ // First test for RTLD_DEFAULT and RTLD_NEXT
+ if ((handle == 0/*RTLD_DEFAULT*/) || (handle == ((void *) -1L)/*RTLD_NEXT*/))
+ {
+ return 0; // Not yet supported for Win32
+ }
+ else
+ return (::GetProcAddress((HMODULE)handle, symbol_name));
+}
+
+#define LOCAL_ERROR_BUF_SIZE 1024
+static char szLastWinError[LOCAL_ERROR_BUF_SIZE];
+//***************************************************************
+//
+// dlerror()
+//
+// Emulates POSIX dlerror() using Win32 GetLastError().
+//
+// Returns:
+//
+// On Success: The translated message corresponding to the
+// last error
+// On Failure: NULL (if the last error was ERROR_SUCCESS)
+//
+LIBPBD_API char* PBD_APICALLTYPE
+dlerror ()
+{
+ DWORD dwLastErrorId = GetLastError();
+ if (ERROR_SUCCESS == dwLastErrorId)
+ return 0;
+ else
+ {
+ if (0 == FormatMessage(
+ FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ dwLastErrorId,
+ 0,
+ szLastWinError,
+ LOCAL_ERROR_BUF_SIZE,
+ 0))
+ {
+ sprintf(szLastWinError, "Could not decipher the previous error message");
+ }
+
+ // POSIX dlerror() seems to reset the
+ // error system, so emulate that here
+ SetLastError(ERROR_SUCCESS);
+ }
+
+ return(szLastWinError);
+}
+
+#endif // COMPILER_MSVC
diff --git a/libs/pbd/msvc/msvc_poll.cc b/libs/pbd/msvc/msvc_poll.cc
new file mode 100644
index 0000000000..921638a3f5
--- /dev/null
+++ b/libs/pbd/msvc/msvc_poll.cc
@@ -0,0 +1,215 @@
+/*
+ Copyright (C) 2009 John Emmas
+
+ 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.
+
+*/
+
+#ifdef COMPILER_MSVC
+
+//#include <glib/gtimer.h>
+#include "pbd/msvc_pbd.h"
+
+#ifndef _DWORD_DEFINED
+#define _DWORD_DEFINED
+typedef unsigned long DWORD;
+#endif // !_DWORD_DEFINED
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * *
+ * Note that this entire strategy failed to work, at least for pipes. It turned *
+ * out that Windows 'tell()' always returns 0 when used on a pipe. This strategy *
+ * is now deprecated, having been replaced by a new pipe-like object, which I've *
+ * called 'PBD::pipex'. This polling functionality is included here mostly so *
+ * that Ardour will build and launch under Windows. However, any module that *
+ * relies on polling a pipe will eventually need to use the new pipex object. *
+ * This code will allow it to compile and link successfully, although it won't *
+ * poll successfully at run time. Having said that, these functions might well *
+ * work for ports and/or other machanisms that get represented by a file handle. *
+ * *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+int poll_input (struct pollfd *fds, nfds_t nfds, int& elapsed_time, int timeout)
+{
+DWORD dwOldTickCount,
+ dwNewTickCount = GetTickCount();
+bool input = false,
+ error = false;
+int ret = 0;
+
+ if (NULL != fds)
+ {
+ nfds_t loop;
+ short ev_mask = (POLLOUT|POLLWRNORM|POLLWRBAND);
+
+ errno = NO_ERROR;
+
+ do
+ {
+ dwOldTickCount = dwNewTickCount;
+
+ for (loop=0; loop<nfds; loop++)
+ fds[loop].revents = 0;
+
+ for (loop=0; (loop<nfds && !error); loop++)
+ {
+ if (!(fds[loop].events & ev_mask))
+ {
+ long pos = _tell(fds[loop].fd);
+
+ if (0 > pos)
+ {
+ // An error occured ('errno' should have been set by '_tell()')
+ ret = (-1);
+ fds[loop].revents = POLLERR;
+ if (fds[loop].events & POLLRDNORM)
+ fds[loop].revents |= POLLRDNORM;
+ if (fds[loop].events & POLLRDBAND)
+ fds[loop].revents |= POLLRDBAND;
+ if (fds[loop].events & POLLPRI)
+ fds[loop].revents |= POLLPRI;
+
+ // Do we want to abort on error?
+ if (fds[loop].events & POLLERR)
+ error = true;
+ }
+ else if (pos > 0)
+ {
+ // Input characters were found for this fd
+ ret += 1;
+ if (fds[loop].events & POLLRDNORM)
+ fds[loop].revents |= POLLRDNORM;
+ if (fds[loop].events & POLLRDBAND)
+ fds[loop].revents |= POLLRDBAND;
+ if (fds[loop].events & POLLPRI)
+ fds[loop].revents |= POLLPRI;
+
+ // Do we want to abort on input?
+ if ((fds[loop].events & POLLIN) ||
+ (fds[loop].events & POLLPRI) ||
+ (fds[loop].events & POLLRDNORM) ||
+ (fds[loop].events & POLLRDBAND))
+ input = true;
+ }
+ }
+ }
+
+ if (input)
+ break;
+
+ dwNewTickCount = GetTickCount();
+ elapsed_time += (dwNewTickCount-dwOldTickCount);
+ // Note that the above will wrap round if the user leaves
+ // his computer powered up for more than about 50 days!
+
+ // Sleep briefly because GetTickCount() only has an accuracy of 10mS
+ Sleep(10); // For some reason 'g_usleep()' craps over everything here. Different 'C' runtimes???
+
+ } while ((!error) && ((timeout == (-1)) || (elapsed_time < timeout)));
+ }
+ else
+ {
+ errno = ERROR_BAD_ARGUMENTS;
+ ret = (-1);
+ }
+
+ return (ret);
+}
+
+int poll_output (struct pollfd *fds, nfds_t nfds, int& elapsed_time, int timeout)
+{
+int ret = 0; // This functionality is not yet implemented
+
+ if (NULL != fds)
+ {
+ // Just flag whichever pollfd was specified for writing
+ short ev_mask = (POLLOUT|POLLWRNORM|POLLWRBAND);
+
+ errno = NO_ERROR;
+ elapsed_time = 0;
+
+ for (nfds_t loop=0; loop<nfds; loop++)
+ {
+ if (fds[loop].events & ev_mask)
+ {
+ fds[loop].revents = POLLNVAL;
+ errno = ERROR_INVALID_ACCESS;
+ ret = (-1);
+ }
+ }
+ }
+ else
+ {
+ errno = ERROR_BAD_ARGUMENTS;
+ ret = (-1);
+ }
+
+ return (ret);
+}
+
+//***************************************************************
+//
+// poll()
+//
+// Emulates POSIX poll() using Win32 _tell().
+//
+// Returns:
+//
+// On Success: A positive integer indicating the total number
+// of file descriptors that were available for
+// writing or had data available for reading.
+// On Failure: -1 (the actual error is saved in 'errno').
+//
+LIBPBD_API int PBD_APICALLTYPE
+poll (struct pollfd *fds, nfds_t nfds, int timeout)
+{
+int elapsed_time = 0;
+int ret = (-1);
+
+ // Note that this functionality is not fully implemented.
+ // At the time of writing, Ardour seems only to poll on
+ // read pipes. Therefore return an error if any write
+ // pipe seems to have been specified or if too many file
+ // descriptors were passed.
+ short ev_mask = (POLLOUT|POLLWRNORM|POLLWRBAND);
+
+ if ((nfds > OPEN_MAX) || (nfds > NPOLLFILE))
+ {
+ errno = ERROR_TOO_MANY_OPEN_FILES;
+ }
+ else
+ {
+ ret = 0;
+
+ for (nfds_t loop=0; loop<nfds; loop++)
+ {
+ if (fds[loop].events & ev_mask)
+ {
+ ret = poll_output(fds, nfds, elapsed_time, timeout);
+ break;
+ }
+ }
+
+ if (0 == ret)
+ {
+ // Poll for input
+ ret = poll_input(fds, nfds, elapsed_time, timeout);
+ }
+ }
+
+ return (ret);
+}
+
+#endif //COMPILER_MSVC
diff --git a/libs/pbd/pathexpand.cc b/libs/pbd/pathexpand.cc
index 4911f12788..5784ec9428 100644
--- a/libs/pbd/pathexpand.cc
+++ b/libs/pbd/pathexpand.cc
@@ -18,8 +18,10 @@
*/
#include <vector>
-#include <climits>
#include <iostream>
+#include <climits>
+#include <cerrno>
+#include <cstdlib>
#include <regex.h>
@@ -32,6 +34,22 @@ using std::string;
using std::vector;
string
+PBD::canonical_path (const std::string& path)
+{
+#ifdef COMPILER_MINGW
+ return path;
+#else
+ char buf[PATH_MAX+1];
+
+ if (!realpath (path.c_str(), buf) && (errno != ENOENT)) {
+ return path;
+ }
+
+ return string (buf);
+#endif
+}
+
+string
PBD::path_expand (string path)
{
if (path.empty()) {
@@ -97,13 +115,7 @@ PBD::path_expand (string path)
/* canonicalize */
- char buf[PATH_MAX+1];
-
- if (realpath (path.c_str(), buf)) {
- return buf;
- } else {
- return string();
- }
+ return canonical_path (path);
}
string
diff --git a/libs/pbd/pathscanner.cc b/libs/pbd/pathscanner.cc
index fac2dcfd96..b9b501a120 100644
--- a/libs/pbd/pathscanner.cc
+++ b/libs/pbd/pathscanner.cc
@@ -18,11 +18,19 @@
$Id$
*/
+#ifdef COMPILER_MSVC
+#include <stdlib.h>
+#include <stdio.h>
+using PBD::readdir;
+using PBD::opendir;
+using PBD::closedir;
+#else
+#include <dirent.h>
#include <cstdlib>
#include <cstdio>
+#endif
#include <cstring>
#include <vector>
-#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
diff --git a/libs/pbd/pbd/abstract_ui.cc b/libs/pbd/pbd/abstract_ui.cc
index d43bc64f63..67c39b57e4 100644
--- a/libs/pbd/pbd/abstract_ui.cc
+++ b/libs/pbd/pbd/abstract_ui.cc
@@ -28,6 +28,15 @@
#include "i18n.h"
+#ifdef COMPILER_MSVC
+#include <ardourext/misc.h> // Needed for 'DECLARE_DEFAULT_COMPARISONS'. Objects in an STL container can be
+ // searched and sorted. Thus, when instantiating the container, MSVC complains
+ // if the type of object being contained has no appropriate comparison operators
+ // defined (specifically, if operators '<' and '==' are undefined). This seems
+ // to be the case with ptw32 'pthread_t' which is a simple struct.
+DECLARE_DEFAULT_COMPARISONS(ptw32_handle_t)
+#endif
+
using namespace std;
template<typename RequestBuffer> void
@@ -146,7 +155,7 @@ AbstractUI<RequestObject>::get_request (RequestType rt)
return 0;
}
- DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1: allocated per-thread request of type %2, caller %3\n", name(), rt, pthread_self()));
+ DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1: allocated per-thread request of type %2, caller %3\n", name(), rt, pthread_name()));
vec.buf[0]->type = rt;
vec.buf[0]->valid = true;
@@ -158,7 +167,7 @@ AbstractUI<RequestObject>::get_request (RequestType rt)
* are not at work.
*/
- DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1: allocated normal heap request of type %2, caller %3\n", name(), rt, pthread_self()));
+ DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1: allocated normal heap request of type %2, caller %3\n", name(), rt, pthread_name()));
RequestObject* req = new RequestObject;
req->type = rt;
@@ -213,7 +222,7 @@ AbstractUI<RequestObject>::handle_ui_requests ()
for (i = request_buffers.begin(); i != request_buffers.end(); ) {
if ((*i).second->dead) {
DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 deleting dead per-thread request buffer for %3 @ %4\n",
- name(), pthread_self(), i->first, i->second));
+ name(), pthread_name(), i->second));
delete (*i).second;
RequestBufferMapIterator tmp = i;
++tmp;
@@ -241,7 +250,7 @@ AbstractUI<RequestObject>::handle_ui_requests ()
request_buffer_map_lock.lock ();
if (!req->valid) {
- DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 handling invalid heap request, type %3, deleting\n", name(), pthread_self(), req->type));
+ DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 handling invalid heap request, type %3, deleting\n", name(), pthread_name(), req->type));
delete req;
request_buffer_map_lock.unlock ();
continue;
@@ -253,7 +262,7 @@ AbstractUI<RequestObject>::handle_ui_requests ()
*/
if (req->invalidation) {
- DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 remove request from its invalidation list\n", name(), pthread_self()));
+ DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 remove request from its invalidation list\n", name(), pthread_name()));
/* after this call, if the object referenced by the
* invalidation record is deleted, it will no longer
@@ -281,7 +290,7 @@ AbstractUI<RequestObject>::handle_ui_requests ()
lm.release ();
- DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 execute request type %3\n", name(), pthread_self(), req->type));
+ DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 execute request type %3\n", name(), pthread_name(), req->type));
/* and lets do it ... this is a virtual call so that each
* specific type of UI can have its own set of requests without
@@ -290,7 +299,7 @@ AbstractUI<RequestObject>::handle_ui_requests ()
do_request (req);
- DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 delete heap request type %3\n", name(), pthread_self(), req->type));
+ DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 delete heap request type %3\n", name(), pthread_name(), req->type));
delete req;
/* re-acquire the list lock so that we check again */
@@ -315,7 +324,7 @@ AbstractUI<RequestObject>::send_request (RequestObject *req)
/* the thread that runs this UI's event loop is sending itself
a request: we dispatch it immediately and inline.
*/
- DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 direct dispatch of request type %3\n", name(), pthread_self(), req->type));
+ DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 direct dispatch of request type %3\n", name(), pthread_name(), req->type));
do_request (req);
} else {
@@ -334,13 +343,13 @@ AbstractUI<RequestObject>::send_request (RequestObject *req)
RequestBuffer* rbuf = per_thread_request_buffer.get ();
if (rbuf != 0) {
- DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 send per-thread request type %3\n", name(), pthread_self(), req->type));
+ DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 send per-thread request type %3\n", name(), pthread_name(), req->type));
rbuf->increment_write_ptr (1);
} else {
/* no per-thread buffer, so just use a list with a lock so that it remains
single-reader/single-writer semantics
*/
- DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 send heap request type %3\n", name(), pthread_self(), req->type));
+ DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 send heap request type %3\n", name(), pthread_name(), req->type));
Glib::Threads::Mutex::Lock lm (request_list_lock);
request_list.push_back (req);
}
@@ -349,7 +358,7 @@ AbstractUI<RequestObject>::send_request (RequestObject *req)
at the per-thread and generic request lists.
*/
- request_channel.wakeup ();
+ signal_new_request ();
}
}
@@ -357,7 +366,7 @@ template<typename RequestObject> void
AbstractUI<RequestObject>::call_slot (InvalidationRecord* invalidation, const boost::function<void()>& f)
{
if (caller_is_self()) {
- DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 direct dispatch of call slot via functor @ %3, invalidation %4\n", name(), pthread_self(), &f, invalidation));
+ DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 direct dispatch of call slot via functor @ %3, invalidation %4\n", name(), pthread_name(), &f, invalidation));
f ();
return;
}
@@ -368,7 +377,7 @@ AbstractUI<RequestObject>::call_slot (InvalidationRecord* invalidation, const bo
return;
}
- DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 queue call-slot using functor @ %3, invalidation %4\n", name(), pthread_self(), &f, invalidation));
+ DEBUG_TRACE (PBD::DEBUG::AbstractUI, string_compose ("%1/%2 queue call-slot using functor @ %3, invalidation %4\n", name(), pthread_name(), &f, invalidation));
/* copy semantics: copy the functor into the request object */
diff --git a/libs/pbd/pbd/abstract_ui.h b/libs/pbd/pbd/abstract_ui.h
index f78ba26090..1ceefe7b3b 100644
--- a/libs/pbd/pbd/abstract_ui.h
+++ b/libs/pbd/pbd/abstract_ui.h
@@ -52,7 +52,7 @@
class Touchable;
template<typename RequestObject>
-class ABSTRACT_UI_API AbstractUI : public BaseUI /* see notes in visibility.h about why this is not LIBPBD_API */
+class /*ABSTRACT_UI_API*/ AbstractUI : public BaseUI /* see notes in visibility.h about why this is not LIBPBD_API */
{
public:
AbstractUI (const std::string& name);
@@ -74,8 +74,22 @@ class ABSTRACT_UI_API AbstractUI : public BaseUI /* see notes in visibility.h ab
, ui (uir) {}
};
typedef typename RequestBuffer::rw_vector RequestBufferVector;
+
+#if defined(__MINGW32__)
+
+ struct pthread_cmp
+ {
+ bool operator() (const ptw32_handle_t& thread1, const ptw32_handle_t& thread2)
+ {
+ return thread1.p < thread2.p;
+ }
+ };
+ typedef typename std::map<pthread_t,RequestBuffer*, pthread_cmp>::iterator RequestBufferMapIterator;
+ typedef std::map<pthread_t,RequestBuffer*, pthread_cmp> RequestBufferMap;
+#else
typedef typename std::map<pthread_t,RequestBuffer*>::iterator RequestBufferMapIterator;
typedef std::map<pthread_t,RequestBuffer*> RequestBufferMap;
+#endif
RequestBufferMap request_buffers;
static Glib::Threads::Private<RequestBuffer> per_thread_request_buffer;
diff --git a/libs/pbd/pbd/atomic_counter.h b/libs/pbd/pbd/atomic_counter.h
new file mode 100644
index 0000000000..1e1998e1f1
--- /dev/null
+++ b/libs/pbd/pbd/atomic_counter.h
@@ -0,0 +1,99 @@
+/*
+ Copyright (C) 2010 Tim Mayberry
+
+ 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_ATOMIC_COUNTER_H
+#define PBD_ATOMIC_COUNTER_H
+
+#include <glib.h>
+
+namespace PBD {
+
+class atomic_counter
+{
+ /**
+ * Prevent copying and assignment
+ */
+ atomic_counter (const atomic_counter&);
+ atomic_counter& operator= (const atomic_counter&);
+
+public:
+
+ atomic_counter (gint value = 0)
+ :
+ m_value(value)
+ { }
+
+ gint get() const
+ {
+ return g_atomic_int_get (&m_value);
+ }
+
+ void set (gint new_value)
+ {
+ g_atomic_int_set (&m_value, new_value);
+ }
+
+ void increment ()
+ {
+ g_atomic_int_inc (&m_value);
+ }
+
+ void operator++ ()
+ {
+ increment ();
+ }
+
+ bool decrement_and_test ()
+ {
+ return g_atomic_int_dec_and_test (&m_value);
+ }
+
+ bool operator-- ()
+ {
+ return decrement_and_test ();
+ }
+
+ bool compare_and_exchange (gint old_value, gint new_value)
+ {
+ return g_atomic_int_compare_and_exchange
+ (
+ &m_value,
+ old_value,
+ new_value
+ );
+ }
+
+ /**
+ * convenience method, \see compare_and_exchange
+ */
+ bool cas (gint old_value, gint new_value)
+ {
+ return compare_and_exchange (old_value, new_value);
+ }
+
+private:
+
+ // Has to be mutable when using the apple version of gcc.
+ mutable volatile gint m_value;
+
+};
+
+} // namespace PBD
+
+#endif // PBD_ATOMIC_COUNTER_H
diff --git a/libs/pbd/pbd/base_ui.h b/libs/pbd/pbd/base_ui.h
index ee2bbf5ee9..ea1afbbb5a 100644
--- a/libs/pbd/pbd/base_ui.h
+++ b/libs/pbd/pbd/base_ui.h
@@ -72,13 +72,13 @@ class LIBPBD_API BaseUI : public sigc::trackable, public PBD::EventLoop
void quit ();
protected:
- CrossThreadChannel request_channel;
bool _ok;
Glib::RefPtr<Glib::MainLoop> _main_loop;
- Glib::Threads::Thread* run_loop_thread;
+ Glib::RefPtr<Glib::MainContext> m_context;
+ Glib::Threads::Thread* run_loop_thread;
Glib::Threads::Mutex _run_lock;
- Glib::Threads::Cond _running;
+ Glib::Threads::Cond _running;
/* this signals _running from within the event loop,
from an idle callback
@@ -93,9 +93,17 @@ class LIBPBD_API BaseUI : public sigc::trackable, public PBD::EventLoop
virtual void thread_init () {};
+#ifdef PLATFORM_WINDOWS
+ static gboolean _request_handler (gpointer);
+ bool request_handler ();
+#else
/** Called when there input ready on the request_channel
*/
bool request_handler (Glib::IOCondition);
+#endif
+
+ void signal_new_request ();
+ void attach_request_source ();
/** Derived UI objects must implement this method,
* which will be called whenever there are requests
@@ -106,6 +114,10 @@ class LIBPBD_API BaseUI : public sigc::trackable, public PBD::EventLoop
private:
std::string _name;
BaseUI* base_ui_instance;
+
+#ifndef PLATFORM_WINDOWS
+ CrossThreadChannel request_channel;
+#endif
static uint64_t rt_bit;
diff --git a/libs/pbd/pbd/cartesian.h b/libs/pbd/pbd/cartesian.h
index 20c8b27088..5f0b951d5f 100644
--- a/libs/pbd/pbd/cartesian.h
+++ b/libs/pbd/pbd/cartesian.h
@@ -97,7 +97,7 @@ struct LIBPBD_API AngularVector {
}
};
-LIBPBD_API inline void CartesianVector::angular (AngularVector& a) const {
+inline void CartesianVector::angular (AngularVector& a) const {
cartesian_to_spherical (x, y, z, a.azi, a.ele, a.length);
}
diff --git a/libs/pbd/pbd/compose.h b/libs/pbd/pbd/compose.h
index a80cb213b2..cb4182699f 100644
--- a/libs/pbd/pbd/compose.h
+++ b/libs/pbd/pbd/compose.h
@@ -204,7 +204,7 @@ namespace StringPrivate
// 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> LIBPBD_API
+ template <typename T1>
inline std::string string_compose(const std::string &fmt, const T1 &o1)
{
StringPrivate::Composition c(fmt);
@@ -212,7 +212,7 @@ namespace StringPrivate
return c.str();
}
- template <typename T1, typename T2> LIBPBD_API
+ template <typename T1, typename T2>
inline std::string string_compose(const std::string &fmt,
const T1 &o1, const T2 &o2)
{
@@ -221,7 +221,7 @@ namespace StringPrivate
return c.str();
}
- template <typename T1, typename T2, typename T3> LIBPBD_API
+ 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)
{
@@ -230,7 +230,7 @@ namespace StringPrivate
return c.str();
}
- template <typename T1, typename T2, typename T3, typename T4> LIBPBD_API
+ 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)
@@ -240,7 +240,7 @@ namespace StringPrivate
return c.str();
}
- template <typename T1, typename T2, typename T3, typename T4, typename T5> LIBPBD_API
+ 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)
@@ -251,7 +251,7 @@ namespace StringPrivate
}
template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6> LIBPBD_API
+ 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)
@@ -262,7 +262,7 @@ namespace StringPrivate
}
template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7> LIBPBD_API
+ 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,
@@ -274,7 +274,7 @@ namespace StringPrivate
}
template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8> LIBPBD_API
+ 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,
@@ -286,7 +286,7 @@ namespace StringPrivate
}
template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9> LIBPBD_API
+ 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,
@@ -298,7 +298,7 @@ namespace StringPrivate
}
template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10> LIBPBD_API
+ 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,
@@ -313,7 +313,7 @@ namespace StringPrivate
template <typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11> LIBPBD_API
+ 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,
@@ -328,7 +328,7 @@ namespace StringPrivate
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> LIBPBD_API
+ 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,
@@ -343,7 +343,7 @@ namespace StringPrivate
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> LIBPBD_API
+ 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,
@@ -359,7 +359,7 @@ namespace StringPrivate
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> LIBPBD_API
+ 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,
@@ -376,7 +376,7 @@ namespace StringPrivate
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> LIBPBD_API
+ 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,
diff --git a/libs/pbd/pbd/convert.h b/libs/pbd/pbd/convert.h
index 1269254906..6580a6e8e7 100644
--- a/libs/pbd/pbd/convert.h
+++ b/libs/pbd/pbd/convert.h
@@ -47,7 +47,7 @@ LIBPBD_API std::string length2string (const int64_t frames, const double sample_
LIBPBD_API std::vector<std::string> internationalize (const char *, const char **);
LIBPBD_API bool strings_equal_ignore_case (const std::string& a, const std::string& b);
-template <class T> std::string LIBPBD_API
+template <class T> std::string /*LIBPBD_API*/
to_string (T t, std::ios_base & (*f)(std::ios_base&))
{
std::ostringstream oss;
diff --git a/libs/pbd/pbd/debug.h b/libs/pbd/pbd/debug.h
index dc7e1ce906..54577f1a7e 100644
--- a/libs/pbd/pbd/debug.h
+++ b/libs/pbd/pbd/debug.h
@@ -45,6 +45,7 @@ namespace PBD {
LIBPBD_API extern uint64_t Pool;
LIBPBD_API extern uint64_t EventLoop;
LIBPBD_API extern uint64_t AbstractUI;
+ extern uint64_t FileUtils;
}
}
diff --git a/libs/pbd/pbd/demangle.h b/libs/pbd/pbd/demangle.h
index c9f5c194c0..12dc58839c 100644
--- a/libs/pbd/pbd/demangle.h
+++ b/libs/pbd/pbd/demangle.h
@@ -32,7 +32,7 @@
namespace PBD
{
- template<typename T> LIBPBD_API
+ template<typename T> /*LIBPBD_API*/
std::string demangled_name (T const & obj)
{
#ifdef __GNUC__
diff --git a/libs/pbd/pbd/fallback_folders.h b/libs/pbd/pbd/fallback_folders.h
new file mode 100644
index 0000000000..db8992db6d
--- /dev/null
+++ b/libs/pbd/pbd/fallback_folders.h
@@ -0,0 +1,62 @@
+/*
+ Copyright (C) 2009 John Emmas
+
+ 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 __platform_fallback_folders_h__
+#define __platform_fallback_folders_h__
+
+#include <pbd/msvc_pbd.h>
+#include <glib/gtypes.h>
+
+#ifdef PLATFORM_WINDOWS // Would not be relevant for Cygwin!!
+ LIBPBD_API gchar* PBD_APICALLTYPE get_win_special_folder (int csidl);
+#endif
+
+namespace PBD {
+
+ typedef enum fallback_folder_t {
+ FOLDER_LOCALE,
+ FOLDER_GTK,
+ FOLDER_CONFIG,
+ FOLDER_ARDOUR,
+ FOLDER_MODULE,
+ FOLDER_DATA,
+ FOLDER_ICONS,
+ FOLDER_PIXMAPS,
+ FOLDER_CONTROL_SURFACES,
+ FOLDER_VAMP,
+ FOLDER_LADSPA,
+ FOLDER_VST,
+ FOLDER_BUNDLED_LV2,
+ FALLBACK_FOLDER_MAX
+ };
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+ LIBPBD_API G_CONST_RETURN gchar* PBD_APICALLTYPE get_platform_fallback_folder (PBD::fallback_folder_t index);
+ LIBPBD_API G_CONST_RETURN gchar* G_CONST_RETURN * PBD_APICALLTYPE alloc_platform_fallback_folders ();
+ LIBPBD_API void PBD_APICALLTYPE free_platform_fallback_folders ();
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+} // namespace PBD
+
+#endif /* __platform_fallback_folders_h__ */
diff --git a/libs/pbd/uuid_boost.cc b/libs/pbd/pbd/ffs.h
index 1a988b9820..f21fc82a39 100644
--- a/libs/pbd/uuid_boost.cc
+++ b/libs/pbd/pbd/ffs.h
@@ -1,6 +1,5 @@
/*
- Copyright (C) 2008 Paul Davis
- Author: Sakari Bergen
+ Copyright (C) 2013 Tim Mayberry
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
@@ -18,20 +17,13 @@
*/
-#include "pbd/uuid.h"
+#ifndef __libpbd_ffs_h__
+#define __libpbd_ffs_h__
-using namespace PBD;
+#include "pbd/libpbd_visibility.h"
-UUID&
-UUID::operator= (std::string const & str)
-{
- boost::uuids::string_generator gen;
- *((boost::uuids::uuid*) this) = gen (str);
- return *this;
-}
+namespace PBD {
+ LIBPBD_API int ffs(int x);
+}
-std::string
-UUID::to_s () const
-{
- return std::string ((const char*) data, size());
-}
+#endif /* __libpbd_ffs_h__ */
diff --git a/libs/pbd/pbd/file_utils.h b/libs/pbd/pbd/file_utils.h
index 6f8a98b697..01ff8606a7 100644
--- a/libs/pbd/pbd/file_utils.h
+++ b/libs/pbd/pbd/file_utils.h
@@ -69,15 +69,15 @@ find_matching_files_in_directories (const std::vector<std::string>& directory_pa
std::vector<std::string>& result);
/**
- * Takes a SearchPath and puts a list of all the files in the search path
+ * Takes a Searchpath and puts a list of all the files in the search path
* that match pattern into the result vector.
*
- * @param search_path A SearchPath
+ * @param search_path A Searchpath
* @param pattern A Glib::PatternSpec used to match the files
* @param result A vector in which to place the resulting matches.
*/
LIBPBD_API void
-find_matching_files_in_search_path (const SearchPath& search_path,
+find_matching_files_in_search_path (const Searchpath& search_path,
const Glib::PatternSpec& pattern,
std::vector<std::string>& result);
@@ -88,7 +88,7 @@ find_matching_files_in_search_path (const SearchPath& search_path,
* @return true If file is found within the search path.
*/
LIBPBD_API bool
-find_file_in_search_path (const SearchPath& search_path,
+find_file_in_search_path (const Searchpath& search_path,
const std::string& filename,
std::string& result);
diff --git a/libs/pbd/pbd/floating.h b/libs/pbd/pbd/floating.h
index e5d582625a..c0003a3113 100644
--- a/libs/pbd/pbd/floating.h
+++ b/libs/pbd/pbd/floating.h
@@ -26,13 +26,15 @@
#ifndef __libpbd__floating_h__
#define __libpbd__floating_h__
+#include <stdint.h>
+
#include <cmath>
#include "pbd/libpbd_visibility.h"
namespace PBD {
-union LIBPBD_API Float_t
+union /*LIBPBD_API*/ Float_t
{
Float_t (float num = 0.0f) : f(num) {}
diff --git a/libs/pbd/pbd/functor_command.h b/libs/pbd/pbd/functor_command.h
index d2aacd18ac..6cca13209f 100644
--- a/libs/pbd/pbd/functor_command.h
+++ b/libs/pbd/pbd/functor_command.h
@@ -37,7 +37,7 @@
namespace PBD {
template <class obj_type, class arg_type>
-class LIBPBD_API FunctorCommand : public Command
+class /*LIBPBD_API*/ FunctorCommand : public Command
{
private:
typedef void (obj_type::*functor_type)(arg_type);
diff --git a/libs/pbd/pbd/glib_semaphore.h b/libs/pbd/pbd/glib_semaphore.h
new file mode 100644
index 0000000000..7f96120d7d
--- /dev/null
+++ b/libs/pbd/pbd/glib_semaphore.h
@@ -0,0 +1,57 @@
+/*
+ Copyright (C) 2010 Tim Mayberry
+
+ 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_GLIB_SEMAPHORE_H
+#define PBD_GLIB_SEMAPHORE_H
+
+#include <glibmm/threads.h>
+
+#include "pbd/libpbd_visibility.h"
+#include "atomic_counter.h"
+
+namespace PBD {
+
+class LIBPBD_API GlibSemaphore
+{
+
+ // prevent copying and assignment
+ GlibSemaphore(const GlibSemaphore& sema);
+ GlibSemaphore& operator= (const GlibSemaphore& sema);
+
+public:
+
+ GlibSemaphore (gint initial_val = 1);
+
+ void wait ();
+
+ bool try_wait ();
+
+ void post ();
+
+private:
+
+ atomic_counter m_counter;
+ Glib::Threads::Cond m_cond;
+ Glib::Threads::Mutex m_mutex;
+
+};
+
+} // namespace PBD
+
+#endif // PBD_SEMAPHORE_H
diff --git a/libs/pbd/pbd/localeguard.h b/libs/pbd/pbd/localeguard.h
new file mode 100644
index 0000000000..21ea5380fa
--- /dev/null
+++ b/libs/pbd/pbd/localeguard.h
@@ -0,0 +1,37 @@
+/*
+ Copyright (C) 1999-2010 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_localeguard_h__
+#define __pbd_localeguard_h__
+
+#include <string>
+
+namespace PBD {
+
+struct LIBPBD_API /* Added by JE - */ LocaleGuard {
+ LocaleGuard (const char*);
+ ~LocaleGuard ();
+ const char* old;
+
+ /* JE - temporary !!!! */static std::string current;
+};
+
+}; // namespace
+
+#endif /* __pbd_localeguard_h__ */
diff --git a/libs/pbd/pbd/localtime_r.h b/libs/pbd/pbd/localtime_r.h
new file mode 100644
index 0000000000..ad5b89d134
--- /dev/null
+++ b/libs/pbd/pbd/localtime_r.h
@@ -0,0 +1,13 @@
+#ifndef PBD_LOCALTIME_R
+#define PBD_LOCALTIME_R
+#include <time.h>
+
+#ifdef COMPILER_MSVC
+ #define localtime_r( _clock, _result ) \
+ ( *(_result) = *localtime( (_clock) ), \
+ (_result) )
+#else
+ extern struct tm *localtime_r(const time_t *const timep, struct tm *p_tm);
+#endif
+
+#endif
diff --git a/libs/pbd/pbd/memento_command.h b/libs/pbd/pbd/memento_command.h
index 6560780f3c..f6d11a0b33 100644
--- a/libs/pbd/pbd/memento_command.h
+++ b/libs/pbd/pbd/memento_command.h
@@ -51,7 +51,7 @@
* can do `just-in-time' binding from the crossfade ID.
*/
template <class obj_T>
-class LIBPBD_API MementoCommandBinder : public PBD::Destructible
+class /*LIBPBD_API*/ MementoCommandBinder : public PBD::Destructible
{
public:
/** @return Stateful object to operate on */
@@ -68,7 +68,7 @@ public:
/** A simple MementoCommandBinder which binds directly to an object */
template <class obj_T>
-class LIBPBD_API SimpleMementoCommandBinder : public MementoCommandBinder<obj_T>
+class /*LIBPBD_API*/ SimpleMementoCommandBinder : public MementoCommandBinder<obj_T>
{
public:
SimpleMementoCommandBinder (obj_T& o)
@@ -100,7 +100,7 @@ private:
* memento, and redo is restoring the after memento.
*/
template <class obj_T>
-class LIBPBD_API MementoCommand : public Command
+class /*LIBPBD_API*/ MementoCommand : public Command
{
public:
MementoCommand (obj_T& a_object, XMLNode* a_before, XMLNode* a_after)
diff --git a/libs/pbd/pbd/msvc_pbd.h b/libs/pbd/pbd/msvc_pbd.h
new file mode 100644
index 0000000000..a623ca2eb2
--- /dev/null
+++ b/libs/pbd/pbd/msvc_pbd.h
@@ -0,0 +1,256 @@
+/*
+ Copyright (C) 2009 John Emmas
+
+ 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 _msvc_pbd_h_
+#define _msvc_pbd_h_
+
+#ifdef PBD_IS_IN_WIN_STATIC_LIB // #define if your project uses libpbd (under Windows) as a static library
+#undef LIBPBD_DLL
+#define PBD_IS_IN_WINDLL 0
+#endif
+
+#include <pbd/libpbd_visibility.h>
+
+#ifndef COMPILER_MSVC
+#include <sys/time.h>
+#else
+#include <ardourext/misc.h>
+#include <ardourext/sys/time.h>
+#endif
+
+#if !defined(PBD_IS_IN_WINDLL)
+ #if defined(COMPILER_MSVC) || defined(COMPILER_MINGW)
+ // If you need '__declspec' compatibility, add extra compilers to the above as necessary
+ #define PBD_IS_IN_WINDLL 1
+ #else
+ #define PBD_IS_IN_WINDLL 0
+ #endif
+#endif
+
+#if PBD_IS_IN_WINDLL && !defined(PBD_APICALLTYPE)
+ #if defined(BUILDING_PBD)
+ #define PBD_APICALLTYPE __cdecl
+ #elif defined(COMPILER_MSVC) || defined(COMPILER_MINGW) // Probably needs Cygwin too, at some point
+ #define PBD_APICALLTYPE __cdecl
+ #else
+ #error "Attempting to define __declspec with an incompatible compiler !"
+ #endif
+#elif !defined(PBD_APICALLTYPE)
+ // Other compilers / platforms could be accommodated here
+ #define PBD_APICALLTYPE
+#ifndef GETOPT_API
+ #define GETOPT_API
+ #define GETOPT_APICALLTYPE
+#endif
+#endif
+
+#ifndef GETOPT_API
+ #if defined(BUILDING_GETOPT)
+ #define GETOPT_API __declspec(dllexport)
+ #define GETOPT_APICALLTYPE __cdecl
+ #elif defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW__) || defined(_MINGW32__)
+ #define GETOPT_API __declspec(dllimport)
+ #define GETOPT_APICALLTYPE __cdecl
+ #else
+ #error "Attempting to define __declspec with an incompatible compiler !"
+ #endif
+#endif // GETOPT_API
+
+#ifndef _MAX_PATH
+#define _MAX_PATH 260
+#endif
+#ifndef PATH_MAX
+#define PATH_MAX _MAX_PATH
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+// This function is (hopefully) temporary and is placed here
+// because 'g_usleep()' doesn't seem to work very well for glib-win32
+// JE - let's see if we can do without this now! void pbd_g_usleep (unsigned long microseconds);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#ifndef POLLIN
+#define POLLIN 1
+#define POLLPRI 2
+#define POLLOUT 4
+#define POLLERR 8
+#define POLLHUP 16
+#define POLLNVAL 32
+#define NPOLLFILE 64
+
+#define POLLRDNORM POLLIN
+#define POLLRDBAND POLLIN
+#define POLLWRNORM POLLOUT
+#define POLLWRBAND POLLOUT
+#endif
+
+#ifdef PLATFORM_WINDOWS
+
+#ifndef PBDEXTN_API
+ #if defined(BUILDING_PBDEXTN)
+ #define PBDEXTN_API __declspec(dllexport)
+ #define PBDEXTN_APICALLTYPE __cdecl
+ #elif defined(COMPILER_MSVC) || defined(COMPILER_MINGW) // Probably needs Cygwin too, at some point
+ #define PBDEXTN_API __declspec(dllimport)
+ #define PBDEXTN_APICALLTYPE __cdecl
+ #else
+ #error "Attempting to define __declspec with an incompatible compiler !"
+ #endif
+#endif // PBDEXTN_API
+
+#ifndef CYGIMPORT_API
+ #define CYGIMPORT_API __declspec(dllimport)
+ #define CYGIMPORT_APICALLTYPE __cdecl
+#endif // CYGIMPORT_API
+
+#ifndef __THROW
+#define __THROW throw()
+#endif
+
+#ifndef RTLD_DEFAULT
+#define RTLD_DEFAULT ((void *) 0)
+#define RTLD_NEXT ((void *) -1L)
+#define RTLD_LAZY 0x00001
+#define RTLD_NOW 0x00002
+#define RTLD_BINDING_MASK 0x00003
+#define RTLD_NOLOAD 0x00004
+#define RTLD_GLOBAL 0x00004
+#define RTLD_DEEPBIND 0x00008
+#endif
+
+#ifndef OPEN_MAX
+#define OPEN_MAX 32
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+PBDEXTN_API int PBDEXTN_APICALLTYPE cyginit (unsigned int result);
+LIBPBD_API int PBD_APICALLTYPE dlclose (void *handle) __THROW;
+LIBPBD_API void* PBD_APICALLTYPE dlopen (const char *file_name, int mode) __THROW;
+LIBPBD_API void* PBD_APICALLTYPE dlsym (void *handle, const char *symbol_name) __THROW;
+LIBPBD_API char* PBD_APICALLTYPE dlerror () __THROW;
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#ifndef __CYGWIN__
+/* For whatever reason, Ardour's 'libevoral' refuses to build as a DLL if we include both 'rpc.h' */
+/* and 'WinSock2.h'. It doesn't seem to matter which order we #include them. Given that we can't */
+/* edit 'rpc.h' or 'WinSock2.h', just make sure we don't #include them when building libevoral. */
+#ifndef BUILDING_EVORAL
+#include <rpc.h>
+typedef int (FAR PBDEXTN_APICALLTYPE *CYGINIT_API)(unsigned int);
+#endif
+#include <io.h>
+#include <sys/types.h>
+
+#ifndef FILENAME_MAX
+#define FILENAME_MAX (260)
+#endif
+
+#ifndef _SSIZE_T_
+#define _SSIZE_T_
+typedef long _ssize_t;
+
+#ifndef _NO_OLDNAMES
+typedef _ssize_t ssize_t;
+#endif
+#endif /* ! _SSIZE_T_ */
+
+struct dirent
+{
+ long d_ino; // Always zero
+ unsigned short d_reclen; // Always zero
+ unsigned short d_namlen; // Length of name in d_name
+ char d_name[FILENAME_MAX]; // File name
+};
+
+// This is an internal data structure. Do not use it
+// except as an argument to one of the functions below.
+typedef struct
+{
+ // Disk transfer area for this dir
+ struct _finddata_t dd_dta;
+
+ // 'dirent' struct to return from dir (NOTE: this
+ // is not thread safe).
+ struct dirent dd_dir;
+
+ // '_findnext()' handle
+ long dd_handle;
+
+ // Current status of search:
+ // 0 = not started yet (next entry to read is first entry)
+ // -1 = off the end
+ // Otherwise - positive (0 based) index of next entry
+ int dd_stat;
+
+ // Full path for dir with search pattern (struct will be extended)
+ char dd_name[1];
+} DIR;
+
+struct pollfd
+{
+ int fd;
+ short events;
+ short revents;
+};
+
+typedef unsigned int nfds_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+LIBPBD_API int __cdecl gettimeofday(struct timeval *__restrict tv, __timezone_ptr_t tz);
+LIBPBD_API ssize_t PBD_APICALLTYPE pread(int handle, void *buf, size_t nbytes, off_t offset);
+LIBPBD_API ssize_t PBD_APICALLTYPE pwrite(int handle, const void *buf, size_t nbytes, off_t offset);
+LIBPBD_API int PBD_APICALLTYPE poll(struct pollfd *fds, nfds_t nfds, int timeout);
+LIBPBD_API double PBD_APICALLTYPE round(double x);
+
+namespace PBD {
+
+LIBPBD_API bool PBD_APICALLTYPE TestForMinimumSpecOS(char *revision="currently ignored");
+LIBPBD_API char* PBD_APICALLTYPE realpath (const char *original_path, char resolved_path[_MAX_PATH+1]);
+LIBPBD_API int PBD_APICALLTYPE mkstemp (char *template_name);
+LIBPBD_API int PBD_APICALLTYPE ntfs_link (const char *existing_filepath, const char *link_filepath);
+LIBPBD_API int PBD_APICALLTYPE ntfs_unlink (const char *link_filepath);
+
+// These are used to replicate 'dirent.h' functionality
+LIBPBD_API DIR* PBD_APICALLTYPE opendir (const char *szPath);
+LIBPBD_API struct dirent* PBD_APICALLTYPE readdir (DIR *pDir);
+LIBPBD_API int PBD_APICALLTYPE closedir (DIR *pDir);
+
+} // namespace PBD
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif // !__CYGWIN__
+#endif // PLATFORM_WINDOWS
+#endif // _msvc_pbd_h_
diff --git a/libs/pbd/pbd/pathexpand.h b/libs/pbd/pbd/pathexpand.h
index 5f1c03f8ee..5c5d4cf772 100644
--- a/libs/pbd/pbd/pathexpand.h
+++ b/libs/pbd/pbd/pathexpand.h
@@ -24,6 +24,7 @@
#include "pbd/libpbd_visibility.h"
namespace PBD {
+ LIBPBD_API std::string canonical_path (const std::string& path);
LIBPBD_API std::string path_expand (std::string path);
LIBPBD_API std::string search_path_expand (std::string path);
}
diff --git a/libs/pbd/pbd/pathscanner.h b/libs/pbd/pbd/pathscanner.h
index ef6499c759..d62203c008 100644
--- a/libs/pbd/pbd/pathscanner.h
+++ b/libs/pbd/pbd/pathscanner.h
@@ -22,7 +22,11 @@
#include <vector>
#include <string>
+#ifdef COMPILER_MSVC
+#include <ardourext/misc.h>
+#else
#include <regex.h>
+#endif
#include "pbd/libpbd_visibility.h"
diff --git a/libs/pbd/pbd/properties.h b/libs/pbd/pbd/properties.h
index 27a0be1895..70d18db4c7 100644
--- a/libs/pbd/pbd/properties.h
+++ b/libs/pbd/pbd/properties.h
@@ -37,7 +37,7 @@ namespace PBD {
/** Parent class for classes which represent a single scalar property in a Stateful object */
template<class T>
-class LIBPBD_API PropertyTemplate : public PropertyBase
+class /*LIBPBD_API*/ PropertyTemplate : public PropertyBase
{
public:
PropertyTemplate (PropertyDescriptor<T> p, T const& v)
@@ -197,7 +197,7 @@ private:
PropertyTemplate (PropertyTemplate<T> const &);
};
-template<class T> LIBPBD_API
+template<class T> /*LIBPBD_API*/
std::ostream & operator<<(std::ostream& os, PropertyTemplate<T> const& s)
{
return os << s.val ();
@@ -207,7 +207,7 @@ std::ostream & operator<<(std::ostream& os, PropertyTemplate<T> const& s)
* with types that can be written to / read from stringstreams.
*/
template<class T>
-class LIBPBD_API Property : public PropertyTemplate<T>
+class /*LIBPBD_API*/ Property : public PropertyTemplate<T>
{
public:
Property (PropertyDescriptor<T> q, T const& v)
@@ -285,7 +285,7 @@ private:
* separators, etc.
*/
template<>
-class LIBPBD_API Property<std::string> : public PropertyTemplate<std::string>
+class /*LIBPBD_API*/ Property<std::string> : public PropertyTemplate<std::string>
{
public:
Property (PropertyDescriptor<std::string> d, std::string const & v)
@@ -319,7 +319,7 @@ private:
};
template<class T>
-class LIBPBD_API EnumProperty : public Property<T>
+class /*LIBPBD_API*/ EnumProperty : public Property<T>
{
public:
EnumProperty (PropertyDescriptor<T> q, T const& v)
@@ -352,7 +352,7 @@ private:
* one.
*/
template <class T>
-class LIBPBD_API SharedStatefulProperty : public PropertyBase
+class /*LIBPBD_API*/ SharedStatefulProperty : public PropertyBase
{
public:
typedef boost::shared_ptr<T> Ptr;
diff --git a/libs/pbd/pbd/property_basics.h b/libs/pbd/pbd/property_basics.h
index 2da21ddb84..d0eb1db922 100644
--- a/libs/pbd/pbd/property_basics.h
+++ b/libs/pbd/pbd/property_basics.h
@@ -38,7 +38,7 @@ class LIBPBD_API StatefulDiffCommand;
typedef GQuark PropertyID;
template<typename T>
-struct LIBPBD_API PropertyDescriptor {
+struct /*LIBPBD_API*/ PropertyDescriptor {
PropertyDescriptor () : property_id (0) {}
PropertyDescriptor (PropertyID pid) : property_id (pid) {}
@@ -47,16 +47,17 @@ struct LIBPBD_API PropertyDescriptor {
};
/** A list of IDs of Properties that have changed in some situation or other */
-class LIBPBD_API PropertyChange : public std::set<PropertyID>
+class /*LIBPBD_API*/ PropertyChange : public std::set<PropertyID>
{
public:
- PropertyChange() {}
+ LIBPBD_API PropertyChange() {}
+ LIBPBD_API ~PropertyChange() {}
template<typename T> PropertyChange(PropertyDescriptor<T> p);
- PropertyChange(const PropertyChange& other) : std::set<PropertyID> (other) {}
+ LIBPBD_API PropertyChange(const PropertyChange& other) : std::set<PropertyID> (other) {}
- PropertyChange operator=(const PropertyChange& other) {
+ LIBPBD_API PropertyChange operator=(const PropertyChange& other) {
clear ();
insert (other.begin (), other.end ());
return *this;
@@ -65,7 +66,7 @@ public:
template<typename T> PropertyChange operator=(PropertyDescriptor<T> p);
template<typename T> bool contains (PropertyDescriptor<T> p) const;
- bool contains (const PropertyChange& other) const {
+ LIBPBD_API bool contains (const PropertyChange& other) const {
for (const_iterator x = other.begin (); x != other.end (); ++x) {
if (find (*x) != end ()) {
return true;
@@ -74,8 +75,8 @@ public:
return false;
}
- void add (PropertyID id) { insert (id); }
- void add (const PropertyChange& other) { insert (other.begin (), other.end ()); }
+ LIBPBD_API void add (PropertyID id) { insert (id); }
+ LIBPBD_API void add (const PropertyChange& other) { insert (other.begin (), other.end ()); }
template<typename T> void add (PropertyDescriptor<T> p);
};
diff --git a/libs/pbd/pbd/pthread_utils.h b/libs/pbd/pbd/pthread_utils.h
index c66feb73a5..37ce723715 100644
--- a/libs/pbd/pbd/pthread_utils.h
+++ b/libs/pbd/pbd/pthread_utils.h
@@ -20,7 +20,11 @@
#ifndef __pbd_pthread_utils__
#define __pbd_pthread_utils__
+#ifdef COMPILER_MSVC
+#include <ardourext/pthread.h>
+#else
#include <pthread.h>
+#endif
#include <signal.h>
#include <string>
#include <stdint.h>
diff --git a/libs/pbd/pbd/rcu.h b/libs/pbd/pbd/rcu.h
index 6ee68afabf..eceec24cd5 100644
--- a/libs/pbd/pbd/rcu.h
+++ b/libs/pbd/pbd/rcu.h
@@ -45,7 +45,7 @@
and managed object.
*/
template<class T>
-class LIBPBD_API RCUManager
+class /*LIBPBD_API*/ RCUManager
{
public:
@@ -111,7 +111,7 @@ class LIBPBD_API RCUManager
means that no actual objects will be deleted incorrectly if this is misused.
*/
template<class T>
-class LIBPBD_API SerializedRCUManager : public RCUManager<T>
+class /*LIBPBD_API*/ SerializedRCUManager : public RCUManager<T>
{
public:
@@ -214,7 +214,7 @@ private:
*/
template<class T>
-class LIBPBD_API RCUWriter
+class /*LIBPBD_API*/ RCUWriter
{
public:
diff --git a/libs/pbd/pbd/resource.h b/libs/pbd/pbd/resource.h
new file mode 100644
index 0000000000..ec826e4930
--- /dev/null
+++ b/libs/pbd/pbd/resource.h
@@ -0,0 +1,49 @@
+/*
+ Copyright (C) 2011 Tim Mayberry
+
+ 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.
+
+*/
+
+#include <stdint.h>
+
+namespace PBD {
+
+typedef uint64_t rlimit_t;
+
+enum ResourceType {
+ OpenFiles
+};
+
+struct ResourceLimit
+{
+ rlimit_t current_limit;
+ rlimit_t max_limit;
+};
+
+/**
+ * @return true on success, false on error
+ */
+bool
+get_resource_limit (ResourceType resource, ResourceLimit& limit);
+
+/**
+ * @return true on success, false on error
+ */
+bool
+set_resource_limit (ResourceType resource, const ResourceLimit& limit);
+
+
+} // namespace PBD
diff --git a/libs/pbd/pbd/ringbuffer.h b/libs/pbd/pbd/ringbuffer.h
index bb2b8244f9..e3cec6adf1 100644
--- a/libs/pbd/pbd/ringbuffer.h
+++ b/libs/pbd/pbd/ringbuffer.h
@@ -26,7 +26,7 @@
#include "pbd/libpbd_visibility.h"
template<class T>
-class LIBPBD_API RingBuffer
+class /*LIBPBD_API*/ RingBuffer
{
public:
RingBuffer (guint sz) {
@@ -120,7 +120,7 @@ class LIBPBD_API RingBuffer
guint size_mask;
};
-template<class T> LIBPBD_API guint
+template<class T> /*LIBPBD_API*/ guint
RingBuffer<T>::read (T *dest, guint cnt)
{
guint free_cnt;
@@ -159,7 +159,7 @@ RingBuffer<T>::read (T *dest, guint cnt)
return to_read;
}
-template<class T> LIBPBD_API guint
+template<class T> /*LIBPBD_API*/ guint
RingBuffer<T>::write (T const *src, guint cnt)
{
@@ -199,8 +199,8 @@ RingBuffer<T>::write (T const *src, guint cnt)
return to_write;
}
-template<class T> LIBPBD_API void
-RingBuffer<T>::get_read_vector (RingBuffer<T>::rw_vector *vec)
+template<class T> /*LIBPBD_API*/ void
+RingBuffer<T>::get_read_vector (typename RingBuffer<T>::rw_vector *vec)
{
guint free_cnt;
@@ -240,8 +240,8 @@ RingBuffer<T>::get_read_vector (RingBuffer<T>::rw_vector *vec)
}
}
-template<class T> LIBPBD_API void
-RingBuffer<T>::get_write_vector (RingBuffer<T>::rw_vector *vec)
+template<class T> /*LIBPBD_API*/ void
+RingBuffer<T>::get_write_vector (typename RingBuffer<T>::rw_vector *vec)
{
guint free_cnt;
diff --git a/libs/pbd/pbd/ringbufferNPT.h b/libs/pbd/pbd/ringbufferNPT.h
index 65fe939597..cd17299961 100644
--- a/libs/pbd/pbd/ringbufferNPT.h
+++ b/libs/pbd/pbd/ringbufferNPT.h
@@ -32,7 +32,7 @@ namespace PBD {
/* ringbuffer class where the element size is not required to be a power of two */
template<class T>
-class LIBPBD_API RingBufferNPT
+class /*LIBPBD_API*/ RingBufferNPT
{
public:
RingBufferNPT (size_t sz) {
@@ -120,7 +120,7 @@ class LIBPBD_API RingBufferNPT
mutable gint read_ptr;
};
-template<class T> LIBPBD_API size_t
+template<class T> /*LIBPBD_API*/ size_t
RingBufferNPT<T>::read (T *dest, size_t cnt)
{
size_t free_cnt;
@@ -159,7 +159,7 @@ RingBufferNPT<T>::read (T *dest, size_t cnt)
return to_read;
}
-template<class T> LIBPBD_API size_t
+template<class T> /*LIBPBD_API*/ size_t
RingBufferNPT<T>::write (const T *src, size_t cnt)
{
size_t free_cnt;
@@ -198,8 +198,8 @@ RingBufferNPT<T>::write (const T *src, size_t cnt)
return to_write;
}
-template<class T> LIBPBD_API void
-RingBufferNPT<T>::get_read_vector (RingBufferNPT<T>::rw_vector *vec)
+template<class T> /*LIBPBD_API*/ void
+RingBufferNPT<T>::get_read_vector (typename RingBufferNPT<T>::rw_vector *vec)
{
size_t free_cnt;
size_t cnt2;
@@ -238,8 +238,8 @@ RingBufferNPT<T>::get_read_vector (RingBufferNPT<T>::rw_vector *vec)
}
}
-template<class T> LIBPBD_API void
-RingBufferNPT<T>::get_write_vector (RingBufferNPT<T>::rw_vector *vec)
+template<class T> /*LIBPBD_API*/ void
+RingBufferNPT<T>::get_write_vector (typename RingBufferNPT<T>::rw_vector *vec)
{
size_t free_cnt;
size_t cnt2;
diff --git a/libs/pbd/pbd/search_path.h b/libs/pbd/pbd/search_path.h
index ad0b6c75d5..909bffb0a4 100644
--- a/libs/pbd/pbd/search_path.h
+++ b/libs/pbd/pbd/search_path.h
@@ -17,8 +17,8 @@
*/
-#ifndef PBD_SEARCH_PATH_INCLUDED
-#define PBD_SEARCH_PATH_INCLUDED
+#ifndef __libpbd_search_path_h__
+#define __libpbd_search_path_h__
#include <string>
#include <vector>
@@ -28,26 +28,26 @@
namespace PBD {
/**
- * @class SearchPath
+ * @class Searchpath
*
- * The SearchPath class is a helper class for getting a
+ * The Searchpath class is a helper class for getting a
* vector of paths contained in a search path string where a
* "search path string" contains absolute directory paths
* separated by a colon(:) or a semi-colon(;) on windows.
*
- * The SearchPath class does not test whether the paths exist
+ * The Searchpath class does not test whether the paths exist
* or are directories. It is basically just a container.
*/
-class LIBPBD_API SearchPath : public std::vector<std::string>
+class /*LIBPBD_API*/ Searchpath : public std::vector<std::string>
{
public:
/**
- * Create an empty SearchPath.
+ * Create an empty Searchpath.
*/
- SearchPath ();
+ LIBPBD_API Searchpath ();
/**
- * Initialize SearchPath from a string where the string contains
+ * Initialize Searchpath from a string where the string contains
* one or more absolute paths to directories which are delimited
* by a path separation character. The path delimeter is a
* colon(:) on unix and a semi-colon(;) on windows.
@@ -57,15 +57,17 @@ public:
*
* @param search_path A path string.
*/
- SearchPath (const std::string& search_path);
+ LIBPBD_API Searchpath (const std::string& search_path);
/**
- * Initialize SearchPath from a vector of paths that may or may
+ * Initialize Searchpath from a vector of paths that may or may
* not exist.
*
* @param paths A vector of paths.
*/
- SearchPath (const std::vector<std::string>& paths);
+ LIBPBD_API Searchpath (const std::vector<std::string>& paths);
+
+ LIBPBD_API ~Searchpath () {};
/**
* @return a search path string.
@@ -73,41 +75,41 @@ public:
* The string that is returned contains the platform specific
* path separator.
*/
- const std::string to_string () const;
+ LIBPBD_API const std::string to_string () const;
/**
* Add all the directories in path to this.
*/
- SearchPath& operator+= (const SearchPath& spath);
+ LIBPBD_API Searchpath& operator+= (const Searchpath& spath);
/**
* Add another directory path to the search path.
*/
- SearchPath& operator+= (const std::string& directory_path);
+ LIBPBD_API Searchpath& operator+= (const std::string& directory_path);
/**
- * Concatenate another SearchPath onto this.
+ * Concatenate another Searchpath onto this.
*/
- SearchPath& operator+ (const SearchPath& other);
+ LIBPBD_API Searchpath& operator+ (const Searchpath& other);
/**
* Add another path to the search path.
*/
- SearchPath& operator+ (const std::string& directory_path);
+ LIBPBD_API Searchpath& operator+ (const std::string& directory_path);
/**
* Add a sub-directory to each path in the search path.
* @param subdir The directory name, it should not contain
* any path separating tokens.
*/
- SearchPath& add_subdirectory_to_paths (const std::string& subdir);
+ LIBPBD_API Searchpath& add_subdirectory_to_paths (const std::string& subdir);
protected:
- void add_directory (const std::string& directory_path);
- void add_directories (const std::vector<std::string>& paths);
+ LIBPBD_API void add_directory (const std::string& directory_path);
+ LIBPBD_API void add_directories (const std::vector<std::string>& paths);
};
} // namespace PBD
-#endif
+#endif /* __libpbd_search_path_h__ */
diff --git a/libs/pbd/pbd/semaphore.h b/libs/pbd/pbd/semaphore.h
index a2390f5a18..265a219e07 100644
--- a/libs/pbd/pbd/semaphore.h
+++ b/libs/pbd/pbd/semaphore.h
@@ -22,8 +22,11 @@
#ifdef __APPLE__
# include <mach/mach.h>
-#elif defined(_WIN32)
+#elif defined(PLATFORM_WINDOWS)
# include <windows.h>
+#ifndef INFINITE
+#define INFINITE 0xffffffffL
+#endif
#else
# include <semaphore.h>
# include <errno.h>
@@ -46,7 +49,7 @@ namespace PBD {
only safe way to reliably signal from a real-time audio thread. The
counting semantics also complement ringbuffers of events nicely.
*/
-class LIBPBD_API Semaphore
+class /*LIBPBD_API*/ Semaphore
{
public:
/**
@@ -70,7 +73,7 @@ public:
private:
#if defined(__APPLE__)
semaphore_t _sem; // sem_t is a worthless broken mess on OSX
-#elif defined(_WIN32)
+#elif defined(PLATFORM_WINDOWS)
HANDLE _sem; // types are overrated anyway
#else
sem_t _sem;
@@ -115,7 +118,7 @@ Semaphore::try_wait()
return semaphore_timedwait(_sem, zero) == KERN_SUCCESS;
}
-#elif defined(_WIN32)
+#elif defined(PLATFORM_WINDOWS)
inline
Semaphore::Semaphore(unsigned initial)
@@ -152,7 +155,7 @@ Semaphore::try_wait()
return WaitForSingleObject(_sem, 0) == WAIT_OBJECT_0;
}
-#else /* !defined(__APPLE__) && !defined(_WIN32) */
+#else /* !defined(__APPLE__) && !defined(PLATFORM_WINDOWS) */
Semaphore::Semaphore(unsigned initial)
{
diff --git a/libs/pbd/pbd/semutils.h b/libs/pbd/pbd/semutils.h
index 719a3d0f46..5c0191e25b 100644
--- a/libs/pbd/pbd/semutils.h
+++ b/libs/pbd/pbd/semutils.h
@@ -19,7 +19,11 @@
#ifndef __pbd_semutils_h__
#define __pbd_semutils_h__
+#ifdef PLATFORM_WINDOWS
+#include <windows.h>
+#else
#include <semaphore.h>
+#endif
#include "pbd/libpbd_visibility.h"
@@ -27,7 +31,10 @@ namespace PBD {
class LIBPBD_API ProcessSemaphore {
private:
-#ifdef __APPLE__
+#ifdef PLATFORM_WINDOWS
+ HANDLE _sem;
+
+#elif __APPLE__
sem_t* _sem;
sem_t* ptr_to_sem() const { return _sem; }
#else
@@ -39,8 +46,15 @@ class LIBPBD_API ProcessSemaphore {
ProcessSemaphore (const char* name, int val);
~ProcessSemaphore ();
+#ifdef PLATFORM_WINDOWS
+
+ int signal ();
+ int wait ();
+
+#else
int signal () { return sem_post (ptr_to_sem()); }
int wait () { return sem_wait (ptr_to_sem()); }
+#endif
};
}
diff --git a/libs/pbd/pbd/sequence_property.h b/libs/pbd/pbd/sequence_property.h
index 28775b5f3c..e105e82e47 100644
--- a/libs/pbd/pbd/sequence_property.h
+++ b/libs/pbd/pbd/sequence_property.h
@@ -44,7 +44,7 @@ namespace PBD {
* any change.
*/
template<typename Container>
-class LIBPBD_API SequenceProperty : public PropertyBase
+class /*LIBPBD_API*/ SequenceProperty : public PropertyBase
{
public:
typedef std::set<typename Container::value_type> ChangeContainer;
@@ -95,14 +95,14 @@ class LIBPBD_API SequenceProperty : public PropertyBase
/* record the change described in our change member */
if (!_changes.added.empty()) {
- for (typename ChangeContainer::iterator i = _changes.added.begin(); i != _changes.added.end(); ++i) {
+ for (typename ChangeContainer::const_iterator i = _changes.added.begin(); i != _changes.added.end(); ++i) {
XMLNode* add_node = new XMLNode ("Add");
child->add_child_nocopy (*add_node);
get_content_as_xml (*i, *add_node);
}
}
if (!_changes.removed.empty()) {
- for (typename ChangeContainer::iterator i = _changes.removed.begin(); i != _changes.removed.end(); ++i) {
+ for (typename ChangeContainer::const_iterator i = _changes.removed.begin(); i != _changes.removed.end(); ++i) {
XMLNode* remove_node = new XMLNode ("Remove");
child->add_child_nocopy (*remove_node);
get_content_as_xml (*i, *remove_node);
@@ -171,7 +171,7 @@ class LIBPBD_API SequenceProperty : public PropertyBase
with this diff().
*/
- for (typename ChangeContainer::iterator i = a->changes().added.begin(); i != a->changes().added.end(); ++i) {
+ for (typename ChangeContainer::const_iterator i = a->changes().added.begin(); i != a->changes().added.end(); ++i) {
(*i)->DropReferences.connect_same_thread (*cmd, boost::bind (&Destructible::drop_references, cmd));
}
}
@@ -311,10 +311,10 @@ class LIBPBD_API SequenceProperty : public PropertyBase
}
Container& operator= (const Container& other) {
- for (typename Container::iterator i = _val.begin(); i != _val.end(); ++i) {
+ for (typename Container::const_iterator i = _val.begin(); i != _val.end(); ++i) {
_changes.remove (*i);
}
- for (typename Container::iterator i = other.begin(); i != other.end(); ++i) {
+ for (typename Container::const_iterator i = other.begin(); i != other.end(); ++i) {
_changes.add (*i);
}
return _val = other;
diff --git a/libs/pbd/pbd/signals.h b/libs/pbd/pbd/signals.h
index 3896fd55b5..672dc66850 100644
--- a/libs/pbd/pbd/signals.h
+++ b/libs/pbd/pbd/signals.h
@@ -79,7 +79,7 @@ private:
};
template<typename R>
-class LIBPBD_API OptionalLastValue
+class /*LIBPBD_API*/ OptionalLastValue
{
public:
typedef boost::optional<R> result_type;
diff --git a/libs/pbd/pbd/stacktrace.h b/libs/pbd/pbd/stacktrace.h
index fbb92c8fa0..c5d9743b1e 100644
--- a/libs/pbd/pbd/stacktrace.h
+++ b/libs/pbd/pbd/stacktrace.h
@@ -44,7 +44,7 @@ namespace PBD {
LIBPBD_API std::string demangle (const std::string&);
template<typename T>
-class LIBPBD_API thing_with_backtrace
+class /*LIBPBD_API*/ thing_with_backtrace
{
public:
thing_with_backtrace () {
@@ -113,11 +113,11 @@ private:
static Glib::Threads::Mutex all_mutex;
};
-template<typename T> LIBPBD_API std::list<PBD::thing_with_backtrace<T> *> PBD::thing_with_backtrace<T>::all;
-template<typename T> LIBPBD_API Glib::Threads::Mutex PBD::thing_with_backtrace<T>::all_mutex;
+template<typename T> /*LIBPBD_API*/ std::list<PBD::thing_with_backtrace<T> *> PBD::thing_with_backtrace<T>::all;
+template<typename T> /*LIBPBD_API*/ Glib::Threads::Mutex PBD::thing_with_backtrace<T>::all_mutex;
} // namespace PBD
-
+// JE - !!!!#include "../pbd/stacktrace.impl"
#endif /* __libpbd_stacktrace_h__ */
diff --git a/libs/pbd/pbd/stl_delete.h b/libs/pbd/pbd/stl_delete.h
index b98bb5e8e3..1598a90e2c 100644
--- a/libs/pbd/pbd/stl_delete.h
+++ b/libs/pbd/pbd/stl_delete.h
@@ -26,7 +26,7 @@
first include the revelant container type header.
*/
#if defined(_CPP_VECTOR) || defined(_GLIBCXX_VECTOR) || defined(__SGI_STL_VECTOR) || defined(_LIBCPP_VECTOR)
-template<class T> LIBPBD_API void vector_delete (std::vector<T *> *vec)
+template<class T> /*LIBPBD_API*/ void vector_delete (std::vector<T *> *vec)
{
typename std::vector<T *>::iterator i;
@@ -38,7 +38,7 @@ template<class T> LIBPBD_API void vector_delete (std::vector<T *> *vec)
#endif // _CPP_VECTOR || _GLIBCXX_VECTOR || __SGI_STL_VECTOR || _LIBCPP_VECTOR
#if defined(_CPP_MAP) || defined(_GLIBCXX_MAP) || defined(__SGI_STL_MAP)
-template<class K, class T> LIBPBD_API void map_delete (std::map<K, T *> *m)
+template<class K, class T> /*LIBPBD_API*/ void map_delete (std::map<K, T *> *m)
{
typename std::map<K, T *>::iterator i;
@@ -50,7 +50,7 @@ template<class K, class T> LIBPBD_API void map_delete (std::map<K, T *> *m)
#endif // _CPP_MAP || _GLIBCXX_MAP || __SGI_STL_MAP
#if defined(_CPP_LIST) || defined(_GLIBCXX_LIST) || defined(__SGI_STL_LIST)
-template<class T> LIBPBD_API void list_delete (std::list<T *> *l)
+template<class T> /*LIBPBD_API*/ void list_delete (std::list<T *> *l)
{
typename std::list<T *>::iterator i;
@@ -63,7 +63,7 @@ template<class T> LIBPBD_API void list_delete (std::list<T *> *l)
#endif // _CPP_LIST || _GLIBCXX_LIST || __SGI_STL_LIST
#if defined(_CPP_SLIST) || defined(_GLIBCXX_SLIST) || defined(__SGI_STL_SLIST)
-template<class T> LIBPBD_API void slist_delete (std::slist<T *> *l)
+template<class T> /*LIBPBD_API*/ void slist_delete (std::slist<T *> *l)
{
typename std::slist<T *>::iterator i;
@@ -76,7 +76,7 @@ template<class T> LIBPBD_API void slist_delete (std::slist<T *> *l)
#endif // _CPP_SLIST || _GLIBCXX_SLIST || __SGI_STL_SLIST
#if defined(_CPP_SET) || defined(_GLIBCXX_SET) || defined(__SGI_STL_SET)
-template<class T> void LIBPBD_API set_delete (std::set<T *> *sset)
+template<class T> void /*LIBPBD_API*/ set_delete (std::set<T *> *sset)
{
typename std::set<T *>::iterator i;
diff --git a/libs/pbd/pbd/timersub.h b/libs/pbd/pbd/timersub.h
new file mode 100644
index 0000000000..6cb152414c
--- /dev/null
+++ b/libs/pbd/pbd/timersub.h
@@ -0,0 +1,32 @@
+/* Copyright (C) 1991-1994,1996-2003,2005,2006,2009
+ Free Software Foundation, Inc.
+
+ The GNU C 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.
+
+ The GNU C Library 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 the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <sys/time.h>
+
+#ifndef timersub
+# define timersub(a, b, result) \
+ do { \
+ (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
+ (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
+ if ((result)->tv_usec < 0) { \
+ --(result)->tv_sec; \
+ (result)->tv_usec += 1000000; \
+ } \
+ } while (0)
+#endif
+
diff --git a/libs/pbd/pbd/tokenizer.h b/libs/pbd/pbd/tokenizer.h
index b4b3b107c0..3253473519 100644
--- a/libs/pbd/pbd/tokenizer.h
+++ b/libs/pbd/pbd/tokenizer.h
@@ -37,7 +37,7 @@ namespace PBD {
are discarded.
*/
template<typename StringType, typename Iter>
-LIBPBD_API unsigned int
+/*LIBPBD_API*/ unsigned int
tokenize(const StringType& str,
const StringType& delims,
Iter it,
diff --git a/libs/pbd/pbd/touchable.h b/libs/pbd/pbd/touchable.h
index ed7d75df52..297be8b0f1 100644
--- a/libs/pbd/pbd/touchable.h
+++ b/libs/pbd/pbd/touchable.h
@@ -21,7 +21,7 @@
#include "pbd/libpbd_visibility.h"
-class LIBPBD_API Touchable
+class /*LIBPBD_API*/ Touchable
{
public:
Touchable() : _delete_after_touch (false) {}
@@ -37,7 +37,7 @@ class LIBPBD_API Touchable
};
template<class T>
-class LIBPBD_API DynamicTouchable : public Touchable
+class /*LIBPBD_API*/ DynamicTouchable : public Touchable
{
public:
DynamicTouchable (T& t, void (T::*m)(void))
@@ -53,7 +53,7 @@ class LIBPBD_API DynamicTouchable : public Touchable
};
template<class T1, class T2>
-class LIBPBD_API DynamicTouchable1 : public Touchable
+class /*LIBPBD_API*/ DynamicTouchable1 : public Touchable
{
public:
DynamicTouchable1 (T1& t, void (T1::*m)(T2), T2 a)
@@ -70,7 +70,7 @@ class LIBPBD_API DynamicTouchable1 : public Touchable
};
template<class T1, class T2, class T3>
-class LIBPBD_API DynamicTouchable2 : public Touchable
+class /*LIBPBD_API*/ DynamicTouchable2 : public Touchable
{
public:
DynamicTouchable2 (T1& t, void (T1::*m)(T2, T3), T2 a1, T3 a2)
diff --git a/libs/pbd/pbd/undo.h b/libs/pbd/pbd/undo.h
index 753bc13b15..794e68ce97 100644
--- a/libs/pbd/pbd/undo.h
+++ b/libs/pbd/pbd/undo.h
@@ -25,7 +25,11 @@
#include <map>
#include <sigc++/slot.h>
#include <sigc++/bind.h>
+#ifndef COMPILER_MSVC
#include <sys/time.h>
+#else
+#include <ardourext/misc.h>
+#endif
#include "pbd/libpbd_visibility.h"
#include "pbd/command.h"
diff --git a/libs/pbd/pbd/unknown_type.h b/libs/pbd/pbd/unknown_type.h
index 4d984269a7..ef9db1ac43 100644
--- a/libs/pbd/pbd/unknown_type.h
+++ b/libs/pbd/pbd/unknown_type.h
@@ -22,9 +22,9 @@
#include <exception>
-#include "pbd/libpbd_visibility.h"
+//#include "pbd/libpbd_visibility.h"
-class LIBPBD_API unknown_type : public std::exception {
+class /*LIBPBD_API*/ unknown_type : public std::exception {
public:
virtual const char *what() const throw() { return "unknown type"; }
};
diff --git a/libs/pbd/pbd/unwind.h b/libs/pbd/pbd/unwind.h
index cf7998fdd4..5a0fe26559 100644
--- a/libs/pbd/pbd/unwind.h
+++ b/libs/pbd/pbd/unwind.h
@@ -25,7 +25,7 @@
namespace PBD {
template <typename T>
-class LIBPBD_API Unwinder {
+class /*LIBPBD_API*/ Unwinder {
public:
Unwinder (T& var, T new_val) : _var (var), _old_val (var) { var = new_val; }
~Unwinder () { _var = _old_val; }
diff --git a/libs/pbd/pbd/uuid.h b/libs/pbd/pbd/uuid.h
index 333a902b4d..77e84c5f09 100644
--- a/libs/pbd/pbd/uuid.h
+++ b/libs/pbd/pbd/uuid.h
@@ -22,31 +22,37 @@
#define __pbd_uuid_h__
#include <string>
-#include <uuid/uuid.h>
+#include <boost/uuid/uuid.hpp>
+#include <boost/uuid/uuid_generators.hpp>
#include "pbd/libpbd_visibility.h"
namespace PBD {
-class LIBPBD_API UUID {
+class LIBPBD_API UUID : public boost::uuids::uuid {
public:
- UUID () { uuid_generate (id); }
- UUID (UUID const & other) { uuid_copy (id, other.id); }
- UUID (std::string const & str) { uuid_parse (str.c_str(), id); }
-
- UUID& operator= (std::string const & str);
- std::string to_s () const;
-
- bool operator== (UUID const & other) const { return !uuid_compare (id, other.id); }
- bool operator!= (UUID const & other) const { return uuid_compare (id, other.id); }
- bool operator< (UUID const & other) const { return uuid_compare (id, other.id) < 0; }
-
- operator bool() const { return !uuid_is_null (id); }
-
- private:
- uuid_t id;
+ UUID ()
+ : boost::uuids::uuid (boost::uuids::random_generator()()) {}
+ UUID (std::string const & str)
+ : boost::uuids::uuid (boost::uuids::string_generator()(str)) {}
+ explicit UUID (boost::uuids::uuid const& u)
+ : boost::uuids::uuid(u)
+ {}
+
+ operator boost::uuids::uuid() {
+ return static_cast<boost::uuids::uuid&>(*this);
+ }
+
+ operator boost::uuids::uuid() const {
+ return static_cast<boost::uuids::uuid const&>(*this);
+ }
+
+ UUID& operator= (std::string const & str);
+ std::string to_s () const;
+
+ operator bool() const { return !is_nil(); }
};
} // namespace PBD
diff --git a/libs/pbd/pool.cc b/libs/pbd/pool.cc
index 7b24625727..cdcd9abdd7 100644
--- a/libs/pbd/pool.cc
+++ b/libs/pbd/pool.cc
@@ -24,6 +24,7 @@
#include <cassert>
#include "pbd/pool.h"
+#include "pbd/pthread_utils.h"
#include "pbd/error.h"
#include "pbd/debug.h"
#include "pbd/compose.h"
@@ -182,7 +183,7 @@ PerThreadPool::per_thread_pool ()
{
CrossThreadPool* p = _key.get();
if (!p) {
- fatal << "programming error: no per-thread pool \"" << _name << "\" for thread " << pthread_self() << endmsg;
+ fatal << "programming error: no per-thread pool \"" << _name << "\" for thread " << pthread_name() << endmsg;
/*NOTREACHED*/
}
return p;
@@ -226,9 +227,9 @@ CrossThreadPool::alloc ()
{
void* ptr;
- DEBUG_TRACE (DEBUG::Pool, string_compose ("%1 %2 has %3 pending free entries waiting\n", pthread_self(), name(), pending.read_space()));
+ DEBUG_TRACE (DEBUG::Pool, string_compose ("%1 %2 has %3 pending free entries waiting\n", pthread_name(), name(), pending.read_space()));
while (pending.read (&ptr, 1) == 1) {
- DEBUG_TRACE (DEBUG::Pool, string_compose ("%1 %2 pushes back a pending free list entry before allocating\n", pthread_self(), name()));
+ DEBUG_TRACE (DEBUG::Pool, string_compose ("%1 %2 pushes back a pending free list entry before allocating\n", pthread_name(), name()));
free_list.write (&ptr, 1);
}
return Pool::alloc ();
diff --git a/libs/pbd/pthread_utils.cc b/libs/pbd/pthread_utils.cc
index 3d3cb96fb5..b8ca8fc093 100644
--- a/libs/pbd/pthread_utils.cc
+++ b/libs/pbd/pthread_utils.cc
@@ -28,9 +28,17 @@
#include <fst.h>
#endif
+#ifdef COMPILER_MSVC
+DECLARE_DEFAULT_COMPARISONS(pthread_t) // Needed for 'DECLARE_DEFAULT_COMPARISONS'. Objects in an STL container can be
+ // searched and sorted. Thus, when instantiating the container, MSVC complains
+ // if the type of object being contained has no appropriate comparison operators
+ // defined (specifically, if operators '<' and '==' are undefined). This seems
+ // to be the case with ptw32 'pthread_t' which is a simple struct.
+#endif
+
using namespace std;
-typedef std::set<pthread_t> ThreadMap;
+typedef std::list<pthread_t> ThreadMap;
static ThreadMap all_threads;
static pthread_mutex_t thread_map_lock = PTHREAD_MUTEX_INITIALIZER;
static Glib::Threads::Private<char> thread_name (free);
@@ -116,7 +124,7 @@ pthread_create_and_store (string name, pthread_t *thread, void * (*start_routin
if ((ret = thread_creator (thread, &default_attr, fake_thread_start, ts)) == 0) {
pthread_mutex_lock (&thread_map_lock);
- all_threads.insert (*thread);
+ all_threads.push_back (*thread);
pthread_mutex_unlock (&thread_map_lock);
}
@@ -149,7 +157,7 @@ pthread_kill_all (int signum)
{
pthread_mutex_lock (&thread_map_lock);
for (ThreadMap::iterator i = all_threads.begin(); i != all_threads.end(); ++i) {
- if ((*i) != pthread_self()) {
+ if (!pthread_equal ((*i), pthread_self())) {
pthread_kill ((*i), signum);
}
}
@@ -161,6 +169,7 @@ void
pthread_cancel_all ()
{
pthread_mutex_lock (&thread_map_lock);
+
for (ThreadMap::iterator i = all_threads.begin(); i != all_threads.end(); ) {
ThreadMap::iterator nxt = i;
diff --git a/libs/pbd/resource.cc b/libs/pbd/resource.cc
new file mode 100644
index 0000000000..9d6f8b1746
--- /dev/null
+++ b/libs/pbd/resource.cc
@@ -0,0 +1,77 @@
+/*
+ Copyright (C) 2011 Tim Mayberry
+
+ 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.
+
+*/
+
+#ifdef PLATFORM_WINDOWS
+#include <stdio.h>
+#else
+#include <sys/time.h>
+#include <sys/resource.h>
+#endif
+
+#include "pbd/resource.h"
+
+namespace PBD {
+
+bool
+get_resource_limit (ResourceType resource, ResourceLimit& limit)
+{
+ if (resource == OpenFiles)
+ {
+#ifdef PLATFORM_WINDOWS
+ limit.current_limit = _getmaxstdio();
+ limit.max_limit = 2048;
+ return true;
+#else
+ struct rlimit rl;
+ if (getrlimit (RLIMIT_NOFILE, &rl) == 0) {
+ limit.current_limit = rl.rlim_cur;
+ limit.max_limit = rl.rlim_max;
+ return true;
+ }
+#endif
+ }
+
+ return false;
+}
+
+bool
+set_resource_limit (ResourceType resource, const ResourceLimit& limit)
+{
+ if (resource == OpenFiles)
+ {
+#ifdef PLATFORM_WINDOWS
+ // no soft and hard limits on windows
+ rlimit_t new_max = _setmaxstdio(limit.current_limit);
+
+ if (new_max == limit.current_limit) return true;
+#else
+ struct rlimit rl;
+ rl.rlim_cur = limit.current_limit;
+ rl.rlim_max = limit.max_limit;
+ if (setrlimit (RLIMIT_NOFILE, &rl) == 0) {
+ return true;
+ }
+
+#endif
+ }
+
+ return false;
+}
+
+} // namespace PBD
diff --git a/libs/pbd/search_path.cc b/libs/pbd/search_path.cc
index 3f7be5aa56..ea08785f68 100644
--- a/libs/pbd/search_path.cc
+++ b/libs/pbd/search_path.cc
@@ -27,7 +27,7 @@ using namespace std;
namespace {
-#ifdef WIN32
+#ifdef PLATFORM_WINDOWS
const char * const path_delimiter = ";";
#else
const char * const path_delimiter = ":";
@@ -37,12 +37,12 @@ const char * const path_delimiter = ":";
namespace PBD {
-SearchPath::SearchPath ()
+Searchpath::Searchpath ()
{
}
-SearchPath::SearchPath (const string& path)
+Searchpath::Searchpath (const string& path)
{
vector<std::string> tmp;
@@ -51,13 +51,13 @@ SearchPath::SearchPath (const string& path)
}
}
-SearchPath::SearchPath (const vector<std::string>& paths)
+Searchpath::Searchpath (const vector<std::string>& paths)
{
add_directories (paths);
}
void
-SearchPath::add_directory (const std::string& directory_path)
+Searchpath::add_directory (const std::string& directory_path)
{
if (!directory_path.empty()) {
push_back(directory_path);
@@ -65,7 +65,7 @@ SearchPath::add_directory (const std::string& directory_path)
}
void
-SearchPath::add_directories (const vector<std::string>& paths)
+Searchpath::add_directories (const vector<std::string>& paths)
{
for(vector<std::string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
add_directory (*i);
@@ -73,7 +73,7 @@ SearchPath::add_directories (const vector<std::string>& paths)
}
const string
-SearchPath::to_string () const
+Searchpath::to_string () const
{
string path;
@@ -87,37 +87,37 @@ SearchPath::to_string () const
return path;
}
-SearchPath&
-SearchPath::operator+= (const SearchPath& spath)
+Searchpath&
+Searchpath::operator+= (const Searchpath& spath)
{
insert(end(), spath.begin(), spath.end());
return *this;
}
-SearchPath&
-SearchPath::operator+= (const std::string& directory_path)
+Searchpath&
+Searchpath::operator+= (const std::string& directory_path)
{
add_directory (directory_path);
return *this;
}
-SearchPath&
-SearchPath::operator+ (const std::string& directory_path)
+Searchpath&
+Searchpath::operator+ (const std::string& directory_path)
{
add_directory (directory_path);
return *this;
}
-SearchPath&
-SearchPath::operator+ (const SearchPath& spath)
+Searchpath&
+Searchpath::operator+ (const Searchpath& spath)
{
- // concatenate paths into new SearchPath
+ // concatenate paths into new Searchpath
insert(end(), spath.begin(), spath.end());
return *this;
}
-SearchPath&
-SearchPath::add_subdirectory_to_paths (const string& subdir)
+Searchpath&
+Searchpath::add_subdirectory_to_paths (const string& subdir)
{
for (vector<std::string>::iterator i = begin(); i != end(); ++i) {
// should these new paths just be added to the end of
diff --git a/libs/pbd/semutils.cc b/libs/pbd/semutils.cc
index 48fdd249f6..cf7b54d30e 100644
--- a/libs/pbd/semutils.cc
+++ b/libs/pbd/semutils.cc
@@ -23,7 +23,12 @@ using namespace PBD;
ProcessSemaphore::ProcessSemaphore (const char* name, int val)
{
-#ifdef __APPLE__
+#ifdef PLATFORM_WINDOWS
+ if ((_sem = CreateSemaphore(NULL, val, 32767, name)) == NULL) {
+ throw failed_constructor ();
+ }
+
+#elif __APPLE__
if ((_sem = sem_open (name, O_CREAT, 0600, val)) == (sem_t*) SEM_FAILED) {
throw failed_constructor ();
}
@@ -45,7 +50,28 @@ ProcessSemaphore::ProcessSemaphore (const char* name, int val)
ProcessSemaphore::~ProcessSemaphore ()
{
-#ifdef __APPLE__
+#ifdef PLATFORM_WINDOWS
+ CloseHandle(_sem);
+#elif __APPLE__
sem_close (ptr_to_sem());
#endif
}
+
+#ifdef PLATFORM_WINDOWS
+
+int
+ProcessSemaphore::signal ()
+{
+ // non-zero on success, opposite to posix
+ return !ReleaseSemaphore(_sem, 1, NULL);
+}
+
+int
+ProcessSemaphore::wait ()
+{
+ DWORD result = 0;
+ result = WaitForSingleObject(_sem, INFINITE);
+ return (result == WAIT_OBJECT_0);
+}
+
+#endif
diff --git a/libs/pbd/sndfile_manager.cc b/libs/pbd/sndfile_manager.cc
index d1dcd05256..c028bc11ba 100644
--- a/libs/pbd/sndfile_manager.cc
+++ b/libs/pbd/sndfile_manager.cc
@@ -22,7 +22,6 @@
*/
#include <sys/time.h>
-#include <sys/resource.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
diff --git a/libs/pbd/stacktrace.cc b/libs/pbd/stacktrace.cc
index 0177b8c9e8..c74dd946f7 100644
--- a/libs/pbd/stacktrace.cc
+++ b/libs/pbd/stacktrace.cc
@@ -22,6 +22,7 @@
#include "pbd/stacktrace.h"
#include <cstdio>
#include <iostream>
+#include <string>
void
PBD::trace_twb ()
@@ -105,7 +106,7 @@ PBD::stacktrace (std::ostream& out, int levels)
#else
std::string
-PBD::demangle (std::string const & l)
+PBD::demangle (std::string const & l) /* JE - !!!! 'PBD' namespace might possibly get removed (except it's still used in 'libs/canvas/item.cc') */
{
return std::string();
}
diff --git a/libs/pbd/stateful.cc b/libs/pbd/stateful.cc
index 105af75861..c4077f60af 100644
--- a/libs/pbd/stateful.cc
+++ b/libs/pbd/stateful.cc
@@ -18,7 +18,11 @@
$Id: stateful.cc 629 2006-06-21 23:01:03Z paul $
*/
+#ifdef COMPILER_MSVC
+#include <io.h> // Microsoft's nearest equivalent to <unistd.h>
+#else
#include <unistd.h>
+#endif
#include <glibmm/fileutils.h>
#include <glibmm/miscutils.h>
diff --git a/libs/pbd/test/filesystem_test.cc b/libs/pbd/test/filesystem_test.cc
index ce2faadc82..458105d177 100644
--- a/libs/pbd/test/filesystem_test.cc
+++ b/libs/pbd/test/filesystem_test.cc
@@ -10,6 +10,7 @@ CPPUNIT_TEST_SUITE_REGISTRATION (FilesystemTest);
void
FilesystemTest::testPathIsWithin ()
{
+#ifndef PLATFORM_WINDOWS
system ("rm -r foo");
CPPUNIT_ASSERT (g_mkdir_with_parents ("foo/bar/baz", 0755) == 0);
@@ -31,5 +32,6 @@ FilesystemTest::testPathIsWithin ()
CPPUNIT_ASSERT (PBD::path_is_within ("foo/bar", "foo/bar"));
CPPUNIT_ASSERT (PBD::path_is_within ("foo/jim/baz", "frobozz") == false);
+#endif
}
diff --git a/libs/pbd/test/mutex_test.cc b/libs/pbd/test/mutex_test.cc
new file mode 100644
index 0000000000..52c36c4695
--- /dev/null
+++ b/libs/pbd/test/mutex_test.cc
@@ -0,0 +1,24 @@
+#include "mutex_test.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION (MutexTest);
+
+using namespace std;
+
+MutexTest::MutexTest ()
+{
+}
+
+void
+MutexTest::testBasic ()
+{
+ Glib::Threads::Mutex::Lock lm (m_mutex);
+
+ CPPUNIT_ASSERT (lm.locked());
+
+ /* This will fail on POSIX systems but not on some older versions of glib
+ * on win32 as TryEnterCriticalSection is used and it will return true
+ * as CriticalSection is reentrant and fail the assertion.
+ */
+ CPPUNIT_ASSERT (!m_mutex.trylock());
+
+}
diff --git a/libs/pbd/test/mutex_test.h b/libs/pbd/test/mutex_test.h
new file mode 100644
index 0000000000..95b6ea3f65
--- /dev/null
+++ b/libs/pbd/test/mutex_test.h
@@ -0,0 +1,17 @@
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "glibmm/threads.h"
+
+class MutexTest : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE (MutexTest);
+ CPPUNIT_TEST (testBasic);
+ CPPUNIT_TEST_SUITE_END ();
+
+public:
+ MutexTest ();
+ void testBasic ();
+
+private:
+ Glib::Threads::Mutex m_mutex;
+};
diff --git a/libs/pbd/test/test_common.cc b/libs/pbd/test/test_common.cc
index 16da3ed2a8..6e099d2f3e 100644
--- a/libs/pbd/test/test_common.cc
+++ b/libs/pbd/test/test_common.cc
@@ -25,10 +25,10 @@
* in an installed location on windows or by setting an environment variable
* on unix.
*/
-PBD::SearchPath
+PBD::Searchpath
test_search_path ()
{
-#ifdef WIN32
+#ifdef PLATFORM_WINDOWS
std::string wsp(g_win32_get_package_installation_directory_of_module(NULL));
return Glib::build_filename (wsp, "pbd_testdata");
#else
diff --git a/libs/pbd/test/test_common.h b/libs/pbd/test/test_common.h
index 0dc62f61dc..825c01fecb 100644
--- a/libs/pbd/test/test_common.h
+++ b/libs/pbd/test/test_common.h
@@ -21,6 +21,6 @@
#include "pbd/search_path.h"
-PBD::SearchPath test_search_path ();
+PBD::Searchpath test_search_path ();
#endif
diff --git a/libs/pbd/test/testrunner.cc b/libs/pbd/test/testrunner.cc
index 1512ebd024..ea8f0aa115 100644
--- a/libs/pbd/test/testrunner.cc
+++ b/libs/pbd/test/testrunner.cc
@@ -4,11 +4,15 @@
#include <cppunit/TestResultCollector.h>
#include <cppunit/TestRunner.h>
#include <cppunit/BriefTestProgressListener.h>
+#include <glibmm/thread.h>
#include "scalar_properties.h"
+
int
main ()
{
+ Glib::thread_init();
+
ScalarPropertiesTest::make_property_quarks ();
CppUnit::TestResult testresult;
diff --git a/libs/pbd/transmitter.cc b/libs/pbd/transmitter.cc
index aa5c75da19..e4266d34d7 100644
--- a/libs/pbd/transmitter.cc
+++ b/libs/pbd/transmitter.cc
@@ -84,12 +84,20 @@ Transmitter::deliver ()
/* do the right thing if this should not return */
if (does_not_return()) {
+#ifndef PLATFORM_WINDOWS
+// TODO !!!! Commented out temporarily (for Windows)
sigset_t mask;
sigemptyset (&mask);
sigsuspend (&mask);
/*NOTREACHED*/
exit (1);
+/* JE - From what I can tell, the above code suspends
+ * program execution until (any) signal occurs. Not
+ * sure at the moment what this achieves, unless it
+ * provides some time for the user to see the message.
+ */
+#endif
}
}
diff --git a/libs/pbd/uuid.cc b/libs/pbd/uuid.cc
index 0ffeca23cb..8b55ab3381 100644
--- a/libs/pbd/uuid.cc
+++ b/libs/pbd/uuid.cc
@@ -20,19 +20,16 @@
#include "pbd/uuid.h"
-using namespace PBD;
-
-UUID&
-UUID::operator= (std::string const & str)
+PBD::UUID&
+PBD::UUID::operator= (std::string const & str)
{
- uuid_parse (str.c_str(), id);
+ boost::uuids::string_generator gen;
+ *((boost::uuids::uuid*) this) = gen (str);
return *this;
}
std::string
-UUID::to_s () const
+PBD::UUID::to_s () const
{
- char buf[37];
- uuid_unparse (id, buf);
- return std::string (buf);
+ return std::string ((const char*) data, size());
}
diff --git a/libs/pbd/wscript b/libs/pbd/wscript
index 09af0f614b..d721a78675 100644
--- a/libs/pbd/wscript
+++ b/libs/pbd/wscript
@@ -38,7 +38,6 @@ libpbd_sources = [
'controllable.cc',
'controllable_descriptor.cc',
'clear_dir.cc',
- 'crossthread.cc',
'cpus.cc',
'debug.cc',
'enumwriter.cc',
@@ -46,11 +45,14 @@ libpbd_sources = [
'enums.cc',
'epa.cc',
'error.cc',
+ 'ffs.cc',
'file_manager.cc',
'file_utils.cc',
'fpu.cc',
+ 'glib_semaphore.cc',
'id.cc',
'locale_guard.cc',
+ 'localtime_r.cc',
'malign.cc',
'mountpoint.cc',
'openuri.cc',
@@ -61,6 +63,7 @@ libpbd_sources = [
'property_list.cc',
'pthread_utils.cc',
'receiver.cc',
+ 'resource.cc',
'search_path.cc',
'semutils.cc',
'shortpath.cc',
@@ -90,20 +93,18 @@ def configure(conf):
autowaf.configure(conf)
autowaf.check_pkg(conf, 'libxml-2.0', uselib_store='XML')
autowaf.check_pkg(conf, 'sigc++-2.0', uselib_store='SIGCPP', atleast_version='2.0')
- if sys.platform != 'darwin':
- autowaf.check_pkg(conf, 'uuid', uselib_store='UUID')
conf.check(function_name='getmntent', header_name='mntent.h', define_name='HAVE_GETMNTENT',mandatory=False)
conf.check(header_name='execinfo.h', define_name='HAVE_EXECINFO',mandatory=False)
conf.check(header_name='unistd.h', define_name='HAVE_UNISTD',mandatory=False)
conf.check_cc(function_name='posix_memalign', header_name='stdlib.h', cflags='-D_XOPEN_SOURCE=600', define_name='HAVE_POSIX_MEMALIGN', mandatory=False)
+ conf.check(function_name='localtime_r', header_name='time.h', define_name='HAVE_LOCALTIME_R',mandatory=False)
conf.write_config_header('libpbd-config.h', remove=False)
# Boost headers
autowaf.check_header(conf, 'cxx', 'boost/shared_ptr.hpp')
autowaf.check_header(conf, 'cxx', 'boost/weak_ptr.hpp')
- # autowaf.check_header(conf, 'cxx', 'boost/uuid/uuid.hpp')
def build(bld):
@@ -127,6 +128,9 @@ def build(bld):
if bld.is_defined('DEBUG_RT_ALLOC'):
obj.source += 'debug_rt_alloc.c'
+ if bld.env['build_target'] != 'mingw':
+ obj.source += [ 'crossthread.cc' ]
+
obj.export_includes = ['.']
obj.includes = ['.']
obj.name = 'libpbd'
@@ -150,6 +154,7 @@ def build(bld):
testobj.source = '''
test/testrunner.cc
test/xpath.cc
+ test/mutex_test.cc
test/scalar_properties.cc
test/signals_test.cc
test/convert_test.cc
@@ -161,7 +166,7 @@ def build(bld):
testobj.uselib = 'CPPUNIT XML SNDFILE'
testobj.use = 'libpbd'
testobj.name = 'libpbd-tests'
- if sys.platform != 'darwin':
+ if sys.platform != 'darwin' and bld.env['build_target'] != 'mingw':
testobj.linkflags = ['-lrt']
diff --git a/libs/pbd/xml++.cc b/libs/pbd/xml++.cc
index a1fa77db66..69187995a1 100644
--- a/libs/pbd/xml++.cc
+++ b/libs/pbd/xml++.cc
@@ -167,6 +167,7 @@ XMLTree::write() const
void
XMLTree::debug(FILE* out) const
{
+#ifdef LIBXML_DEBUG_ENABLED
xmlDocPtr doc;
XMLNodeList children;
@@ -176,6 +177,7 @@ XMLTree::debug(FILE* out) const
writenode(doc, _root, doc->children, 1);
xmlDebugDumpDocument (out, doc);
xmlFreeDoc(doc);
+#endif
}
const string&