+struct expected_user_error : virtual user_error {};
+struct not_supported : virtual user_error {};
+
+std::string get_context();
+
+class scoped_context : boost::noncopyable
+{
+public:
+ scoped_context();
+ scoped_context(std::string msg);
+ template <typename Str>
+ scoped_context(Str msg)
+ : scoped_context(u8(std::move(msg)))
+ {
+ }
+
+ ~scoped_context();
+ void replace_msg(std::string msg);
+ template <typename Str>
+ void replace_msg(std::string msg)
+ {
+ replace_msg(u8(std::move(msg)));
+ }
+ void clear_msg();
+private:
+ std::list<std::string>& for_thread_;
+ std::string* msg_;
+};
+
+#define _CASPAR_GENERATE_UNIQUE_IDENTIFIER_CAT(name, line) name##line
+#define _CASPAR_GENERATE_UNIQUE_IDENTIFIER(name, line) _CASPAR_GENERATE_UNIQUE_IDENTIFIER_CAT(name, line)
+#define CASPAR_SCOPED_CONTEXT_MSG(ctx_msg) ::caspar::scoped_context _CASPAR_GENERATE_UNIQUE_IDENTIFIER(SCOPED_CONTEXT, __LINE__)(u8(ctx_msg));
+
+#define CASPAR_THROW_EXCEPTION(e) BOOST_THROW_EXCEPTION(e << call_stack_info(caspar::get_call_stack()) << context_info(get_context()))