<ItemGroup>\r
<ClInclude Include="compiler\vs\disable_silly_warnings.h" />\r
<ClInclude Include="concurrency\executor.h" />\r
- <ClInclude Include="diagnostics\context.h" />\r
<ClInclude Include="diagnostics\graph.h" />\r
- <ClInclude Include="diagnostics\sink_backend.h" />\r
<ClInclude Include="exception\exceptions.h" />\r
<ClInclude Include="exception\win32_exception.h" />\r
<ClInclude Include="gl\gl_check.h" />\r
<ClInclude Include="utility\timer.h" />\r
</ItemGroup>\r
<ItemGroup>\r
- <ClCompile Include="diagnostics\context.cpp">\r
- <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
- <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
- <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
- </ClCompile>\r
<ClCompile Include="diagnostics\graph.cpp">\r
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
</ClCompile>\r
- <ClCompile Include="diagnostics\sink_backend.cpp">\r
- <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
- <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
- <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
- </ClCompile>\r
<ClCompile Include="exception\win32_exception.cpp">\r
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
#include "../stdafx.h"\r
\r
#include "graph.h"\r
-#include "context.h"\r
\r
#pragma warning (disable : 4244)\r
\r
#include <array>\r
\r
namespace caspar { namespace diagnostics {\r
+ \r
+struct drawable : public sf::Drawable\r
+{\r
+ virtual ~drawable(){}\r
+ virtual void render(sf::RenderTarget& target) = 0;\r
+ virtual void Render(sf::RenderTarget& target) const { const_cast<drawable*>(this)->render(target);}\r
+};\r
+\r
+class context : public drawable\r
+{ \r
+ timer timer_;\r
+ sf::RenderWindow window_;\r
+ \r
+ std::list<std::shared_ptr<drawable>> drawables_;\r
+ \r
+ executor executor_;\r
+public: \r
+\r
+ template<typename Func>\r
+ static auto begin_invoke(Func&& func) -> boost::unique_future<decltype(func())> // noexcept\r
+ { \r
+ return get_instance().executor_.begin_invoke(std::forward<Func>(func)); \r
+ }\r
+\r
+ static void register_drawable(const std::shared_ptr<drawable>& drawable)\r
+ {\r
+ begin_invoke([=]\r
+ {\r
+ get_instance().do_register_drawable(drawable);\r
+ });\r
+ }\r
+ \r
+private:\r
+ context()\r
+ {\r
+ executor_.start();\r
+ executor_.begin_invoke([this]\r
+ {\r
+ window_.Create(sf::VideoMode(600, 1000), "CasparCG Diagnostics");\r
+ window_.SetPosition(0, 0);\r
+ window_.SetActive();\r
+ glEnable(GL_BLEND);\r
+ glEnable(GL_LINE_SMOOTH);\r
+ glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);\r
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\r
+ tick();\r
+ });\r
+ }\r
+\r
+ void tick()\r
+ {\r
+ sf::Event e;\r
+ while(window_.GetEvent(e)){} \r
+ glClear(GL_COLOR_BUFFER_BIT);\r
+ window_.Draw(*this);\r
+ window_.Display();\r
+ timer_.tick(1.0/50.0);\r
+ executor_.begin_invoke([this]{tick();});\r
+ }\r
+\r
+ void render(sf::RenderTarget& target)\r
+ {\r
+ auto count = std::max<size_t>(10, drawables_.size());\r
+ float target_dy = 1.0f/static_cast<float>(count);\r
+\r
+ float last_y = 0.0f;\r
+ int n = 0;\r
+ for(auto it = drawables_.begin(); it != drawables_.end(); ++n)\r
+ {\r
+ auto& drawable = *it;\r
+ if(!drawable.unique())\r
+ {\r
+ drawable->SetScale(static_cast<float>(window_.GetWidth()), static_cast<float>(target_dy*window_.GetHeight()));\r
+ float target_y = std::max(last_y, static_cast<float>(n * window_.GetHeight())*target_dy);\r
+ drawable->SetPosition(0.0f, target_y); \r
+ target.Draw(*drawable); \r
+ ++it; \r
+ }\r
+ else \r
+ it = drawables_.erase(it); \r
+ } \r
+ } \r
+ \r
+ void do_register_drawable(const std::shared_ptr<drawable>& drawable)\r
+ {\r
+ drawables_.push_back(drawable);\r
+ }\r
+ \r
+ static context& get_instance()\r
+ {\r
+ static context impl;\r
+ return impl;\r
+ }\r
+};\r
\r
class guide : public drawable\r
{\r
{\r
std::map<std::string, diagnostics::line> lines_;\r
std::string name_;\r
- float height_scale_;\r
\r
implementation(const std::string& name) \r
- : name_(name)\r
- , height_scale_(0){}\r
+ : name_(name){}\r
\r
void update(const std::string& name, float value)\r
{\r
private:\r
void render(sf::RenderTarget& target)\r
{\r
+ const size_t text_size = 15;\r
+ const size_t text_margin = 2;\r
+ const size_t text_offset = text_size+text_margin*2;\r
+\r
+ sf::String text(name_.c_str(), sf::Font::GetDefaultFont(), text_size);\r
+ text.SetStyle(sf::String::Italic);\r
+ text.Move(text_margin, text_margin);\r
+ \r
glPushMatrix();\r
- glScaled(1.0f, height_scale_, 1.0f);\r
- height_scale_ = std::min(1.0f, height_scale_+0.1f);\r
+ glScaled(1.0f/GetScale().x, 1.0f/GetScale().y, 1.0f);\r
+ target.Draw(text);\r
+ float x_offset = text.GetPosition().x + text.GetRect().Right + text_margin*4;\r
+ for(auto it = lines_.begin(); it != lines_.end(); ++it)\r
+ { \r
+ sf::String line_text(it->first, sf::Font::GetDefaultFont(), text_size);\r
+ line_text.SetPosition(x_offset, text_margin);\r
+ auto c = it->second.get_color();\r
+ line_text.SetColor(sf::Color(c.red*255.0f, c.green*255.0f, c.blue*255.0f, c.alpha*255.0f));\r
+ target.Draw(line_text);\r
+ x_offset = line_text.GetRect().Right + text_margin*2;\r
+ }\r
\r
- const size_t text_size = 15;\r
- const size_t text_margin = 2;\r
- const size_t text_offset = text_size+text_margin*2;\r
+ glDisable(GL_TEXTURE_2D);\r
+ glPopMatrix();\r
\r
- sf::String text(name_.c_str(), sf::Font::GetDefaultFont(), text_size);\r
- text.SetStyle(sf::String::Italic);\r
- text.Move(text_margin, text_margin);\r
- \r
- glPushMatrix();\r
- glScaled(1.0f/GetScale().x, 1.0f/GetScale().y, 1.0f);\r
- target.Draw(text);\r
- float x_offset = text.GetPosition().x + text.GetRect().Right + text_margin*4;\r
- for(auto it = lines_.begin(); it != lines_.end(); ++it)\r
- { \r
- sf::String line_text(it->first, sf::Font::GetDefaultFont(), text_size);\r
- line_text.SetPosition(x_offset, text_margin);\r
- auto c = it->second.get_color();\r
- line_text.SetColor(sf::Color(c.red*255.0f, c.green*255.0f, c.blue*255.0f, c.alpha*255.0f));\r
- target.Draw(line_text);\r
- x_offset = line_text.GetRect().Right + text_margin*2;\r
- }\r
-\r
- glDisable(GL_TEXTURE_2D);\r
- glPopMatrix();\r
-\r
- glBegin(GL_QUADS);\r
- glColor4f(1.0f, 1.0f, 1.0f, 0.2f); \r
- glVertex2f(1.0f, 0.99f);\r
- glVertex2f(0.0f, 0.99f);\r
- glVertex2f(0.0f, 0.01f); \r
- glVertex2f(1.0f, 0.01f); \r
- glEnd();\r
-\r
- glPushMatrix();\r
- glTranslated(0.0f, text_offset/GetScale().y, 1.0f);\r
- glScaled(1.0f, 1.0-text_offset/GetScale().y, 1.0f);\r
- \r
- target.Draw(diagnostics::guide(1.0f, color(1.0f, 1.0f, 1.0f, 0.6f)));\r
- target.Draw(diagnostics::guide(0.0f, color(1.0f, 1.0f, 1.0f, 0.6f)));\r
+ glBegin(GL_QUADS);\r
+ glColor4f(1.0f, 1.0f, 1.0f, 0.2f); \r
+ glVertex2f(1.0f, 0.99f);\r
+ glVertex2f(0.0f, 0.99f);\r
+ glVertex2f(0.0f, 0.01f); \r
+ glVertex2f(1.0f, 0.01f); \r
+ glEnd();\r
\r
- for(auto it = lines_.begin(); it != lines_.end(); ++it) \r
- target.Draw(it->second);\r
+ glPushMatrix();\r
+ glTranslated(0.0f, text_offset/GetScale().y, 1.0f);\r
+ glScaled(1.0f, 1.0-text_offset/GetScale().y, 1.0f);\r
\r
- glPopMatrix();\r
+ target.Draw(diagnostics::guide(1.0f, color(1.0f, 1.0f, 1.0f, 0.6f)));\r
+ target.Draw(diagnostics::guide(0.0f, color(1.0f, 1.0f, 1.0f, 0.6f)));\r
\r
+ for(auto it = lines_.begin(); it != lines_.end(); ++it) \r
+ target.Draw(it->second);\r
+ \r
glPopMatrix();\r
}\r
\r
\r
#include "transition_producer.h"\r
\r
-#include <common/diagnostics/graph.h>\r
-#include <common/utility/timer.h>\r
#include <core/video_format.h>\r
\r
#include <mixer/frame/draw_frame.h>\r
-#include <mixer/frame_mixer_device.h>\r
#include <mixer/image/image_transform.h>\r
#include <mixer/audio/audio_mixer.h>\r
#include <mixer/audio/audio_transform.h>\r
\r
-#include <boost/range/algorithm/copy.hpp>\r
-\r
namespace caspar { namespace core { \r
\r
struct transition_producer::implementation : boost::noncopyable\r
safe_ptr<frame_producer> source_producer_;\r
\r
std::shared_ptr<frame_factory> frame_factory_;\r
-\r
- safe_ptr<diagnostics::graph> graph_;\r
- timer perf_timer_;\r
-\r
+ \r
implementation(const safe_ptr<frame_producer>& dest, const transition_info& info) \r
: current_frame_(0)\r
, info_(info)\r
, dest_producer_(dest)\r
, source_producer_(frame_producer::empty())\r
- , graph_(diagnostics::create_graph(narrow(print())))\r
{\r
- graph_->guide("frame-time", 0.5);\r
- graph_->set_color("frame-time", diagnostics::color(1.0f, 0.0f, 0.0f));\r
- graph_->set_color("frames-left", diagnostics::color(0.0f, 1.0f, 0.0f));\r
}\r
\r
void initialize(const safe_ptr<frame_factory>& frame_factory)\r
}\r
\r
safe_ptr<draw_frame> receive()\r
- {\r
- perf_timer_.reset();\r
- auto frame = do_receive();\r
- graph_->update("frame-time", static_cast<float>(perf_timer_.elapsed()/frame_factory_->get_video_format_desc().interval*0.5));\r
- graph_->update("frames-left", static_cast<float>(info_.duration-current_frame_)/static_cast<float>(info_.duration));\r
- return frame;\r
- }\r
- \r
- safe_ptr<draw_frame> do_receive()\r
{\r
if(current_frame_++ >= info_.duration)\r
return draw_frame::eof();\r