summaryrefslogtreecommitdiffstats
path: root/src/Log.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Log.cpp')
-rw-r--r--src/Log.cpp157
1 files changed, 126 insertions, 31 deletions
diff --git a/src/Log.cpp b/src/Log.cpp
index c72f3dbb..b2d30b7d 100644
--- a/src/Log.cpp
+++ b/src/Log.cpp
@@ -1,6 +1,6 @@
/*
This file is part of Ingen.
- Copyright 2007-2015 David Robillard <http://drobilla.net/>
+ Copyright 2007-2016 David Robillard <http://drobilla.net/>
Ingen is free software: you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free
@@ -14,65 +14,160 @@
along with Ingen. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <iostream>
+#include <stdio.h>
#include "ingen/Log.hpp"
+#include "ingen/Node.hpp"
#include "ingen/URIs.hpp"
+#include "ingen/World.hpp"
+
+#ifdef HAVE_ISATTY
+# include <unistd.h>
+#else
+inline int isatty(int fd) { return 0; }
+#endif
namespace Ingen {
-static const char* const ANSI_RESET = "\033[0m";
-static const char* const ANSI_RED = "\033[0;31m";
-//static const char* const ANSI_GREEN = "\033[0;32m";
-static const char* const ANSI_YELLOW = "\033[0;33m";
-//static const char* const ANSI_BLUE = "\033[0;34m";
-//static const char* const ANSI_MAGENTA = "\033[0;35m";
-//static const char* const ANSI_CYAN = "\033[0;36m";
-//static const char* const ANSI_WHITE = "\033[0;37m";
+class ColorContext {
+public:
+ enum class Color { RED = 31, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE };
+
+ ColorContext(FILE* stream, Color color) : stream(stream) {
+ if (isatty(fileno(stream))) {
+ fprintf(stream, "\033[0;%dm", color);
+ }
+ }
+
+ ~ColorContext() {
+ if (isatty(fileno(stream))) {
+ fprintf(stream, "\033[0m");
+ fflush(stream);
+ }
+ }
+
+
+ FILE* stream;
+};
Log::Log(LV2_Log_Log* log, URIs& uris)
: _log(log)
, _uris(uris)
, _flush(false)
+ , _trace(false)
{}
void
Log::error(const std::string& msg)
{
- if (_log) {
- _log->printf(_log->handle, _uris.log_Error, "%s", msg.c_str());
- } else {
- std::cerr << ANSI_RED << msg << ANSI_RESET;
- if (_flush) {
- std::flush(std::cerr);
- }
- }
+ va_list args;
+ vtprintf(_uris.log_Error, msg.c_str(), args);
}
void
Log::warn(const std::string& msg)
{
- if (_log) {
- _log->printf(_log->handle, _uris.log_Warning, "%s", msg.c_str());
- } else {
- std::cerr << ANSI_YELLOW << msg << ANSI_RESET;
- if (_flush) {
- std::flush(std::cerr);
- }
- }
+ va_list args;
+ vtprintf(_uris.log_Warning, msg.c_str(), args);
}
void
Log::info(const std::string& msg)
{
+ va_list args;
+ vtprintf(_uris.log_Note, msg.c_str(), args);
+}
+
+void
+Log::trace(const std::string& msg)
+{
+ va_list args;
+ vtprintf(_uris.log_Trace, msg.c_str(), args);
+}
+
+void
+Log::print(FILE* stream, const std::string& msg)
+{
+ fprintf(stream, "%s", msg.c_str());
+ if (_flush) {
+ fflush(stdout);
+ }
+}
+
+int
+Log::vtprintf(LV2_URID type, const char* fmt, va_list args)
+{
+ int ret = 0;
if (_log) {
- _log->printf(_log->handle, _uris.log_Note, "%s", msg.c_str());
+ ret = _log->vprintf(_log->handle, type, fmt, args);
+ } else if (type == _uris.log_Error) {
+ ColorContext ctx(stderr, ColorContext::Color::RED);
+ ret = vfprintf(stderr, fmt, args);
+ } else if (type == _uris.log_Warning) {
+ ColorContext ctx(stderr, ColorContext::Color::YELLOW);
+ ret = vfprintf(stderr, fmt, args);
+ } else if (type == _uris.log_Note) {
+ ColorContext ctx(stderr, ColorContext::Color::GREEN);
+ ret = vfprintf(stdout, fmt, args);
+ } else if (_trace && type == _uris.log_Trace) {
+ ColorContext ctx(stderr, ColorContext::Color::GREEN);
+ ret = vfprintf(stderr, fmt, args);
} else {
- std::cout << msg;
- if (_flush) {
- std::flush(std::cout);
- }
+ fprintf(stderr, "Unknown log type %d\n", type);
+ return 0;
}
+ if (_flush) {
+ fflush(stdout);
+ }
+ return ret;
+}
+
+static int
+log_vprintf(LV2_Log_Handle handle, LV2_URID type, const char* fmt, va_list args)
+{
+ Log::Feature::Handle* f = (Log::Feature::Handle*)handle;
+ va_list noargs;
+
+ int ret = f->log->vtprintf(type, f->node->path().c_str(), noargs);
+ ret += f->log->vtprintf(type, ": ", noargs);
+ ret += f->log->vtprintf(type, fmt, args);
+
+ return ret;
+}
+
+static int
+log_printf(LV2_Log_Handle handle, LV2_URID type, const char* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ const int ret = log_vprintf(handle, type, fmt, args);
+ va_end(args);
+
+ return ret;
+}
+
+static void
+free_log_feature(LV2_Feature* feature) {
+ LV2_Log_Log* lv2_log = (LV2_Log_Log*)feature->data;
+ free(lv2_log->handle);
+ free(feature);
+}
+
+SPtr<LV2_Feature>
+Log::Feature::feature(World* world, Node* block)
+{
+ Handle* handle = (Handle*)calloc(1, sizeof(Handle));
+ handle->lv2_log.handle = handle;
+ handle->lv2_log.printf = log_printf;
+ handle->lv2_log.vprintf = log_vprintf;
+ handle->log = &world->log();
+ handle->node = block;
+
+ LV2_Feature* f = (LV2_Feature*)malloc(sizeof(LV2_Feature));
+ f->URI = LV2_LOG__log;
+ f->data = &handle->lv2_log;
+
+ return SPtr<LV2_Feature>(f, &free_log_feature);
}
} // namespace Ingen