diff options
author | David Robillard <d@drobilla.net> | 2016-08-01 01:16:15 -0400 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2016-08-01 03:43:56 -0400 |
commit | ff6d8a87f9569a42c7827428f2329280c9b633b9 (patch) | |
tree | d7ccbeaac5381e8cfd07c4ad5efd0872de65fd45 | |
parent | 7eb24a2761deb9604f1c6b813e6de69876088f9e (diff) | |
download | ingen-ff6d8a87f9569a42c7827428f2329280c9b633b9.tar.gz ingen-ff6d8a87f9569a42c7827428f2329280c9b633b9.tar.bz2 ingen-ff6d8a87f9569a42c7827428f2329280c9b633b9.zip |
Implement LV2 log extension as host
Only print color logs if output is a terminal.
-rw-r--r-- | ingen/Log.hpp | 22 | ||||
-rw-r--r-- | ingen/URIs.hpp | 1 | ||||
-rw-r--r-- | src/Configuration.cpp | 1 | ||||
-rw-r--r-- | src/Log.cpp | 157 | ||||
-rw-r--r-- | src/URIs.cpp | 1 | ||||
-rw-r--r-- | src/World.cpp | 6 | ||||
-rw-r--r-- | src/server/UndoStack.cpp | 1 | ||||
-rw-r--r-- | wscript | 6 |
8 files changed, 160 insertions, 35 deletions
diff --git a/ingen/Log.hpp b/ingen/Log.hpp index 6c88e9a4..a868e714 100644 --- a/ingen/Log.hpp +++ b/ingen/Log.hpp @@ -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 @@ -21,6 +21,7 @@ #include <boost/format.hpp> +#include "ingen/LV2Features.hpp" #include "ingen/ingen.h" #include "lv2/lv2plug.in/ns/ext/log/log.h" @@ -34,20 +35,39 @@ class INGEN_API Log { public: Log(LV2_Log_Log* log, URIs& uris); + struct Feature : public LV2Features::Feature { + const char* uri() const { return LV2_LOG__log; } + + SPtr<LV2_Feature> feature(World* world, Node* block); + + struct Handle { + LV2_Log_Log lv2_log; + Log* log; + Node* node; + }; + }; + void error(const std::string& msg); void info(const std::string& msg); void warn(const std::string& msg); + void trace(const std::string& msg); inline void error(const fmt& fmt) { error(fmt.str()); } inline void info(const fmt& fmt) { info(fmt.str()); } inline void warn(const fmt& fmt) { warn(fmt.str()); } + int vtprintf(LV2_URID type, const char* fmt, va_list args); + void set_flush(bool f) { _flush = f; } + void set_trace(bool f) { _trace = f; } private: + void print(FILE* stream, const std::string& msg); + LV2_Log_Log* _log; URIs& _uris; bool _flush; + bool _trace; }; } // namespace Ingen diff --git a/ingen/URIs.hpp b/ingen/URIs.hpp index 52921085..9fc771da 100644 --- a/ingen/URIs.hpp +++ b/ingen/URIs.hpp @@ -127,6 +127,7 @@ public: const Quark ingen_value; const Quark log_Error; const Quark log_Note; + const Quark log_Trace; const Quark log_Warning; const Quark lv2_AudioPort; const Quark lv2_CVPort; diff --git a/src/Configuration.cpp b/src/Configuration.cpp index 0f3e3d53..7df565be 100644 --- a/src/Configuration.cpp +++ b/src/Configuration.cpp @@ -65,6 +65,7 @@ Configuration::Configuration(Forge& forge) add("path", "path", 'L', "Target path for loaded graph", SESSION, forge.String, Atom()); add("queueSize", "queue-size", 'q', "Event queue size", GLOBAL, forge.Int, forge.make(4096)); add("flushLog", "flush-log", 'f', "Flush logs after every entry", SESSION, forge.Bool, forge.make(false)); + add("trace", "trace", 't', "Show LV2 plugin trace messages", SESSION, forge.Bool, forge.make(false)); add("humanNames", "human-names", 0, "Show human names in GUI", GUI, forge.Bool, forge.make(true)); add("portLabels", "port-labels", 0, "Show port labels in GUI", GUI, forge.Bool, forge.make(true)); add("graphDirectory", "graph-directory", 0, "Default directory for opening graphs", GUI, forge.String, Atom()); 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 diff --git a/src/URIs.cpp b/src/URIs.cpp index 005490c4..b272e48e 100644 --- a/src/URIs.cpp +++ b/src/URIs.cpp @@ -110,6 +110,7 @@ URIs::URIs(Forge& f, URIMap* map, LilvWorld* lworld) , ingen_value (forge, map, lworld, INGEN__value) , log_Error (forge, map, lworld, LV2_LOG__Error) , log_Note (forge, map, lworld, LV2_LOG__Note) + , log_Trace (forge, map, lworld, LV2_LOG__Trace) , log_Warning (forge, map, lworld, LV2_LOG__Warning) , lv2_AudioPort (forge, map, lworld, LV2_CORE__AudioPort) , lv2_CVPort (forge, map, lworld, LV2_CORE__CVPort) diff --git a/src/World.cpp b/src/World.cpp index 105363b6..38b27a9a 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -111,8 +111,8 @@ public: , uri_map(new URIMap(log, map, unmap)) , forge(new Forge(*uri_map)) , uris(new URIs(*forge, uri_map, lilv_world)) - , log(lv2_log, *uris) , conf(*forge) + , log(lv2_log, *uris) { // Parse default configuration files std::list<std::string> files = conf.load_default("ingen", "options.ttl"); @@ -123,12 +123,14 @@ public: // Parse command line options, overriding configuration file values conf.parse(argc, argv); log.set_flush(conf.option("flush-log").get<int32_t>()); + log.set_trace(conf.option("trace").get<int32_t>()); lv2_features = new LV2Features(); lv2_features->add_feature(uri_map->urid_map_feature()); lv2_features->add_feature(uri_map->urid_unmap_feature()); lv2_features->add_feature(SPtr<InstanceAccess>(new InstanceAccess())); lv2_features->add_feature(SPtr<DataAccess>(new DataAccess())); + lv2_features->add_feature(SPtr<Log::Feature>(new Log::Feature())); lilv_world_load_all(lilv_world); // Set up RDF namespaces @@ -215,8 +217,8 @@ public: Forge* forge; URIs* uris; LV2_Log_Log* lv2_log; - Log log; Configuration conf; + Log log; SPtr<Interface> interface; SPtr<EngineBase> engine; SPtr<Serialiser> serialiser; diff --git a/src/server/UndoStack.cpp b/src/server/UndoStack.cpp index f8a7f37b..77d26871 100644 --- a/src/server/UndoStack.cpp +++ b/src/server/UndoStack.cpp @@ -15,7 +15,6 @@ */ #include <ctime> -#include <iostream> #include "ingen/URIMap.hpp" #include "ingen/URIs.hpp" @@ -86,6 +86,12 @@ def configure(conf): define_name = 'HAVE_POSIX_MEMALIGN', mandatory = False) + conf.check(function_name = 'isatty', + header_name = 'unistd.h', + defines = '_POSIX_SOURCE=1', + define_name = 'HAVE_ISATTY', + mandatory = False) + if not Options.options.no_socket: conf.check(function_name = 'socket', header_name = 'sys/socket.h', |