aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/expat/ExpatParser.cxx2
-rw-r--r--src/lib/expat/ExpatParser.hxx5
-rw-r--r--src/lib/ffmpeg/Buffer.hxx73
-rw-r--r--src/lib/ffmpeg/Domain.cxx2
-rw-r--r--src/lib/ffmpeg/Domain.hxx2
-rw-r--r--src/lib/ffmpeg/Error.cxx2
-rw-r--r--src/lib/ffmpeg/Error.hxx2
-rw-r--r--src/lib/ffmpeg/Init.cxx38
-rw-r--r--src/lib/ffmpeg/Init.hxx26
-rw-r--r--src/lib/ffmpeg/LogCallback.cxx66
-rw-r--r--src/lib/ffmpeg/LogCallback.hxx30
-rw-r--r--src/lib/ffmpeg/LogError.cxx45
-rw-r--r--src/lib/ffmpeg/LogError.hxx29
-rw-r--r--src/lib/ffmpeg/Time.hxx110
-rw-r--r--src/lib/icu/Collate.cxx151
-rw-r--r--src/lib/icu/Collate.hxx5
-rw-r--r--src/lib/icu/Converter.cxx163
-rw-r--r--src/lib/icu/Converter.hxx97
-rw-r--r--src/lib/icu/Error.cxx2
-rw-r--r--src/lib/icu/Error.hxx2
-rw-r--r--src/lib/icu/Init.cxx2
-rw-r--r--src/lib/icu/Init.hxx2
-rw-r--r--src/lib/icu/Util.cxx74
-rw-r--r--src/lib/icu/Util.hxx45
-rw-r--r--src/lib/icu/Win32.cxx60
-rw-r--r--src/lib/icu/Win32.hxx38
-rw-r--r--src/lib/nfs/Base.cxx2
-rw-r--r--src/lib/nfs/Base.hxx2
-rw-r--r--src/lib/nfs/Blocking.cxx2
-rw-r--r--src/lib/nfs/Blocking.hxx2
-rw-r--r--src/lib/nfs/Callback.hxx2
-rw-r--r--src/lib/nfs/Cancellable.hxx2
-rw-r--r--src/lib/nfs/Connection.cxx2
-rw-r--r--src/lib/nfs/Connection.hxx2
-rw-r--r--src/lib/nfs/Domain.cxx2
-rw-r--r--src/lib/nfs/Domain.hxx2
-rw-r--r--src/lib/nfs/FileReader.cxx2
-rw-r--r--src/lib/nfs/FileReader.hxx2
-rw-r--r--src/lib/nfs/Glue.cxx2
-rw-r--r--src/lib/nfs/Glue.hxx2
-rw-r--r--src/lib/nfs/Lease.hxx2
-rw-r--r--src/lib/nfs/Manager.cxx11
-rw-r--r--src/lib/nfs/Manager.hxx2
-rw-r--r--src/lib/pulse/Domain.cxx24
-rw-r--r--src/lib/pulse/Domain.hxx27
-rw-r--r--src/lib/pulse/Error.cxx33
-rw-r--r--src/lib/pulse/Error.hxx29
-rw-r--r--src/lib/pulse/LogError.cxx33
-rw-r--r--src/lib/pulse/LogError.hxx28
-rw-r--r--src/lib/smbclient/Domain.cxx2
-rw-r--r--src/lib/smbclient/Domain.hxx2
-rw-r--r--src/lib/smbclient/Init.cxx2
-rw-r--r--src/lib/smbclient/Init.hxx2
-rw-r--r--src/lib/smbclient/Mutex.cxx2
-rw-r--r--src/lib/smbclient/Mutex.hxx2
-rw-r--r--src/lib/sqlite/Domain.cxx24
-rw-r--r--src/lib/sqlite/Domain.hxx27
-rw-r--r--src/lib/sqlite/Util.hxx188
-rw-r--r--src/lib/upnp/Action.hxx2
-rw-r--r--src/lib/upnp/Callback.hxx2
-rw-r--r--src/lib/upnp/ClientInit.cxx2
-rw-r--r--src/lib/upnp/ClientInit.hxx2
-rw-r--r--src/lib/upnp/ContentDirectoryService.cxx2
-rw-r--r--src/lib/upnp/ContentDirectoryService.hxx5
-rw-r--r--src/lib/upnp/Device.cxx2
-rw-r--r--src/lib/upnp/Device.hxx2
-rw-r--r--src/lib/upnp/Discovery.cxx59
-rw-r--r--src/lib/upnp/Discovery.hxx29
-rw-r--r--src/lib/upnp/Domain.cxx2
-rw-r--r--src/lib/upnp/Domain.hxx2
-rw-r--r--src/lib/upnp/Init.cxx2
-rw-r--r--src/lib/upnp/Init.hxx2
-rw-r--r--src/lib/upnp/Util.cxx2
-rw-r--r--src/lib/upnp/Util.hxx2
-rw-r--r--src/lib/upnp/WorkQueue.hxx9
-rw-r--r--src/lib/zlib/Domain.cxx2
-rw-r--r--src/lib/zlib/Domain.hxx2
77 files changed, 1495 insertions, 178 deletions
diff --git a/src/lib/expat/ExpatParser.cxx b/src/lib/expat/ExpatParser.cxx
index c6b1abe76..7d9f1d587 100644
--- a/src/lib/expat/ExpatParser.cxx
+++ b/src/lib/expat/ExpatParser.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/expat/ExpatParser.hxx b/src/lib/expat/ExpatParser.hxx
index 9d2ac65e5..5f2626dda 100644
--- a/src/lib/expat/ExpatParser.hxx
+++ b/src/lib/expat/ExpatParser.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -41,6 +41,9 @@ public:
XML_ParserFree(parser);
}
+ ExpatParser(const ExpatParser &) = delete;
+ ExpatParser &operator=(const ExpatParser &) = delete;
+
void SetElementHandler(XML_StartElementHandler start,
XML_EndElementHandler end) {
XML_SetElementHandler(parser, start, end);
diff --git a/src/lib/ffmpeg/Buffer.hxx b/src/lib/ffmpeg/Buffer.hxx
new file mode 100644
index 000000000..2463ce197
--- /dev/null
+++ b/src/lib/ffmpeg/Buffer.hxx
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPD_FFMPEG_BUFFER_HXX
+#define MPD_FFMPEG_BUFFER_HXX
+
+extern "C" {
+#include <libavutil/mem.h>
+
+#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(52, 18, 0)
+#define HAVE_AV_FAST_MALLOC
+#else
+#include <libavcodec/avcodec.h>
+#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52, 25, 0)
+#define HAVE_AV_FAST_MALLOC
+#endif
+#endif
+}
+
+#include <stddef.h>
+
+/* suppress the ffmpeg compatibility macro */
+#ifdef SampleFormat
+#undef SampleFormat
+#endif
+
+class FfmpegBuffer {
+ void *data;
+ unsigned size;
+
+public:
+ FfmpegBuffer():data(nullptr), size(0) {}
+
+ ~FfmpegBuffer() {
+ av_free(data);
+ }
+
+ gcc_malloc
+ void *Get(size_t min_size) {
+#ifdef HAVE_AV_FAST_MALLOC
+ av_fast_malloc(&data, &size, min_size);
+#else
+ void *new_data = av_fast_realloc(data, &size, min_size);
+ if (new_data == nullptr)
+ return AVERROR(ENOMEM);
+ data = new_data;
+#endif
+ return data;
+ }
+
+ template<typename T>
+ T *GetT(size_t n) {
+ return (T *)Get(n * sizeof(T));
+ }
+};
+
+#endif
diff --git a/src/lib/ffmpeg/Domain.cxx b/src/lib/ffmpeg/Domain.cxx
index 78db30bae..08b3c6b43 100644
--- a/src/lib/ffmpeg/Domain.cxx
+++ b/src/lib/ffmpeg/Domain.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/ffmpeg/Domain.hxx b/src/lib/ffmpeg/Domain.hxx
index f21498a32..c6d82f800 100644
--- a/src/lib/ffmpeg/Domain.hxx
+++ b/src/lib/ffmpeg/Domain.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/ffmpeg/Error.cxx b/src/lib/ffmpeg/Error.cxx
index bcc12fb1d..53f4d65f5 100644
--- a/src/lib/ffmpeg/Error.cxx
+++ b/src/lib/ffmpeg/Error.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/ffmpeg/Error.hxx b/src/lib/ffmpeg/Error.hxx
index 943dca6ce..a92394b2c 100644
--- a/src/lib/ffmpeg/Error.hxx
+++ b/src/lib/ffmpeg/Error.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/ffmpeg/Init.cxx b/src/lib/ffmpeg/Init.cxx
new file mode 100644
index 000000000..44c641f89
--- /dev/null
+++ b/src/lib/ffmpeg/Init.cxx
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/* necessary because libavutil/common.h uses UINT64_C */
+#define __STDC_CONSTANT_MACROS
+
+#include "config.h"
+#include "Init.hxx"
+#include "LogCallback.hxx"
+
+extern "C" {
+#include <libavformat/avformat.h>
+}
+
+void
+FfmpegInit()
+{
+ av_log_set_callback(FfmpegLogCallback);
+
+ av_register_all();
+}
+
diff --git a/src/lib/ffmpeg/Init.hxx b/src/lib/ffmpeg/Init.hxx
new file mode 100644
index 000000000..ca5f9d691
--- /dev/null
+++ b/src/lib/ffmpeg/Init.hxx
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPD_FFMPEG_INIT_HXX
+#define MPD_FFMPEG_INIT_HXX
+
+void
+FfmpegInit();
+
+#endif
diff --git a/src/lib/ffmpeg/LogCallback.cxx b/src/lib/ffmpeg/LogCallback.cxx
new file mode 100644
index 000000000..ce2caeabb
--- /dev/null
+++ b/src/lib/ffmpeg/LogCallback.cxx
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/* necessary because libavutil/common.h uses UINT64_C */
+#define __STDC_CONSTANT_MACROS
+
+#include "config.h"
+#include "LogCallback.hxx"
+#include "Domain.hxx"
+#include "LogV.hxx"
+#include "util/Domain.hxx"
+
+extern "C" {
+#include <libavutil/log.h>
+}
+
+#include <stdio.h>
+
+gcc_const
+static LogLevel
+FfmpegImportLogLevel(int level)
+{
+ if (level <= AV_LOG_FATAL)
+ return LogLevel::ERROR;
+
+ if (level <= AV_LOG_WARNING)
+ return LogLevel::WARNING;
+
+ if (level <= AV_LOG_INFO)
+ return LogLevel::INFO;
+
+ return LogLevel::DEBUG;
+}
+
+void
+FfmpegLogCallback(gcc_unused void *ptr, int level, const char *fmt, va_list vl)
+{
+ const AVClass * cls = nullptr;
+
+ if (ptr != nullptr)
+ cls = *(const AVClass *const*)ptr;
+
+ if (cls != nullptr) {
+ char domain[64];
+ snprintf(domain, sizeof(domain), "%s/%s",
+ ffmpeg_domain.GetName(), cls->item_name(ptr));
+ const Domain d(domain);
+ LogFormatV(d, FfmpegImportLogLevel(level), fmt, vl);
+ }
+}
diff --git a/src/lib/ffmpeg/LogCallback.hxx b/src/lib/ffmpeg/LogCallback.hxx
new file mode 100644
index 000000000..f1b114366
--- /dev/null
+++ b/src/lib/ffmpeg/LogCallback.hxx
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPD_FFMPEG_LOG_CALLBACK_HXX
+#define MPD_FFMPEG_LOG_CALLBACK_HXX
+
+#include "check.h"
+
+#include <stdarg.h>
+
+void
+FfmpegLogCallback(void *ptr, int level, const char *fmt, va_list vl);
+
+#endif
diff --git a/src/lib/ffmpeg/LogError.cxx b/src/lib/ffmpeg/LogError.cxx
new file mode 100644
index 000000000..8a0675a1c
--- /dev/null
+++ b/src/lib/ffmpeg/LogError.cxx
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+#include "LogError.hxx"
+#include "Domain.hxx"
+#include "Log.hxx"
+
+#include <cstdint> /* needed due to libavutil bug */
+
+extern "C" {
+#include <libavutil/error.h>
+}
+
+void
+LogFfmpegError(int errnum)
+{
+ char msg[256];
+ av_strerror(errnum, msg, sizeof(msg));
+ LogError(ffmpeg_domain, msg);
+}
+
+void
+LogFfmpegError(int errnum, const char *prefix)
+{
+ char msg[256];
+ av_strerror(errnum, msg, sizeof(msg));
+ FormatError(ffmpeg_domain, "%s: %s", prefix, msg);
+}
diff --git a/src/lib/ffmpeg/LogError.hxx b/src/lib/ffmpeg/LogError.hxx
new file mode 100644
index 000000000..e6d96988d
--- /dev/null
+++ b/src/lib/ffmpeg/LogError.hxx
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPD_FFMPEG_LOG_ERROR_HXX
+#define MPD_FFMPEG_LOG_ERROR_HXX
+
+void
+LogFfmpegError(int errnum);
+
+void
+LogFfmpegError(int errnum, const char *prefix);
+
+#endif
diff --git a/src/lib/ffmpeg/Time.hxx b/src/lib/ffmpeg/Time.hxx
new file mode 100644
index 000000000..92c076d0d
--- /dev/null
+++ b/src/lib/ffmpeg/Time.hxx
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPD_FFMPEG_TIME_HXX
+#define MPD_FFMPEG_TIME_HXX
+
+#include "Chrono.hxx"
+#include "Compiler.h"
+
+extern "C" {
+#include <libavutil/avutil.h>
+#include <libavutil/mathematics.h>
+}
+
+#include <assert.h>
+#include <stdint.h>
+
+/* suppress the ffmpeg compatibility macro */
+#ifdef SampleFormat
+#undef SampleFormat
+#endif
+
+/**
+ * Convert a FFmpeg time stamp to a floating point value (in seconds).
+ */
+gcc_const
+static inline double
+FfmpegTimeToDouble(int64_t t, const AVRational time_base)
+{
+ assert(t != (int64_t)AV_NOPTS_VALUE);
+
+ return (double)av_rescale_q(t, time_base, (AVRational){1, 1024})
+ / (double)1024;
+}
+
+/**
+ * Convert a std::ratio to a #AVRational.
+ */
+template<typename Ratio>
+static inline constexpr AVRational
+RatioToAVRational()
+{
+ return { Ratio::num, Ratio::den };
+}
+
+/**
+ * Convert a FFmpeg time stamp to a #SongTime.
+ */
+gcc_const
+static inline SongTime
+FromFfmpegTime(int64_t t, const AVRational time_base)
+{
+ assert(t != (int64_t)AV_NOPTS_VALUE);
+
+ return SongTime::FromMS(av_rescale_q(t, time_base,
+ (AVRational){1, 1000}));
+}
+
+/**
+ * Convert a FFmpeg time stamp to a #SignedSongTime.
+ */
+gcc_const
+static inline SignedSongTime
+FromFfmpegTimeChecked(int64_t t, const AVRational time_base)
+{
+ return t != (int64_t)AV_NOPTS_VALUE
+ ? SignedSongTime(FromFfmpegTime(t, time_base))
+ : SignedSongTime::Negative();
+}
+
+/**
+ * Convert a #SongTime to a FFmpeg time stamp with the given base.
+ */
+gcc_const
+static inline int64_t
+ToFfmpegTime(SongTime t, const AVRational time_base)
+{
+ return av_rescale_q(t.count(),
+ RatioToAVRational<SongTime::period>(),
+ time_base);
+}
+
+/**
+ * Replace #AV_NOPTS_VALUE with the given fallback.
+ */
+static constexpr int64_t
+FfmpegTimestampFallback(int64_t t, int64_t fallback)
+{
+ return gcc_likely(t != int64_t(AV_NOPTS_VALUE))
+ ? t
+ : fallback;
+}
+
+#endif
diff --git a/src/lib/icu/Collate.cxx b/src/lib/icu/Collate.cxx
index 17b536b37..dc8598a7a 100644
--- a/src/lib/icu/Collate.cxx
+++ b/src/lib/icu/Collate.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -19,8 +19,10 @@
#include "config.h"
#include "Collate.hxx"
+#include "util/AllocatedString.hxx"
#ifdef HAVE_ICU
+#include "Util.hxx"
#include "Error.hxx"
#include "util/WritableBuffer.hxx"
#include "util/ConstBuffer.hxx"
@@ -29,13 +31,17 @@
#include <unicode/ucol.h>
#include <unicode/ustring.h>
-#elif defined(HAVE_GLIB)
-#include <glib.h>
#else
#include <algorithm>
#include <ctype.h>
#endif
+#ifdef WIN32
+#include "Win32.hxx"
+#include "util/AllocatedString.hxx"
+#include <windows.h>
+#endif
+
#include <assert.h>
#include <string.h>
#include <strings.h>
@@ -71,50 +77,6 @@ IcuCollateFinish()
ucol_close(collator);
}
-static WritableBuffer<UChar>
-UCharFromUTF8(const char *src)
-{
- assert(src != nullptr);
-
- const size_t src_length = strlen(src);
- const size_t dest_capacity = src_length;
- UChar *dest = new UChar[dest_capacity];
-
- UErrorCode error_code = U_ZERO_ERROR;
- int32_t dest_length;
- u_strFromUTF8(dest, dest_capacity, &dest_length,
- src, src_length,
- &error_code);
- if (U_FAILURE(error_code)) {
- delete[] dest;
- return nullptr;
- }
-
- return { dest, size_t(dest_length) };
-}
-
-static WritableBuffer<char>
-UCharToUTF8(ConstBuffer<UChar> src)
-{
- assert(!src.IsNull());
-
- /* worst-case estimate */
- size_t dest_capacity = 4 * src.size;
-
- char *dest = new char[dest_capacity];
-
- UErrorCode error_code = U_ZERO_ERROR;
- int32_t dest_length;
- u_strToUTF8(dest, dest_capacity, &dest_length, src.data, src.size,
- &error_code);
- if (U_FAILURE(error_code)) {
- delete[] dest;
- return nullptr;
- }
-
- return { dest, size_t(dest_length) };
-}
-
#endif
gcc_pure
@@ -150,14 +112,32 @@ IcuCollate(const char *a, const char *b)
return result;
#endif
-#elif defined(HAVE_GLIB)
- return g_utf8_collate(a, b);
+#elif defined(WIN32)
+ const auto wa = MultiByteToWideChar(CP_UTF8, a);
+ const auto wb = MultiByteToWideChar(CP_UTF8, b);
+ if (wa.IsNull())
+ return wb.IsNull() ? 0 : -1;
+ else if (wb.IsNull())
+ return 1;
+
+ auto result = CompareStringEx(LOCALE_NAME_INVARIANT,
+ LINGUISTIC_IGNORECASE,
+ wa.c_str(), -1,
+ wb.c_str(), -1,
+ nullptr, nullptr, 0);
+ if (result != 0)
+ /* "To maintain the C runtime convention of comparing
+ strings, the value 2 can be subtracted from a
+ nonzero return value." */
+ result -= 2;
+
+ return result;
#else
- return strcasecmp(a, b);
+ return strcoll(a, b);
#endif
}
-std::string
+AllocatedString<>
IcuCaseFold(const char *src)
{
#ifdef HAVE_ICU
@@ -169,37 +149,70 @@ IcuCaseFold(const char *src)
const auto u = UCharFromUTF8(src);
if (u.IsNull())
- return std::string(src);
+ return AllocatedString<>::Duplicate(src);
size_t folded_capacity = u.size * 2u;
UChar *folded = new UChar[folded_capacity];
UErrorCode error_code = U_ZERO_ERROR;
size_t folded_length = u_strFoldCase(folded, folded_capacity,
- u.data, u.size,
- U_FOLD_CASE_DEFAULT,
- &error_code);
+ u.data, u.size,
+ U_FOLD_CASE_DEFAULT,
+ &error_code);
delete[] u.data;
if (folded_length == 0 || error_code != U_ZERO_ERROR) {
delete[] folded;
- return std::string(src);
+ return AllocatedString<>::Duplicate(src);
}
- auto result2 = UCharToUTF8({folded, folded_length});
+ auto result = UCharToUTF8({folded, folded_length});
delete[] folded;
- if (result2.IsNull())
- return std::string(src);
-
- std::string result(result2.data, result2.size);
- delete[] result2.data;
-#elif defined(HAVE_GLIB)
- char *tmp = g_utf8_casefold(src, -1);
- std::string result(tmp);
- g_free(tmp);
+ return result;
+
+#elif defined(WIN32)
+ const auto u = MultiByteToWideChar(CP_UTF8, src);
+ if (u.IsNull())
+ return AllocatedString<>::Duplicate(src);
+
+ const int size = LCMapStringEx(LOCALE_NAME_INVARIANT,
+ LCMAP_SORTKEY|LINGUISTIC_IGNORECASE,
+ u.c_str(), -1, nullptr, 0,
+ nullptr, nullptr, 0);
+ if (size <= 0)
+ return AllocatedString<>::Duplicate(src);
+
+ auto buffer = new wchar_t[size];
+ if (LCMapStringEx(LOCALE_NAME_INVARIANT,
+ LCMAP_SORTKEY|LINGUISTIC_IGNORECASE,
+ u.c_str(), -1, buffer, size,
+ nullptr, nullptr, 0) <= 0) {
+ delete[] buffer;
+ return AllocatedString<>::Duplicate(src);
+ }
+
+ auto result = WideCharToMultiByte(CP_UTF8, buffer);
+ delete[] buffer;
+ if (result.IsNull())
+ return AllocatedString<>::Duplicate(src);
+
+ return result;
+
#else
- std::string result(src);
- std::transform(result.begin(), result.end(), result.begin(), tolower);
+ size_t size = strlen(src) + 1;
+ auto buffer = new char[size];
+ size_t nbytes = strxfrm(buffer, src, size);
+ if (nbytes >= size) {
+ /* buffer too small - reallocate and try again */
+ delete[] buffer;
+ size = nbytes + 1;
+ buffer = new char[size];
+ nbytes = strxfrm(buffer, src, size);
+ }
+
+ assert(nbytes < size);
+ assert(buffer[nbytes] == 0);
+
+ return AllocatedString<>::Donate(buffer);
#endif
- return result;
}
diff --git a/src/lib/icu/Collate.hxx b/src/lib/icu/Collate.hxx
index 8ae8de46a..0ad3b24ff 100644
--- a/src/lib/icu/Collate.hxx
+++ b/src/lib/icu/Collate.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -26,6 +26,7 @@
#include <string>
class Error;
+template<typename T> class AllocatedString;
bool
IcuCollateInit(Error &error);
@@ -38,7 +39,7 @@ int
IcuCollate(const char *a, const char *b);
gcc_pure gcc_nonnull_all
-std::string
+AllocatedString<char>
IcuCaseFold(const char *src);
#endif
diff --git a/src/lib/icu/Converter.cxx b/src/lib/icu/Converter.cxx
new file mode 100644
index 000000000..61c0cbdd5
--- /dev/null
+++ b/src/lib/icu/Converter.cxx
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+#include "Converter.hxx"
+#include "Error.hxx"
+#include "util/Error.hxx"
+#include "util/Macros.hxx"
+#include "util/AllocatedString.hxx"
+#include "util/WritableBuffer.hxx"
+#include "util/ConstBuffer.hxx"
+
+#include <string.h>
+
+#ifdef HAVE_ICU
+#include "Util.hxx"
+#include <unicode/ucnv.h>
+#elif defined(HAVE_ICONV)
+#include "util/Domain.hxx"
+static constexpr Domain iconv_domain("iconv");
+#endif
+
+#ifdef HAVE_ICU
+
+IcuConverter::~IcuConverter()
+{
+ ucnv_close(converter);
+}
+
+#endif
+
+#ifdef HAVE_ICU_CONVERTER
+
+IcuConverter *
+IcuConverter::Create(const char *charset, Error &error)
+{
+#ifdef HAVE_ICU
+ UErrorCode code = U_ZERO_ERROR;
+ UConverter *converter = ucnv_open(charset, &code);
+ if (converter == nullptr) {
+ error.Format(icu_domain, int(code),
+ "Failed to initialize charset '%s': %s",
+ charset, u_errorName(code));
+ return nullptr;
+ }
+
+ return new IcuConverter(converter);
+#elif defined(HAVE_ICONV)
+ iconv_t to = iconv_open("utf-8", charset);
+ iconv_t from = iconv_open(charset, "utf-8");
+ if (to == (iconv_t)-1 || from == (iconv_t)-1) {
+ error.FormatErrno("Failed to initialize charset '%s'",
+ charset);
+ if (to != (iconv_t)-1)
+ iconv_close(to);
+ if (from != (iconv_t)-1)
+ iconv_close(from);
+ return nullptr;
+ }
+
+ return new IcuConverter(to, from);
+#endif
+}
+
+#ifdef HAVE_ICU
+#elif defined(HAVE_ICONV)
+
+static AllocatedString<char>
+DoConvert(iconv_t conv, const char *src)
+{
+ // TODO: dynamic buffer?
+ char buffer[4096];
+ char *in = const_cast<char *>(src);
+ char *out = buffer;
+ size_t in_left = strlen(src);
+ size_t out_left = sizeof(buffer);
+
+ size_t n = iconv(conv, &in, &in_left, &out, &out_left);
+
+ if (n == static_cast<size_t>(-1) || in_left > 0)
+ return nullptr;
+
+ return AllocatedString<>::Duplicate(buffer, sizeof(buffer) - out_left);
+}
+
+#endif
+
+AllocatedString<char>
+IcuConverter::ToUTF8(const char *s) const
+{
+#ifdef HAVE_ICU
+ const ScopeLock protect(mutex);
+
+ ucnv_resetToUnicode(converter);
+
+ // TODO: dynamic buffer?
+ UChar buffer[4096], *target = buffer;
+ const char *source = s;
+
+ UErrorCode code = U_ZERO_ERROR;
+
+ ucnv_toUnicode(converter, &target, buffer + ARRAY_SIZE(buffer),
+ &source, source + strlen(source),
+ nullptr, true, &code);
+ if (code != U_ZERO_ERROR)
+ return nullptr;
+
+ const size_t target_length = target - buffer;
+ return UCharToUTF8({buffer, target_length});
+#elif defined(HAVE_ICONV)
+ return DoConvert(to_utf8, s);
+#endif
+}
+
+AllocatedString<char>
+IcuConverter::FromUTF8(const char *s) const
+{
+#ifdef HAVE_ICU
+ const ScopeLock protect(mutex);
+
+ const auto u = UCharFromUTF8(s);
+ if (u.IsNull())
+ return nullptr;
+
+ ucnv_resetFromUnicode(converter);
+
+ // TODO: dynamic buffer?
+ char buffer[4096], *target = buffer;
+ const UChar *source = u.data;
+ UErrorCode code = U_ZERO_ERROR;
+
+ ucnv_fromUnicode(converter, &target, buffer + ARRAY_SIZE(buffer),
+ &source, u.end(),
+ nullptr, true, &code);
+ delete[] u.data;
+
+ if (code != U_ZERO_ERROR)
+ return nullptr;
+
+ return AllocatedString<>::Duplicate(buffer, target);
+
+#elif defined(HAVE_ICONV)
+ return DoConvert(from_utf8, s);
+#endif
+}
+
+#endif
diff --git a/src/lib/icu/Converter.hxx b/src/lib/icu/Converter.hxx
new file mode 100644
index 000000000..edb092d8f
--- /dev/null
+++ b/src/lib/icu/Converter.hxx
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPD_ICU_CONVERTER_HXX
+#define MPD_ICU_CONVERTER_HXX
+
+#include "check.h"
+#include "Compiler.h"
+
+#ifdef HAVE_ICU
+#include "thread/Mutex.hxx"
+#define HAVE_ICU_CONVERTER
+#elif defined(HAVE_ICONV)
+#include <iconv.h>
+#define HAVE_ICU_CONVERTER
+#endif
+
+#ifdef HAVE_ICU_CONVERTER
+
+class Error;
+
+#ifdef HAVE_ICU
+struct UConverter;
+#endif
+
+template<typename T> class AllocatedString;
+
+/**
+ * This class can convert strings with a certain character set to and
+ * from UTF-8.
+ */
+class IcuConverter {
+#ifdef HAVE_ICU
+ /**
+ * ICU's UConverter class is not thread-safe. This mutex
+ * serializes simultaneous calls.
+ */
+ mutable Mutex mutex;
+
+ UConverter *const converter;
+
+ IcuConverter(UConverter *_converter):converter(_converter) {}
+#elif defined(HAVE_ICONV)
+ const iconv_t to_utf8, from_utf8;
+
+ IcuConverter(iconv_t _to, iconv_t _from)
+ :to_utf8(_to), from_utf8(_from) {}
+#endif
+
+public:
+#ifdef HAVE_ICU
+ ~IcuConverter();
+#elif defined(HAVE_ICONV)
+ ~IcuConverter() {
+ iconv_close(to_utf8);
+ iconv_close(from_utf8);
+ }
+#endif
+
+ static IcuConverter *Create(const char *charset, Error &error);
+
+ /**
+ * Convert the string to UTF-8.
+ *
+ * Returns AllocatedString::Null() on error.
+ */
+ gcc_pure gcc_nonnull_all
+ AllocatedString<char> ToUTF8(const char *s) const;
+
+ /**
+ * Convert the string from UTF-8.
+ *
+ * Returns AllocatedString::Null() on error.
+ */
+ gcc_pure gcc_nonnull_all
+ AllocatedString<char> FromUTF8(const char *s) const;
+};
+
+#endif
+
+#endif
diff --git a/src/lib/icu/Error.cxx b/src/lib/icu/Error.cxx
index 1fef078ac..f49ede352 100644
--- a/src/lib/icu/Error.cxx
+++ b/src/lib/icu/Error.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/icu/Error.hxx b/src/lib/icu/Error.hxx
index e96667f57..37cdb12fe 100644
--- a/src/lib/icu/Error.hxx
+++ b/src/lib/icu/Error.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/icu/Init.cxx b/src/lib/icu/Init.cxx
index 1d0ad0777..6b70d60ee 100644
--- a/src/lib/icu/Init.cxx
+++ b/src/lib/icu/Init.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/icu/Init.hxx b/src/lib/icu/Init.hxx
index 9f585e2bd..402e7b957 100644
--- a/src/lib/icu/Init.hxx
+++ b/src/lib/icu/Init.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/icu/Util.cxx b/src/lib/icu/Util.cxx
new file mode 100644
index 000000000..92f1de5aa
--- /dev/null
+++ b/src/lib/icu/Util.cxx
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+#include "Util.hxx"
+#include "util/AllocatedString.hxx"
+#include "util/WritableBuffer.hxx"
+#include "util/ConstBuffer.hxx"
+
+#include <unicode/ustring.h>
+
+#include <assert.h>
+#include <string.h>
+
+WritableBuffer<UChar>
+UCharFromUTF8(const char *src)
+{
+ assert(src != nullptr);
+
+ const size_t src_length = strlen(src);
+ const size_t dest_capacity = src_length;
+ UChar *dest = new UChar[dest_capacity];
+
+ UErrorCode error_code = U_ZERO_ERROR;
+ int32_t dest_length;
+ u_strFromUTF8(dest, dest_capacity, &dest_length,
+ src, src_length,
+ &error_code);
+ if (U_FAILURE(error_code)) {
+ delete[] dest;
+ return nullptr;
+ }
+
+ return { dest, size_t(dest_length) };
+}
+
+AllocatedString<>
+UCharToUTF8(ConstBuffer<UChar> src)
+{
+ assert(!src.IsNull());
+
+ /* worst-case estimate */
+ size_t dest_capacity = 4 * src.size;
+
+ char *dest = new char[dest_capacity + 1];
+
+ UErrorCode error_code = U_ZERO_ERROR;
+ int32_t dest_length;
+ u_strToUTF8(dest, dest_capacity, &dest_length, src.data, src.size,
+ &error_code);
+ if (U_FAILURE(error_code)) {
+ delete[] dest;
+ return nullptr;
+ }
+
+ dest[dest_length] = 0;
+ return AllocatedString<>::Donate(dest);
+}
diff --git a/src/lib/icu/Util.hxx b/src/lib/icu/Util.hxx
new file mode 100644
index 000000000..f2d99d0e6
--- /dev/null
+++ b/src/lib/icu/Util.hxx
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPD_ICU_UTIL_HXX
+#define MPD_ICU_UTIL_HXX
+
+#include "check.h"
+
+#include <unicode/utypes.h>
+
+template<typename T> struct WritableBuffer;
+template<typename T> struct ConstBuffer;
+template<typename T> class AllocatedString;
+
+/**
+ * Wrapper for u_strFromUTF8(). The returned pointer must be freed
+ * with delete[].
+ */
+WritableBuffer<UChar>
+UCharFromUTF8(const char *src);
+
+/**
+ * Wrapper for u_strToUTF8(). The returned pointer must be freed with
+ * delete[].
+ */
+AllocatedString<char>
+UCharToUTF8(ConstBuffer<UChar> src);
+
+#endif
diff --git a/src/lib/icu/Win32.cxx b/src/lib/icu/Win32.cxx
new file mode 100644
index 000000000..6f190c924
--- /dev/null
+++ b/src/lib/icu/Win32.cxx
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+#include "Win32.hxx"
+#include "util/AllocatedString.hxx"
+
+#include <windows.h>
+
+AllocatedString<char>
+WideCharToMultiByte(unsigned code_page, const wchar_t *src)
+{
+ int length = WideCharToMultiByte(code_page, 0, src, -1, nullptr, 0,
+ nullptr, nullptr);
+ if (length <= 0)
+ return nullptr;
+
+ char *buffer = new char[length];
+ length = WideCharToMultiByte(code_page, 0, src, -1, buffer, length,
+ nullptr, nullptr);
+ if (length <= 0) {
+ delete[] buffer;
+ return nullptr;
+ }
+
+ return AllocatedString<char>::Donate(buffer);
+}
+
+AllocatedString<wchar_t>
+MultiByteToWideChar(unsigned code_page, const char *src)
+{
+ int length = MultiByteToWideChar(code_page, 0, src, -1, nullptr, 0);
+ if (length <= 0)
+ return nullptr;
+
+ wchar_t *buffer = new wchar_t[length];
+ length = MultiByteToWideChar(code_page, 0, src, -1, buffer, length);
+ if (length <= 0) {
+ delete[] buffer;
+ return nullptr;
+ }
+
+ return AllocatedString<wchar_t>::Donate(buffer);
+}
diff --git a/src/lib/icu/Win32.hxx b/src/lib/icu/Win32.hxx
new file mode 100644
index 000000000..253fe169a
--- /dev/null
+++ b/src/lib/icu/Win32.hxx
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPD_ICU_WIN32_HXX
+#define MPD_ICU_WIN32_HXX
+
+#include "check.h"
+#include "Compiler.h"
+
+#include <wchar.h>
+
+template<typename T> class AllocatedString;
+
+gcc_pure gcc_nonnull_all
+AllocatedString<char>
+WideCharToMultiByte(unsigned code_page, const wchar_t *src);
+
+gcc_pure gcc_nonnull_all
+AllocatedString<wchar_t>
+MultiByteToWideChar(unsigned code_page, const char *src);
+
+#endif
diff --git a/src/lib/nfs/Base.cxx b/src/lib/nfs/Base.cxx
index 3004cd11b..588176ef6 100644
--- a/src/lib/nfs/Base.cxx
+++ b/src/lib/nfs/Base.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/nfs/Base.hxx b/src/lib/nfs/Base.hxx
index 3a92a86d3..e007bfbd2 100644
--- a/src/lib/nfs/Base.hxx
+++ b/src/lib/nfs/Base.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/nfs/Blocking.cxx b/src/lib/nfs/Blocking.cxx
index 58eaf6af2..7bccfa532 100644
--- a/src/lib/nfs/Blocking.cxx
+++ b/src/lib/nfs/Blocking.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/nfs/Blocking.hxx b/src/lib/nfs/Blocking.hxx
index eb16dfb8c..47721363c 100644
--- a/src/lib/nfs/Blocking.hxx
+++ b/src/lib/nfs/Blocking.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/nfs/Callback.hxx b/src/lib/nfs/Callback.hxx
index ae82ecc3c..849fbfbb9 100644
--- a/src/lib/nfs/Callback.hxx
+++ b/src/lib/nfs/Callback.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/nfs/Cancellable.hxx b/src/lib/nfs/Cancellable.hxx
index 151be0528..6c207d9b2 100644
--- a/src/lib/nfs/Cancellable.hxx
+++ b/src/lib/nfs/Cancellable.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/nfs/Connection.cxx b/src/lib/nfs/Connection.cxx
index 6e9f77345..3b3358be0 100644
--- a/src/lib/nfs/Connection.cxx
+++ b/src/lib/nfs/Connection.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/nfs/Connection.hxx b/src/lib/nfs/Connection.hxx
index 3969a7e8f..3402116b7 100644
--- a/src/lib/nfs/Connection.hxx
+++ b/src/lib/nfs/Connection.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/nfs/Domain.cxx b/src/lib/nfs/Domain.cxx
index fefe0dbf3..af79e45a8 100644
--- a/src/lib/nfs/Domain.cxx
+++ b/src/lib/nfs/Domain.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/nfs/Domain.hxx b/src/lib/nfs/Domain.hxx
index 6730b92e1..15856657f 100644
--- a/src/lib/nfs/Domain.hxx
+++ b/src/lib/nfs/Domain.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/nfs/FileReader.cxx b/src/lib/nfs/FileReader.cxx
index 1b80f2c86..97522321b 100644
--- a/src/lib/nfs/FileReader.cxx
+++ b/src/lib/nfs/FileReader.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/nfs/FileReader.hxx b/src/lib/nfs/FileReader.hxx
index 1495a2832..5e3b5221f 100644
--- a/src/lib/nfs/FileReader.hxx
+++ b/src/lib/nfs/FileReader.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/nfs/Glue.cxx b/src/lib/nfs/Glue.cxx
index 6e1e0f99b..fa894f59a 100644
--- a/src/lib/nfs/Glue.cxx
+++ b/src/lib/nfs/Glue.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/nfs/Glue.hxx b/src/lib/nfs/Glue.hxx
index 6da8957cb..d661b3fe0 100644
--- a/src/lib/nfs/Glue.hxx
+++ b/src/lib/nfs/Glue.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/nfs/Lease.hxx b/src/lib/nfs/Lease.hxx
index 6f88acf53..3276cfc31 100644
--- a/src/lib/nfs/Lease.hxx
+++ b/src/lib/nfs/Lease.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/nfs/Manager.cxx b/src/lib/nfs/Manager.cxx
index 6d50cce18..1cbf18ff1 100644
--- a/src/lib/nfs/Manager.cxx
+++ b/src/lib/nfs/Manager.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -21,6 +21,7 @@
#include "Manager.hxx"
#include "event/Loop.hxx"
#include "Log.hxx"
+#include "util/DeleteDisposer.hxx"
#include <string.h>
@@ -65,9 +66,7 @@ NfsManager::~NfsManager()
CollectGarbage();
- connections.clear_and_dispose([](ManagedConnection *c){
- delete c;
- });
+ connections.clear_and_dispose(DeleteDisposer());
}
NfsConnection &
@@ -95,9 +94,7 @@ NfsManager::CollectGarbage()
{
assert(GetEventLoop().IsInside());
- garbage.clear_and_dispose([](ManagedConnection *c){
- delete c;
- });
+ garbage.clear_and_dispose(DeleteDisposer());
}
void
diff --git a/src/lib/nfs/Manager.hxx b/src/lib/nfs/Manager.hxx
index 130c81aca..1eb01590a 100644
--- a/src/lib/nfs/Manager.hxx
+++ b/src/lib/nfs/Manager.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/pulse/Domain.cxx b/src/lib/pulse/Domain.cxx
new file mode 100644
index 000000000..ac4821cae
--- /dev/null
+++ b/src/lib/pulse/Domain.cxx
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+#include "Domain.hxx"
+#include "util/Domain.hxx"
+
+const Domain pulse_domain("pulse");
diff --git a/src/lib/pulse/Domain.hxx b/src/lib/pulse/Domain.hxx
new file mode 100644
index 000000000..bacf8b7eb
--- /dev/null
+++ b/src/lib/pulse/Domain.hxx
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPD_PULSE_DOMAIN_HXX
+#define MPD_PULSE_DOMAIN_HXX
+
+class Domain;
+
+extern const Domain pulse_domain;
+
+#endif
diff --git a/src/lib/pulse/Error.cxx b/src/lib/pulse/Error.cxx
new file mode 100644
index 000000000..60ca0198a
--- /dev/null
+++ b/src/lib/pulse/Error.cxx
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+#include "Error.hxx"
+#include "Domain.hxx"
+#include "util/Error.hxx"
+
+#include <pulse/context.h>
+#include <pulse/error.h>
+
+void
+SetPulseError(Error &error, pa_context *context, const char *prefix)
+{
+ const int e = pa_context_errno(context);
+ error.Format(pulse_domain, e, "%s: %s", prefix, pa_strerror(e));
+}
diff --git a/src/lib/pulse/Error.hxx b/src/lib/pulse/Error.hxx
new file mode 100644
index 000000000..c9225a7c2
--- /dev/null
+++ b/src/lib/pulse/Error.hxx
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPD_PULSE_ERROR_HXX
+#define MPD_PULSE_ERROR_HXX
+
+class Error;
+struct pa_context;
+
+void
+SetPulseError(Error &error, pa_context *context, const char *prefix);
+
+#endif
diff --git a/src/lib/pulse/LogError.cxx b/src/lib/pulse/LogError.cxx
new file mode 100644
index 000000000..a322e7e75
--- /dev/null
+++ b/src/lib/pulse/LogError.cxx
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+#include "LogError.hxx"
+#include "Domain.hxx"
+#include "Log.hxx"
+
+#include <pulse/context.h>
+#include <pulse/error.h>
+
+void
+LogPulseError(pa_context *context, const char *prefix)
+{
+ const int e = pa_context_errno(context);
+ FormatError(pulse_domain, "%s: %s", prefix, pa_strerror(e));
+}
diff --git a/src/lib/pulse/LogError.hxx b/src/lib/pulse/LogError.hxx
new file mode 100644
index 000000000..2e0859366
--- /dev/null
+++ b/src/lib/pulse/LogError.hxx
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPD_PULSE_LOG_ERROR_HXX
+#define MPD_PULSE_LOG_ERROR_HXX
+
+struct pa_context;
+
+void
+LogPulseError(pa_context *context, const char *prefix);
+
+#endif
diff --git a/src/lib/smbclient/Domain.cxx b/src/lib/smbclient/Domain.cxx
index 00f5ee6c1..c6f6b143d 100644
--- a/src/lib/smbclient/Domain.cxx
+++ b/src/lib/smbclient/Domain.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/smbclient/Domain.hxx b/src/lib/smbclient/Domain.hxx
index 3b21c4e60..dc9812fed 100644
--- a/src/lib/smbclient/Domain.hxx
+++ b/src/lib/smbclient/Domain.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/smbclient/Init.cxx b/src/lib/smbclient/Init.cxx
index a7f2da4dd..999e60fcd 100644
--- a/src/lib/smbclient/Init.cxx
+++ b/src/lib/smbclient/Init.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/smbclient/Init.hxx b/src/lib/smbclient/Init.hxx
index 21014ec8d..1ccaec033 100644
--- a/src/lib/smbclient/Init.hxx
+++ b/src/lib/smbclient/Init.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/smbclient/Mutex.cxx b/src/lib/smbclient/Mutex.cxx
index 4dfc5a9d3..fd78e9948 100644
--- a/src/lib/smbclient/Mutex.cxx
+++ b/src/lib/smbclient/Mutex.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/smbclient/Mutex.hxx b/src/lib/smbclient/Mutex.hxx
index dc7372e6e..893f6204d 100644
--- a/src/lib/smbclient/Mutex.hxx
+++ b/src/lib/smbclient/Mutex.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/sqlite/Domain.cxx b/src/lib/sqlite/Domain.cxx
new file mode 100644
index 000000000..4f6fe4c45
--- /dev/null
+++ b/src/lib/sqlite/Domain.cxx
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+#include "Domain.hxx"
+#include "util/Domain.hxx"
+
+const Domain sqlite_domain("sqlite");
diff --git a/src/lib/sqlite/Domain.hxx b/src/lib/sqlite/Domain.hxx
new file mode 100644
index 000000000..0b9965025
--- /dev/null
+++ b/src/lib/sqlite/Domain.hxx
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPD_SQLITE_DOMAIN_HXX
+#define MPD_SQLITE_DOMAIN_HXX
+
+class Domain;
+
+extern const Domain sqlite_domain;
+
+#endif
diff --git a/src/lib/sqlite/Util.hxx b/src/lib/sqlite/Util.hxx
new file mode 100644
index 000000000..151eac6c2
--- /dev/null
+++ b/src/lib/sqlite/Util.hxx
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPD_SQLITE_UTIL_HXX
+#define MPD_SQLITE_UTIL_HXX
+
+#include "Domain.hxx"
+#include "util/Error.hxx"
+
+#include <sqlite3.h>
+
+#include <assert.h>
+
+static void
+SetError(Error &error, sqlite3 *db, int code, const char *msg)
+{
+ error.Format(sqlite_domain, code, "%s: %s",
+ msg, sqlite3_errmsg(db));
+}
+
+static void
+SetError(Error &error, sqlite3_stmt *stmt, int code, const char *msg)
+{
+ SetError(error, sqlite3_db_handle(stmt), code, msg);
+}
+
+static bool
+Bind(sqlite3_stmt *stmt, unsigned i, const char *value, Error &error)
+{
+ int result = sqlite3_bind_text(stmt, i, value, -1, nullptr);
+ if (result != SQLITE_OK) {
+ SetError(error, stmt, result, "sqlite3_bind_text() failed");
+ return false;
+ }
+
+ return true;
+}
+
+template<typename... Args>
+static bool
+BindAll2(gcc_unused Error &error, gcc_unused sqlite3_stmt *stmt,
+ gcc_unused unsigned i)
+{
+ assert(int(i - 1) == sqlite3_bind_parameter_count(stmt));
+
+ return true;
+}
+
+template<typename... Args>
+static bool
+BindAll2(Error &error, sqlite3_stmt *stmt, unsigned i,
+ const char *value, Args&&... args)
+{
+ return Bind(stmt, i, value, error) &&
+ BindAll2(error, stmt, i + 1, std::forward<Args>(args)...);
+}
+
+template<typename... Args>
+static bool
+BindAll(Error &error, sqlite3_stmt *stmt, Args&&... args)
+{
+ assert(int(sizeof...(args)) == sqlite3_bind_parameter_count(stmt));
+
+ return BindAll2(error, stmt, 1, std::forward<Args>(args)...);
+}
+
+/**
+ * Wrapper for BindAll() that returns the specified sqlite3_stmt* on
+ * success and nullptr on error.
+ */
+template<typename... Args>
+static sqlite3_stmt *
+BindAllOrNull(Error &error, sqlite3_stmt *stmt, Args&&... args)
+{
+ return BindAll(error, stmt, std::forward<Args>(args)...)
+ ? stmt
+ : nullptr;
+}
+
+/**
+ * Call sqlite3_stmt() repepatedly until something other than
+ * SQLITE_BUSY is returned.
+ */
+static int
+ExecuteBusy(sqlite3_stmt *stmt)
+{
+ int result;
+ do {
+ result = sqlite3_step(stmt);
+ } while (result == SQLITE_BUSY);
+
+ return result;
+}
+
+/**
+ * Wrapper for ExecuteBusy() that returns true on SQLITE_ROW.
+ */
+static bool
+ExecuteRow(sqlite3_stmt *stmt, Error &error)
+{
+ int result = ExecuteBusy(stmt);
+ if (result == SQLITE_ROW)
+ return true;
+
+ if (result != SQLITE_DONE)
+ SetError(error, stmt, result, "sqlite3_step() failed");
+
+ return false;
+}
+
+/**
+ * Wrapper for ExecuteBusy() that interprets everything other than
+ * SQLITE_DONE as error.
+ */
+static bool
+ExecuteCommand(sqlite3_stmt *stmt, Error &error)
+{
+ int result = ExecuteBusy(stmt);
+ if (result != SQLITE_DONE) {
+ SetError(error, stmt, result, "sqlite3_step() failed");
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Wrapper for ExecuteCommand() that returns the number of rows
+ * modified via sqlite3_changes(). Returns -1 on error.
+ */
+static inline int
+ExecuteChanges(sqlite3_stmt *stmt, Error &error)
+{
+ if (!ExecuteCommand(stmt, error))
+ return -1;
+
+ return sqlite3_changes(sqlite3_db_handle(stmt));
+}
+
+/**
+ * Wrapper for ExecuteChanges() that returns true if at least one row
+ * was modified. Returns false if nothing was modified or if an error
+ * occurred.
+ */
+static inline bool
+ExecuteModified(sqlite3_stmt *stmt, Error &error)
+{
+ return ExecuteChanges(stmt, error) > 0;
+}
+
+template<typename F>
+static inline bool
+ExecuteForEach(sqlite3_stmt *stmt, Error &error, F &&f)
+{
+ while (true) {
+ int result = ExecuteBusy(stmt);
+ switch (result) {
+ case SQLITE_ROW:
+ f();
+ break;
+
+ case SQLITE_DONE:
+ return true;
+
+ default:
+ SetError(error, stmt, result, "sqlite3_step() failed");
+ return false;
+ }
+ }
+}
+
+#endif
diff --git a/src/lib/upnp/Action.hxx b/src/lib/upnp/Action.hxx
index 28c88be92..bad398e1a 100644
--- a/src/lib/upnp/Action.hxx
+++ b/src/lib/upnp/Action.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/upnp/Callback.hxx b/src/lib/upnp/Callback.hxx
index 85daf0a7e..4d86c0b53 100644
--- a/src/lib/upnp/Callback.hxx
+++ b/src/lib/upnp/Callback.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/upnp/ClientInit.cxx b/src/lib/upnp/ClientInit.cxx
index 77d9cf03d..50fcbdb16 100644
--- a/src/lib/upnp/ClientInit.cxx
+++ b/src/lib/upnp/ClientInit.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/upnp/ClientInit.hxx b/src/lib/upnp/ClientInit.hxx
index 645e64ca6..f49f255ee 100644
--- a/src/lib/upnp/ClientInit.hxx
+++ b/src/lib/upnp/ClientInit.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/upnp/ContentDirectoryService.cxx b/src/lib/upnp/ContentDirectoryService.cxx
index 0e5d2d955..0636505ab 100644
--- a/src/lib/upnp/ContentDirectoryService.cxx
+++ b/src/lib/upnp/ContentDirectoryService.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/upnp/ContentDirectoryService.hxx b/src/lib/upnp/ContentDirectoryService.hxx
index 0b03df2e7..bf6ab913a 100644
--- a/src/lib/upnp/ContentDirectoryService.hxx
+++ b/src/lib/upnp/ContentDirectoryService.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -62,7 +62,8 @@ public:
/**
* Construct by copying data from device and service objects.
*
- * The discovery service does this: use getDirServices()
+ * The discovery service does this: use
+ * UPnPDeviceDirectory::GetDirectories()
*/
ContentDirectoryService(const UPnPDevice &device,
const UPnPService &service);
diff --git a/src/lib/upnp/Device.cxx b/src/lib/upnp/Device.cxx
index 26bffd0f0..402a39166 100644
--- a/src/lib/upnp/Device.cxx
+++ b/src/lib/upnp/Device.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/upnp/Device.hxx b/src/lib/upnp/Device.hxx
index dd7ecac2d..cdb065434 100644
--- a/src/lib/upnp/Device.hxx
+++ b/src/lib/upnp/Device.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/upnp/Discovery.cxx b/src/lib/upnp/Discovery.cxx
index 1539e1512..f6a3ba122 100644
--- a/src/lib/upnp/Discovery.cxx
+++ b/src/lib/upnp/Discovery.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -107,12 +107,12 @@ UPnPDeviceDirectory::LockRemove(const std::string &id)
}
inline void
-UPnPDeviceDirectory::discoExplorer()
+UPnPDeviceDirectory::Explore()
{
for (;;) {
DiscoveredTask *tsk = 0;
- if (!discoveredQueue.take(tsk)) {
- discoveredQueue.workerExit();
+ if (!queue.take(tsk)) {
+ queue.workerExit();
return;
}
@@ -128,7 +128,7 @@ UPnPDeviceDirectory::discoExplorer()
}
// Update or insert the device
- ContentDirectoryDescriptor d(std::move(tsk->deviceId),
+ ContentDirectoryDescriptor d(std::move(tsk->device_id),
MonotonicClockS(), tsk->expires);
{
@@ -148,10 +148,10 @@ UPnPDeviceDirectory::discoExplorer()
}
void *
-UPnPDeviceDirectory::discoExplorer(void *ctx)
+UPnPDeviceDirectory::Explore(void *ctx)
{
UPnPDeviceDirectory &directory = *(UPnPDeviceDirectory *)ctx;
- directory.discoExplorer();
+ directory.Explore();
return (void*)1;
}
@@ -161,7 +161,7 @@ UPnPDeviceDirectory::OnAlive(Upnp_Discovery *disco)
if (isMSDevice(disco->DeviceType) ||
isCDService(disco->ServiceType)) {
DiscoveredTask *tp = new DiscoveredTask(disco);
- if (discoveredQueue.put(tp))
+ if (queue.put(tp))
return UPNP_E_FINISH;
}
@@ -210,9 +210,8 @@ UPnPDeviceDirectory::Invoke(Upnp_EventType et, void *evp)
}
bool
-UPnPDeviceDirectory::expireDevices(Error &error)
+UPnPDeviceDirectory::ExpireDevices(Error &error)
{
- const ScopeLock protect(mutex);
const unsigned now = MonotonicClockS();
bool didsomething = false;
@@ -227,7 +226,7 @@ UPnPDeviceDirectory::expireDevices(Error &error)
}
if (didsomething)
- return search(error);
+ return Search(error);
return true;
}
@@ -236,8 +235,8 @@ UPnPDeviceDirectory::UPnPDeviceDirectory(UpnpClient_Handle _handle,
UPnPDiscoveryListener *_listener)
:handle(_handle),
listener(_listener),
- discoveredQueue("DiscoveredQueue"),
- m_searchTimeout(2), m_lastSearch(0)
+ queue("DiscoveredQueue"),
+ search_timeout(2), last_search(0)
{
}
@@ -249,24 +248,24 @@ UPnPDeviceDirectory::~UPnPDeviceDirectory()
bool
UPnPDeviceDirectory::Start(Error &error)
{
- if (!discoveredQueue.start(1, discoExplorer, this)) {
+ if (!queue.start(1, Explore, this)) {
error.Set(upnp_domain, "Discover work queue start failed");
return false;
}
- return search(error);
+ return Search(error);
}
bool
-UPnPDeviceDirectory::search(Error &error)
+UPnPDeviceDirectory::Search(Error &error)
{
const unsigned now = MonotonicClockS();
- if (now - m_lastSearch < 10)
+ if (now - last_search < 10)
return true;
- m_lastSearch = now;
+ last_search = now;
// We search both for device and service just in case.
- int code = UpnpSearchAsync(handle, m_searchTimeout,
+ int code = UpnpSearchAsync(handle, search_timeout,
ContentDirectorySType, GetUpnpCookie());
if (code != UPNP_E_SUCCESS) {
error.Format(upnp_domain, code,
@@ -275,7 +274,7 @@ UPnPDeviceDirectory::search(Error &error)
return false;
}
- code = UpnpSearchAsync(handle, m_searchTimeout,
+ code = UpnpSearchAsync(handle, search_timeout,
MediaServerDType, GetUpnpCookie());
if (code != UPNP_E_SUCCESS) {
error.Format(upnp_domain, code,
@@ -288,15 +287,14 @@ UPnPDeviceDirectory::search(Error &error)
}
bool
-UPnPDeviceDirectory::getDirServices(std::vector<ContentDirectoryService> &out,
+UPnPDeviceDirectory::GetDirectories(std::vector<ContentDirectoryService> &out,
Error &error)
{
- // Has locking, do it before our own lock
- if (!expireDevices(error))
- return false;
-
const ScopeLock protect(mutex);
+ if (!ExpireDevices(error))
+ return false;
+
for (auto dit = directories.begin();
dit != directories.end(); dit++) {
for (const auto &service : dit->device.services) {
@@ -310,20 +308,19 @@ UPnPDeviceDirectory::getDirServices(std::vector<ContentDirectoryService> &out,
}
bool
-UPnPDeviceDirectory::getServer(const char *friendlyName,
+UPnPDeviceDirectory::GetServer(const char *friendly_name,
ContentDirectoryService &server,
Error &error)
{
- // Has locking, do it before our own lock
- if (!expireDevices(error))
- return false;
-
const ScopeLock protect(mutex);
+ if (!ExpireDevices(error))
+ return false;
+
for (const auto &i : directories) {
const auto &device = i.device;
- if (device.friendlyName != friendlyName)
+ if (device.friendlyName != friendly_name)
continue;
for (const auto &service : device.services) {
diff --git a/src/lib/upnp/Discovery.hxx b/src/lib/upnp/Discovery.hxx
index 767811840..1cf82b77e 100644
--- a/src/lib/upnp/Discovery.hxx
+++ b/src/lib/upnp/Discovery.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -55,13 +55,13 @@ class UPnPDeviceDirectory final : UpnpCallback {
*/
struct DiscoveredTask {
std::string url;
- std::string deviceId;
+ std::string device_id;
unsigned expires; // Seconds valid
DiscoveredTask(const Upnp_Discovery *disco)
:url(disco->Location),
- deviceId(disco->DeviceId),
- expires(disco->Expires) {}
+ device_id(disco->DeviceId),
+ expires(disco->Expires) {}
};
/**
@@ -97,19 +97,19 @@ class UPnPDeviceDirectory final : UpnpCallback {
Mutex mutex;
std::list<ContentDirectoryDescriptor> directories;
- WorkQueue<DiscoveredTask *> discoveredQueue;
+ WorkQueue<DiscoveredTask *> queue;
/**
* The UPnP device search timeout, which should actually be
* called delay because it's the base of a random delay that
* the devices apply to avoid responding all at the same time.
*/
- int m_searchTimeout;
+ int search_timeout;
/**
* The MonotonicClockS() time stamp of the last search.
*/
- unsigned m_lastSearch;
+ unsigned last_search;
public:
UPnPDeviceDirectory(UpnpClient_Handle _handle,
@@ -122,24 +122,26 @@ public:
bool Start(Error &error);
/** Retrieve the directory services currently seen on the network */
- bool getDirServices(std::vector<ContentDirectoryService> &, Error &);
+ bool GetDirectories(std::vector<ContentDirectoryService> &, Error &);
/**
* Get server by friendly name.
*/
- bool getServer(const char *friendlyName,
+ bool GetServer(const char *friendly_name,
ContentDirectoryService &server,
Error &error);
private:
- bool search(Error &error);
+ bool Search(Error &error);
/**
* Look at the devices and get rid of those which have not
* been seen for too long. We do this when listing the top
* directory.
+ *
+ * Caller must lock #mutex.
*/
- bool expireDevices(Error &error);
+ bool ExpireDevices(Error &error);
void LockAdd(ContentDirectoryDescriptor &&d);
void LockRemove(const std::string &id);
@@ -149,12 +151,11 @@ private:
* devices appearing and disappearing, and update the
* directory pool accordingly.
*/
- static void *discoExplorer(void *);
- void discoExplorer();
+ static void *Explore(void *);
+ void Explore();
int OnAlive(Upnp_Discovery *disco);
int OnByeBye(Upnp_Discovery *disco);
- int cluCallBack(Upnp_EventType et, void *evp);
/* virtual methods from class UpnpCallback */
virtual int Invoke(Upnp_EventType et, void *evp) override;
diff --git a/src/lib/upnp/Domain.cxx b/src/lib/upnp/Domain.cxx
index 010d4c7c2..d7700a067 100644
--- a/src/lib/upnp/Domain.cxx
+++ b/src/lib/upnp/Domain.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/upnp/Domain.hxx b/src/lib/upnp/Domain.hxx
index ec01ef735..ff0cd9b85 100644
--- a/src/lib/upnp/Domain.hxx
+++ b/src/lib/upnp/Domain.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/upnp/Init.cxx b/src/lib/upnp/Init.cxx
index 4fc606de9..1b471f53d 100644
--- a/src/lib/upnp/Init.cxx
+++ b/src/lib/upnp/Init.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/upnp/Init.hxx b/src/lib/upnp/Init.hxx
index b23f8e2ab..796251862 100644
--- a/src/lib/upnp/Init.hxx
+++ b/src/lib/upnp/Init.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/upnp/Util.cxx b/src/lib/upnp/Util.cxx
index 79cfb111c..912d993b4 100644
--- a/src/lib/upnp/Util.cxx
+++ b/src/lib/upnp/Util.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/upnp/Util.hxx b/src/lib/upnp/Util.hxx
index a59f23521..d3b0b049f 100644
--- a/src/lib/upnp/Util.hxx
+++ b/src/lib/upnp/Util.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/upnp/WorkQueue.hxx b/src/lib/upnp/WorkQueue.hxx
index fe8ce53f9..cd6b1161d 100644
--- a/src/lib/upnp/WorkQueue.hxx
+++ b/src/lib/upnp/WorkQueue.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -66,10 +66,7 @@ class WorkQueue {
public:
/** Create a WorkQueue
- * @param name for message printing
- * @param hi number of tasks on queue before clients blocks. Default 0
- * meaning no limit. hi == -1 means that the queue is disabled.
- * @param lo minimum count of tasks before worker starts. Default 1.
+ * @param _name for message printing
*/
WorkQueue(const char *_name)
:name(_name),
@@ -86,7 +83,7 @@ public:
/** Start the worker threads.
*
* @param nworkers number of threads copies to start.
- * @param start_routine thread function. It should loop
+ * @param workproc thread function. It should loop
* taking (QueueWorker::take()) and executing tasks.
* @param arg initial parameter to thread function.
* @return true if ok.
diff --git a/src/lib/zlib/Domain.cxx b/src/lib/zlib/Domain.cxx
index 96aad1350..b94076053 100644
--- a/src/lib/zlib/Domain.cxx
+++ b/src/lib/zlib/Domain.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
diff --git a/src/lib/zlib/Domain.hxx b/src/lib/zlib/Domain.hxx
index 653ac0209..9f0b9c5b0 100644
--- a/src/lib/zlib/Domain.hxx
+++ b/src/lib/zlib/Domain.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * Copyright (C) 2003-2015 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify