]> git.sesse.net Git - casparcg/commitdiff
- Fixed diag to work with new SFML version.
authorHelge Norberg <helge.norberg@svt.se>
Wed, 4 Mar 2015 14:12:28 +0000 (15:12 +0100)
committerHelge Norberg <helge.norberg@svt.se>
Wed, 4 Mar 2015 14:12:28 +0000 (15:12 +0100)
- Added thread local contextual information which currently include channel and layer where applicable (used by diag).
- Created graph_sink abstraction, separating diag backend from diag API.
- Bundled liberation fonts for use with SFML font rendering.
- In addition to ordinary diag OSD window backend an OSC backend has also been implemented:
  /diag/[graph_id]/text <string> for the name of the graph
  /diag/[graph_id]/color/[value-name] <int> for the 32-bit rgba value of the color for the tag or value with the a given name.
  /diag/[graph_id]/context/channel <int> for the channel that the graph concerns (if any)
  /diag/[graph_id]/context/layer <int> for the layer that the graph concerns (if any)
  /diag/[graph_id]/value/[value-name] <float> for the value generally within 0.0 <= n <= 1.0
  /diag/[graph_id]/tag/[value-name] only sent when an "event" happens, like a dropped frame or similar. Generally no values are sent for value-names dedicated for tagging.

39 files changed:
.gitignore
common/diagnostics/graph.cpp
common/diagnostics/graph.h
common/prec_timer.cpp
common/prec_timer.h
core/core.vcxproj
core/core.vcxproj.filters
core/diagnostics/call_context.cpp [new file with mode: 0644]
core/diagnostics/call_context.h [new file with mode: 0644]
core/diagnostics/osd_graph.cpp [new file with mode: 0644]
core/diagnostics/osd_graph.h [new file with mode: 0644]
core/diagnostics/subject_diagnostics.cpp [new file with mode: 0644]
core/diagnostics/subject_diagnostics.h [new file with mode: 0644]
core/video_channel.cpp
core/video_channel.h
dependencies64/liberation-fonts/AUTHORS [new file with mode: 0644]
dependencies64/liberation-fonts/ChangeLog [new file with mode: 0644]
dependencies64/liberation-fonts/LICENSE [new file with mode: 0644]
dependencies64/liberation-fonts/LiberationMono-Bold.ttf [new file with mode: 0644]
dependencies64/liberation-fonts/LiberationMono-BoldItalic.ttf [new file with mode: 0644]
dependencies64/liberation-fonts/LiberationMono-Italic.ttf [new file with mode: 0644]
dependencies64/liberation-fonts/LiberationMono-Regular.ttf [new file with mode: 0644]
dependencies64/liberation-fonts/LiberationSans-Bold.ttf [new file with mode: 0644]
dependencies64/liberation-fonts/LiberationSans-BoldItalic.ttf [new file with mode: 0644]
dependencies64/liberation-fonts/LiberationSans-Italic.ttf [new file with mode: 0644]
dependencies64/liberation-fonts/LiberationSans-Regular.ttf [new file with mode: 0644]
dependencies64/liberation-fonts/LiberationSerif-Bold.ttf [new file with mode: 0644]
dependencies64/liberation-fonts/LiberationSerif-BoldItalic.ttf [new file with mode: 0644]
dependencies64/liberation-fonts/LiberationSerif-Italic.ttf [new file with mode: 0644]
dependencies64/liberation-fonts/LiberationSerif-Regular.ttf [new file with mode: 0644]
dependencies64/liberation-fonts/README [new file with mode: 0644]
dependencies64/liberation-fonts/TODO [new file with mode: 0644]
modules/decklink/consumer/decklink_consumer.cpp
modules/flash/producer/cg_proxy.cpp
protocol/amcp/AMCPCommandsImpl.cpp
protocol/cii/CIIProtocolStrategy.cpp
protocol/util/AsyncEventServer.cpp
shell/server.cpp
shell/shell.vcxproj

index ac34a309eae95c764e1b1f847d627fc79a618dff..62492071d8d8943a3355c0372106b67297350c06 100644 (file)
@@ -107,3 +107,4 @@ x64
 /clang-analyze.out
 *.suo
 /dependencies64/boost/stage/lib/libboost_wave-vc120-mt-gd-1_57.lib
+/shell/LiberationSans-Regular.ttf
index 03846f9d6f375dd24af94881a85e526c24b1e2ce..aba34f508a353fdc149de9eb7b4977139ce626ea 100644 (file)
 
 #include "graph.h"
 
-#pragma warning (disable : 4244)
+#include <boost/range/adaptor/transformed.hpp>
+#include <boost/thread.hpp>
 
-#include "../executor.h"
-#include "../lock.h"
-#include "../env.h"
-
-#include <SFML/Graphics.hpp>
-
-#include <boost/optional.hpp>
-#include <boost/circular_buffer.hpp>
-#include <boost/range/algorithm_ext/erase.hpp>
-
-#include <tbb/concurrent_unordered_map.h>
-#include <tbb/atomic.h>
 #include <tbb/spin_mutex.h>
 
-#include <GL/glew.h>
-
-#include <array>
-#include <numeric>
-#include <tuple>
-#include <memory>
+#include <vector>
 
 namespace caspar { namespace diagnostics {
                
@@ -67,516 +51,90 @@ std::tuple<float, float, float, float> color(int code)
        return std::make_tuple(r, g, b, a);
 }
 
-sf::Font& get_default_font()
-{
-       static sf::Font DEFAULT_FONT = []()
-       {
-               sf::Font font;
-               if (!font.loadFromFile("arial.ttf"))
-                       BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("arial.ttf not found"));
-               return font;
-       }();
-
-       return DEFAULT_FONT;
-}
+typedef std::vector<spi::sink_factory_t> sink_factories_t;
+static boost::mutex g_sink_factories_mutex;
+static sink_factories_t g_sink_factories;
 
-struct drawable : public sf::Drawable, public sf::Transformable
+std::vector<spl::shared_ptr<spi::graph_sink>> create_sinks()
 {
-       virtual ~drawable(){}
-       virtual void render(sf::RenderTarget& target, sf::RenderStates states) = 0;
-       virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override
-       {
-               states.transform *= getTransform();
-               glLoadMatrixf(states.transform.getMatrix());
-               const_cast<drawable*>(this)->render(target, states);
-       }
-};
-
-class context : public drawable
-{      
-       std::unique_ptr<sf::RenderWindow> window_;
-       
-       std::list<std::weak_ptr<drawable>> drawables_;
-               
-       executor executor_ = L"diagnostics";
-public:                                        
-
-       static void register_drawable(const std::shared_ptr<drawable>& drawable)
-       {
-               if(!drawable)
-                       return;
-
-               get_instance()->executor_.begin_invoke([=]
-               {
-                       get_instance()->do_register_drawable(drawable);
-               }, task_priority::high_priority);
-       }
-
-       static void show(bool value)
-       {
-               get_instance()->executor_.begin_invoke([=]
-               {       
-                       get_instance()->do_show(value);
-               }, task_priority::high_priority);
-       }
-       
-       static void shutdown()
-       {
-               get_instance().reset();
-       }
-private:
-       context()
-       {
-               executor_.begin_invoke([=]
-               {                       
-                       SetThreadPriority(GetCurrentThread(), BELOW_NORMAL_PRIORITY_CLASS);
-               });
-       }
-
-       void do_show(bool value)
-       {
-               if(value)
-               {
-                       if(!window_)
-                       {
-                               window_.reset(new sf::RenderWindow(sf::VideoMode(750, 750), "CasparCG Diagnostics"));
-                               window_->setPosition(sf::Vector2i(0, 0));
-                               window_->setActive();
-                               glEnable(GL_BLEND);
-                               glEnable(GL_LINE_SMOOTH);
-                               glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
-                               glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-                               tick();
-                       }
-               }
-               else
-                       window_.reset();
-       }
-
-       void tick()
-       {
-               if(!window_)
-                       return;
-
-               sf::Event e;
-               while(window_->pollEvent(e))
-               {
-                       if(e.type == sf::Event::Closed)
-                       {
-                               window_.reset();
-                               return;
-                       }
-               }               
-               //glClear(GL_COLOR_BUFFER_BIT);
-               window_->clear();
-               window_->draw(*this);
-               window_->display();
-               boost::this_thread::sleep(boost::posix_time::milliseconds(10));
-               executor_.begin_invoke([this]{tick();});
-       }
-
-       void render(sf::RenderTarget& target, sf::RenderStates states)
-       {
-               auto count = std::max<size_t>(8, drawables_.size());
-               float target_dy = 1.0f/static_cast<float>(count);
-
-               float last_y = 0.0f;
-               int n = 0;
-               for(auto it = drawables_.begin(); it != drawables_.end(); ++n)
-               {
-                       auto drawable = it->lock();
-                       if(drawable)
-                       {
-                               drawable->setScale(static_cast<float>(window_->getSize().x), static_cast<float>(target_dy*window_->getSize().y));
-                               float target_y = std::max(last_y, static_cast<float>(n * window_->getSize().y)*target_dy);
-                               drawable->setPosition(0.0f, target_y);                  
-                               target.draw(*drawable, states);
-                               ++it;           
-                       }
-                       else    
-                               it = drawables_.erase(it);                      
-               }
-       }       
-       
-       void do_register_drawable(const std::shared_ptr<drawable>& drawable)
-       {
-               drawables_.push_back(drawable);
-               auto it = drawables_.begin();
-               while(it != drawables_.end())
-               {
-                       if(it->lock())
-                               ++it;
-                       else    
-                               it = drawables_.erase(it);                      
-               }
-       }
-       
-       static std::unique_ptr<context>& get_instance()
-       {
-               static auto impl = std::unique_ptr<context>(new context);
-               return impl;
-       }
-};
+       boost::lock_guard<boost::mutex> lock(g_sink_factories_mutex);
+       auto sinks = g_sink_factories | boost::adaptors::transformed([](const spi::sink_factory_t& s){ return s(); });
+       return std::vector<spl::shared_ptr<spi::graph_sink>>(std::begin(sinks), std::end(sinks));
+}
 
-class line : public drawable
+struct graph::impl
 {
-       boost::circular_buffer<std::pair<float, bool>> line_data_;
-
-       tbb::atomic<float>      tick_data_;
-       tbb::atomic<bool>       tick_tag_;
-       tbb::atomic<int>        color_;
+       std::vector<spl::shared_ptr<spi::graph_sink>> sinks_ = create_sinks();
 public:
-       line(size_t res = 1200)
-               : line_data_(res)
-       {
-               tick_data_      = -1.0f;
-               color_          = 0xFFFFFFFF;
-               tick_tag_       = false;
-
-               line_data_.push_back(std::make_pair(-1.0f, false));
-       }
-       
-       void set_value(float value)
-       {
-               tick_data_ = value;
-       }
-       
-       void set_tag()
-       {
-               tick_tag_ = true;
-       }
-               
-       void set_color(int color)
+       impl()
        {
-               color_ = color;
        }
 
-       int get_color()
+       void activate()
        {
-               return color_;
+               for (auto& sink : sinks_)
+                       sink->activate();
        }
-               
-       void render(sf::RenderTarget& target, sf::RenderStates states)
-       {
-               float dx = 1.0f/static_cast<float>(line_data_.capacity());
-               float x = static_cast<float>(line_data_.capacity()-line_data_.size())*dx;
-
-               line_data_.push_back(std::make_pair(tick_data_, tick_tag_));            
-               tick_tag_   = false;
-                               
-               glBegin(GL_LINE_STRIP);
-               auto c = color(color_);
-               glColor4f(std::get<0>(c), std::get<1>(c), std::get<2>(c), 0.8f);                
-               for(size_t n = 0; n < line_data_.size(); ++n)           
-                       if(line_data_[n].first > -0.5)
-                               glVertex3d(x+n*dx, std::max(0.05, std::min(0.95, (1.0f-line_data_[n].first)*0.8 + 0.1f)), 0.0);         
-               glEnd();
-                               
-               glEnable(GL_LINE_STIPPLE);
-               glLineStipple(3, 0xAAAA);
-               for(size_t n = 0; n < line_data_.size(); ++n)   
-               {
-                       if(line_data_[n].second)
-                       {
-                               glBegin(GL_LINE_STRIP);                 
-                                       glVertex3f(x+n*dx, 0.0f, 0.0f);                         
-                                       glVertex3f(x+n*dx, 1.0f, 0.0f);         
-                               glEnd();
-                       }
-               }
-               glDisable(GL_LINE_STIPPLE);
-       }
-};
 
-struct graph::impl : public drawable
-{
-       tbb::concurrent_unordered_map<std::string, diagnostics::line> lines_;
-
-       tbb::spin_mutex mutex_;
-       std::wstring text_;
-       bool auto_reset_ = false;
-
-       impl()
-       {
-       }
-               
        void set_text(const std::wstring& value)
        {
-               auto temp = value;
-               lock(mutex_, [&]
-               {
-                       text_ = std::move(temp);
-               });
+               for (auto& sink : sinks_)
+                       sink->set_text(value);
        }
 
        void set_value(const std::string& name, double value)
        {
-               lines_[name].set_value(value);
+               for (auto& sink : sinks_)
+                       sink->set_value(name, value);
        }
 
        void set_tag(const std::string& name)
        {
-               lines_[name].set_tag();
+               for (auto& sink : sinks_)
+                       sink->set_tag(name);
        }
 
        void set_color(const std::string& name, int color)
        {
-               lines_[name].set_color(color);
+               for (auto& sink : sinks_)
+                       sink->set_color(name, color);
        }
+
        void auto_reset()
        {
-               lock(mutex_, [this]
-               {
-                       auto_reset_ = true;
-               });
+               for (auto& sink : sinks_)
+                       sink->auto_reset();
        }
                
 private:
-       void render(sf::RenderTarget& target, sf::RenderStates states)
-       {
-               const size_t text_size = 15;
-               const size_t text_margin = 2;
-               const size_t text_offset = (text_size+text_margin*2)*2;
-
-               std::wstring text_str;
-               bool auto_reset;
-
-               {
-                       tbb::spin_mutex::scoped_lock lock(mutex_);
-                       text_str = text_;
-                       auto_reset = auto_reset_;
-               }
-
-               //sf::Text test("Test", get_default_font());
-               //target.draw(test, states);
-
-               sf::Text text(text_str.c_str(), get_default_font(), text_size);
-               text.setStyle(sf::Text::Italic);
-               text.move(text_margin, text_margin);
-               
-               //glPushMatrix();
-                       //glScaled(1.0f/getScale().x, 1.0f/getScale().y, 1.0f);
-                       target.draw(text, states);
-                       float x_offset = text_margin;
-                       for(auto it = lines_.begin(); it != lines_.end(); ++it)
-                       {
-                               sf::Text line_text(it->first, get_default_font(), text_size);
-                               line_text.setPosition(x_offset, text_margin+text_offset/2);
-                               auto c = it->second.get_color();
-                               line_text.setColor(sf::Color((c >> 24) & 255, (c >> 16) & 255, (c >> 8) & 255, (c >> 0) & 255));
-                               target.draw(line_text, states);
-                               x_offset += (line_text.getLocalBounds().width/* - line_text.getLocalBounds().left*/) + text_margin * 2;
-                       }
-
-                       glDisable(GL_TEXTURE_2D);
-               //glPopMatrix();
-
-               static auto rect = []()
-               {
-                       sf::RectangleShape r(sf::Vector2f(1.0f, 0.99f));
-                       r.setFillColor(sf::Color(255, 255, 255, 51));
-                       r.setOutlineThickness(0.00f);
-                       return r;
-               }();
-               target.draw(rect, states);
-               /*glBegin(GL_QUADS);
-                       glColor4f(1.0f, 1.0f, 1.0f, 0.2f);      
-                       glVertex2f(1.0f, 0.99f);
-                       glVertex2f(0.0f, 0.99f);
-                       glVertex2f(0.0f, 0.01f);        
-                       glVertex2f(1.0f, 0.01f);        
-               glEnd();*/
-
-               states.transform
-                       .translate(0, text_offset)
-                       .scale(1.0f, text_offset / getScale().y);
-               //glLoadMatrixf(states.transform.getMatrix());
-               //glPushMatrix();
-                       //glTranslated(0.0f, text_offset/getScale().y, 1.0f);
-                       //glScaled(1.0f, 1.0-text_offset/getScale().y, 1.0f);
-               
-                       glEnable(GL_LINE_STIPPLE);
-                       glLineStipple(3, 0xAAAA);
-                       glColor4f(1.0f, 1.0f, 1.9f, 0.5f);      
-                       glBegin(GL_LINE_STRIP);         
-                               glVertex3f(0.0f, (1.0f-0.5f) * 0.8f + 0.1f, 0.0f);              
-                               glVertex3f(1.0f, (1.0f-0.5f) * 0.8f + 0.1f, 0.0f);      
-                       glEnd();
-                       glBegin(GL_LINE_STRIP);         
-                               glVertex3f(0.0f, (1.0f-0.0f) * 0.8f + 0.1f, 0.0f);              
-                               glVertex3f(1.0f, (1.0f-0.0f) * 0.8f + 0.1f, 0.0f);      
-                       glEnd();
-                       glBegin(GL_LINE_STRIP);         
-                               glVertex3f(0.0f, (1.0f-1.0f) * 0.8f + 0.1f, 0.0f);              
-                               glVertex3f(1.0f, (1.0f-1.0f) * 0.8f + 0.1f, 0.0f);      
-                       glEnd();
-                       glDisable(GL_LINE_STIPPLE);
-
-                       //target.Draw(diagnostics::guide(1.0f, color(1.0f, 1.0f, 1.0f, 0.6f)));
-                       //target.Draw(diagnostics::guide(0.0f, color(1.0f, 1.0f, 1.0f, 0.6f)));
-
-                       for(auto it = lines_.begin(); it != lines_.end(); ++it)         
-                       {
-                               target.draw(it->second, states);
-                               if(auto_reset)
-                                       it->second.set_value(0.0f);
-                       }
-               
-               //glPopMatrix();
-       }
-
        impl(impl&);
        impl& operator=(impl&);
 };
        
-graph::graph() : impl_(new impl())
+graph::graph() : impl_(new impl)
 {
 }
 
-void graph::set_text(const std::wstring& value){impl_->set_text(value);}
-void graph::set_value(const std::string& name, double value){impl_->set_value(name, value);}
-void graph::set_color(const std::string& name, int color){impl_->set_color(name, color);}
-void graph::set_tag(const std::string& name){impl_->set_tag(name);}
-void graph::auto_reset(){impl_->auto_reset(); }
+void graph::set_text(const std::wstring& value) { impl_->set_text(value); }
+void graph::set_value(const std::string& name, double value) { impl_->set_value(name, value); }
+void graph::set_color(const std::string& name, int color) { impl_->set_color(name, color); }
+void graph::set_tag(const std::string& name) { impl_->set_tag(name); }
+void graph::auto_reset() { impl_->auto_reset(); }
+
 void register_graph(const spl::shared_ptr<graph>& graph)
 {
-       context::register_drawable(graph->impl_);
+       graph->impl_->activate();
 }
 
-void show_graphs(bool value)
-{
-       context::show(value);
-}
+namespace spi {
 
-void shutdown()
+void register_sink_factory(sink_factory_t factory)
 {
-       context::shutdown();
+       boost::lock_guard<boost::mutex> lock(g_sink_factories_mutex);
+
+       g_sink_factories.push_back(std::move(factory));
 }
 
-//namespace v2
-//{    
-//     
-//struct line::impl
-//{
-//     std::wstring name_;
-//     boost::circular_buffer<data> ticks_;
-//
-//     impl(const std::wstring& name) 
-//             : name_(name)
-//             , ticks_(1024){}
-//     
-//     void set_value(float value)
-//     {
-//             ticks_.push_back();
-//             ticks_.back().value = value;
-//     }
-//
-//     void set_value(float value)
-//     {
-//             ticks_.clear();
-//             set_value(value);
-//     }
-//};
-//
-//line::line(){}
-//line::line(const std::wstring& name) : impl_(new impl(name)){}
-//std::wstring line::print() const {return impl_->name_;}
-//void line::set_value(float value){impl_->set_value(value);}
-//void line::set_value(float value){impl_->set_value(value);}
-//boost::circular_buffer<data>& line::ticks() { return impl_->ticks_;}
-//
-//struct graph::impl
-//{
-//     std::map<std::wstring, line> lines_;
-//     color                                            color_;
-//     printer                                          printer_;
-//
-//     impl(const std::wstring& name) 
-//             : printer_([=]{return name;}){}
-//
-//     impl(const printer& parent_printer) 
-//             : printer_(parent_printer){}
-//     
-//     void set_value(const std::wstring& name, float value)
-//     {
-//             auto it = lines_.find(name);
-//             if(it == lines_.end())
-//                     it = lines_.insert(std::make_pair(name, line(name))).first;
-//
-//             it->second.set_value(value);
-//     }
-//
-//     void set_value(const std::wstring& name, float value)
-//     {
-//             auto it = lines_.find(name);
-//             if(it == lines_.end())
-//                     it = lines_.insert(std::make_pair(name, line(name))).first;
-//
-//             it->second.set_value(value);
-//     }
-//     
-//     void set_color(const std::wstring& name, color color)
-//     {
-//             color_ = color;
-//     }
-//
-//     std::map<std::wstring, line>& get_lines()
-//     {
-//             return lines_;
-//     }
-//     
-//     color get_color() const
-//     {
-//             return color_;
-//     }
-//
-//     std::wstring print() const
-//     {
-//             return printer_ ? printer_() : L"graph";
-//     }
-//};
-//     
-//graph::graph(const std::wstring& name) : impl_(new impl(name)){}
-//graph::graph(const printer& parent_printer) : impl_(new impl(parent_printer)){}
-//void graph::set_value(const std::wstring& name, float value){impl_->set_value(name, value);}
-//void graph::set_value(const std::wstring& name, float value){impl_->set_value(name, value);}
-//void graph::set_color(const std::wstring& name, color c){impl_->set_color(name, c);}
-//color graph::get_color() const {return impl_->get_color();}
-//std::wstring graph::print() const {return impl_->print();}
-//
-//spl::shared_ptr<graph> graph::clone() const 
-//{
-//     spl::shared_ptr<graph> clone(new graph(std::wstring(L"")));
-//     clone->impl_->printer_ = impl_->printer_;
-//     clone->impl_->lines_ = impl_->lines_;
-//     clone->impl_->color_ = impl_->color_;   
-//}
-//
-//std::map<std::wstring, line>& graph::get_lines() {impl_->get_lines();}
-//
-//std::vector<spl::shared_ptr<graph>> g_graphs;
-//
-//spl::shared_ptr<graph> create_graph(const std::string& name)
-//{
-//     g_graphs.push_back(spl::make_shared<graph>(name));
-//     return g_graphs.back();
-//}
-//
-//spl::shared_ptr<graph> create_graph(const printer& parent_printer)
-//{
-//     g_graphs.push_back(spl::make_shared<graph>(parent_printer));
-//     return g_graphs.back();
-//}
-//
-//static std::vector<spl::shared_ptr<graph>> get_all_graphs()
-//{
-//     std::vector<spl::shared_ptr<graph>> graphs;
-//     BOOST_FOREACH(auto& graph, g_graphs)
-//             graphs.push_back(graph->clone());
-//
-//     return graphs;
-//}
-//
-//}
+}
 
 }}
\ No newline at end of file
index b23e2fff4ac2e7422f8f6352bbbf5aa363c73168..f925b78b690be9f3237e81cbce2feae9438ec37c 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <string>
 #include <tuple>
+#include <functional>
 
 #include <boost/noncopyable.hpp>
 
@@ -49,7 +50,24 @@ private:
 };
 
 void register_graph(const spl::shared_ptr<graph>& graph);
-void show_graphs(bool value);
-void shutdown();
+
+namespace spi {
+
+class graph_sink : boost::noncopyable
+{
+public:
+       virtual ~graph_sink() { }
+       virtual void activate() = 0;
+       virtual void set_text(const std::wstring& value) = 0;
+       virtual void set_value(const std::string& name, double value) = 0;
+       virtual void set_color(const std::string& name, int color) = 0;
+       virtual void set_tag(const std::string& name) = 0;
+       virtual void auto_reset() = 0;
+};
+
+typedef std::function<spl::shared_ptr<graph_sink>()> sink_factory_t;
+void register_sink_factory(sink_factory_t factory);
+
+}
 
 }}
\ No newline at end of file
index 94c01730aa7a45418a520dfa374be0840b331a54..12d94f1ab579b84ce7fc9584b5a4074d905d94a7 100644 (file)
@@ -37,23 +37,27 @@ prec_timer::prec_timer()
 // Author: Ryan M. Geiss
 // http://www.geisswerks.com/ryan/FAQS/timing.html
 void prec_timer::tick(double interval)
-{      
+{
+       tick_millis(static_cast<int64_t>(interval * 1000.0));
+}
+
+void prec_timer::tick_millis(int64_t ticks_to_wait)
+{
        auto t = ::timeGetTime();
 
        if (time_ != 0)
        {
-               auto ticks_to_wait = static_cast<DWORD>(interval*1000.0);
                bool done = 0;
                do
-               {                               
+               {
                        auto ticks_passed = t - time_;
-                       auto ticks_left   = ticks_to_wait - ticks_passed;
+                       auto ticks_left = ticks_to_wait - ticks_passed;
 
                        if (t < time_)    // time wrap
                                done = 1;
                        if (ticks_passed >= ticks_to_wait)
                                done = 1;
-                               
+
                        if (!done)
                        {
                                // if > 0.002s left, do Sleep(1), which will actually sleep some 
@@ -64,17 +68,16 @@ void prec_timer::tick(double interval)
                                //   amount of time.
                                if (ticks_left > 2)
                                        Sleep(1);
-                               else                        
-                                       for (int i = 0; i < 10; ++i) 
+                               else
+                                       for (int i = 0; i < 10; ++i)
                                                Sleep(0);  // causes thread to give up its timeslice
                        }
 
                        t = ::timeGetTime();
-               }
-               while (!done);            
+               } while (!done);
        }
 
        time_ = t;
-}      
+}
 
 }
\ No newline at end of file
index d0a11e74ac26405d3ca19404cf3431534a710fc9..e41fccc5f0d88bf63e4ad375e37066cde795e40f 100644 (file)
@@ -21,6 +21,8 @@
 
 #pragma once
 
+#include <cstdint>
+
 namespace caspar {
        
 class prec_timer
@@ -31,6 +33,7 @@ public:
        // Author: Ryan M. Geiss
        // http://www.geisswerks.com/ryan/FAQS/timing.html
        void tick(double interval);
+       void tick_millis(int64_t interval);
 
 private:       
        unsigned long time_;
index d730165f139a527a6c1969fe9d1c2f4c57298cc0..af2de85fe0aa0ec465cb38ebb763b81714db3967 100644 (file)
   </ItemDefinitionGroup>\r
   <ItemGroup>\r
     <ClInclude Include="consumer\port.h" />\r
+    <ClInclude Include="diagnostics\call_context.h" />\r
+    <ClInclude Include="diagnostics\osd_graph.h" />\r
+    <ClInclude Include="diagnostics\subject_diagnostics.h" />\r
     <ClInclude Include="frame\draw_frame.h" />\r
     <ClInclude Include="frame\frame.h" />\r
     <ClInclude Include="frame\frame_factory.h" />\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../StdAfx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">../StdAfx.h</PrecompiledHeaderFile>\r
     </ClCompile>\r
+    <ClCompile Include="diagnostics\call_context.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="diagnostics\osd_graph.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="diagnostics\subject_diagnostics.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
     <ClCompile Include="frame\frame.cpp">\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../StdAfx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">../StdAfx.h</PrecompiledHeaderFile>\r
index 2fb7c2abfd2bed60edffcd1ebc0d6695ea31dbd2..8829ddc465299aca9f925ce51010898cfd9bd8df 100644 (file)
@@ -49,6 +49,9 @@
     <Filter Include="source\producer\text\utils">\r
       <UniqueIdentifier>{fc435676-34ca-46fe-bbcf-2fbad8e3cd21}</UniqueIdentifier>\r
     </Filter>\r
+    <Filter Include="source\diagnostics">\r
+      <UniqueIdentifier>{42cbb33e-a2fd-43a1-86fb-204caa2afc13}</UniqueIdentifier>\r
+    </Filter>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ClInclude Include="producer\transition\transition_producer.h">\r
     <ClInclude Include="thumbnail_generator.h">\r
       <Filter>source</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="diagnostics\subject_diagnostics.h">\r
+      <Filter>source\diagnostics</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="diagnostics\call_context.h">\r
+      <Filter>source\diagnostics</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="diagnostics\osd_graph.h">\r
+      <Filter>source\diagnostics</Filter>\r
+    </ClInclude>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ClCompile Include="producer\transition\transition_producer.cpp">\r
     <ClCompile Include="thumbnail_generator.cpp">\r
       <Filter>source</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="diagnostics\subject_diagnostics.cpp">\r
+      <Filter>source\diagnostics</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="diagnostics\call_context.cpp">\r
+      <Filter>source\diagnostics</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="diagnostics\osd_graph.cpp">\r
+      <Filter>source\diagnostics</Filter>\r
+    </ClCompile>\r
   </ItemGroup>\r
 </Project>
\ No newline at end of file
diff --git a/core/diagnostics/call_context.cpp b/core/diagnostics/call_context.cpp
new file mode 100644 (file)
index 0000000..b5cc0db
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>
+*
+* This file is part of CasparCG (www.casparcg.com).
+*
+* CasparCG 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 3 of the License, or
+* (at your option) any later version.
+*
+* CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.
+*
+* Author: Helge Norberg, helge.norberg@svt.se
+*/
+
+#include "../StdAfx.h"
+
+#include "call_context.h"
+
+#include <boost/thread/tss.hpp>
+
+namespace caspar { namespace core { namespace diagnostics {
+
+call_context& call_context::for_thread()
+{
+       static boost::thread_specific_ptr<call_context> contexts;
+
+       auto local = contexts.get();
+
+       if (!local)
+       {
+               local = new call_context;
+               contexts.reset(local);
+       }
+
+       return *local;
+}
+
+}}}
diff --git a/core/diagnostics/call_context.h b/core/diagnostics/call_context.h
new file mode 100644 (file)
index 0000000..35a8828
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>
+*
+* This file is part of CasparCG (www.casparcg.com).
+*
+* CasparCG 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 3 of the License, or
+* (at your option) any later version.
+*
+* CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.
+*
+* Author: Helge Norberg, helge.norberg@svt.se
+*/
+
+#pragma once
+
+namespace caspar { namespace core { namespace diagnostics {
+
+struct call_context
+{
+       int             video_channel   = -1;
+       int             layer                   = -1;
+
+       static call_context& for_thread();
+};
+
+class scoped_call_context : boost::noncopyable
+{
+       call_context    saved_ = call_context::for_thread();
+public:
+       ~scoped_call_context()
+       {
+               call_context::for_thread() = saved_;
+       }
+};
+
+}}}
diff --git a/core/diagnostics/osd_graph.cpp b/core/diagnostics/osd_graph.cpp
new file mode 100644 (file)
index 0000000..13f774f
--- /dev/null
@@ -0,0 +1,554 @@
+/*
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>
+*
+* This file is part of CasparCG (www.casparcg.com).
+*
+* CasparCG 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 3 of the License, or
+* (at your option) any later version.
+*
+* CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.
+*
+* Author: Robert Nagy, ronag89@gmail.com
+*/
+
+#include "../stdafx.h"
+
+#include "osd_graph.h"
+
+#pragma warning (disable : 4244)
+
+#include "call_context.h"
+
+#include <common/executor.h>
+#include <common/lock.h>
+#include <common/env.h>
+#include <common/prec_timer.h>
+
+#include <SFML/Graphics.hpp>
+
+#include <boost/optional.hpp>
+#include <boost/circular_buffer.hpp>
+#include <boost/lexical_cast.hpp>
+
+#include <tbb/concurrent_unordered_map.h>
+#include <tbb/atomic.h>
+#include <tbb/spin_mutex.h>
+
+#include <GL/glew.h>
+
+#include <numeric>
+#include <tuple>
+#include <memory>
+
+#include <Windows.h>
+
+namespace caspar { namespace core { namespace diagnostics { namespace osd {
+
+static const int PREFERRED_VERTICAL_GRAPHS = 8;
+static const int RENDERING_WIDTH = 750;
+static const int RENDERING_HEIGHT = RENDERING_WIDTH / PREFERRED_VERTICAL_GRAPHS;
+
+sf::Color get_sfml_color(int color)
+{
+       auto c = caspar::diagnostics::color(color);
+
+       return {
+               (color >> 24) & 255,
+               (color >> 16) & 255,
+               (color >> 8) & 255,
+               (color >> 0) & 255
+       };
+}
+
+sf::Font& get_default_font()
+{
+       static sf::Font DEFAULT_FONT = []()
+       {
+               sf::Font font;
+               if (!font.loadFromFile("LiberationSans-Regular.ttf"))
+                       BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("LiberationSans-Regular.ttf not found"));
+               return font;
+       }();
+
+       return DEFAULT_FONT;
+}
+
+struct drawable : public sf::Drawable, public sf::Transformable
+{
+       virtual ~drawable(){}
+       virtual void render(sf::RenderTarget& target, sf::RenderStates states) = 0;
+       virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override
+       {
+               states.transform *= getTransform();
+               const_cast<drawable*>(this)->render(target, states);
+       }
+};
+
+class context : public drawable
+{      
+       std::unique_ptr<sf::RenderWindow>       window_;
+       sf::View                                                        view_;
+       
+       std::list<std::weak_ptr<drawable>>      drawables_;
+       int64_t                                                         refresh_rate_millis_            = 16;
+       boost::timer                                            display_time_;
+       bool                                                            calculate_view_;
+       int                                                                     scroll_position_                        = 0;
+       bool                                                            dragging_                                       = false;
+       int                                                                     last_mouse_y_;
+
+       executor                                                        executor_                                       = L"diagnostics";
+public:                                        
+
+       static void register_drawable(const std::shared_ptr<drawable>& drawable)
+       {
+               if(!drawable)
+                       return;
+
+               get_instance()->executor_.begin_invoke([=]
+               {
+                       get_instance()->do_register_drawable(drawable);
+               }, task_priority::high_priority);
+       }
+
+       static void show(bool value)
+       {
+               get_instance()->executor_.begin_invoke([=]
+               {       
+                       get_instance()->do_show(value);
+               }, task_priority::high_priority);
+       }
+       
+       static void shutdown()
+       {
+               get_instance().reset();
+       }
+private:
+       context()
+       {
+               executor_.begin_invoke([=]
+               {                       
+                       SetThreadPriority(GetCurrentThread(), BELOW_NORMAL_PRIORITY_CLASS);
+               });
+       }
+
+       void do_show(bool value)
+       {
+               if(value)
+               {
+                       if(!window_)
+                       {
+                               window_.reset(new sf::RenderWindow(sf::VideoMode(RENDERING_WIDTH, RENDERING_WIDTH), "CasparCG Diagnostics"));
+                               window_->setPosition(sf::Vector2i(0, 0));
+                               window_->setActive();
+                               window_->setVerticalSyncEnabled(true);
+                               calculate_view_ = true;
+                               glEnable(GL_BLEND);
+                               glEnable(GL_LINE_SMOOTH);
+                               glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
+                               glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+                               tick();
+                       }
+               }
+               else
+                       window_.reset();
+       }
+
+       void tick()
+       {
+               if(!window_)
+                       return;
+
+               sf::Event e;
+               while (window_->pollEvent(e))
+               {
+                       switch (e.type)
+                       {
+                       case sf::Event::Closed:
+                               window_.reset();
+                               return;
+                       case sf::Event::Resized:
+                               calculate_view_ = true;
+                               break;
+                       case sf::Event::MouseButtonPressed:
+                               dragging_ = true;
+                               last_mouse_y_ = e.mouseButton.y;
+                               break;
+                       case sf::Event::MouseButtonReleased:
+                               dragging_ = false;
+                               break;
+                       case sf::Event::MouseMoved:
+                               if (dragging_)
+                               {
+                                       auto delta_y = e.mouseMove.y - last_mouse_y_;
+                                       scroll_position_ += delta_y;
+                                       last_mouse_y_ = e.mouseMove.y;
+                                       calculate_view_ = true;
+                               }
+
+                               break;
+                       case sf::Event::MouseWheelMoved:
+                               scroll_position_ += e.mouseWheel.delta * 15;
+                               calculate_view_ = true;
+                               break;
+                       }
+               }
+
+               window_->clear();
+
+               if (calculate_view_)
+               {
+                       view_.setViewport(sf::FloatRect(0, 0, 1.0, 1.0));
+                       view_.setSize(RENDERING_WIDTH, window_->getSize().y);
+                       view_.setCenter(RENDERING_WIDTH / 2, window_->getSize().y / 2 - scroll_position_);
+                       window_->setView(view_);
+                       calculate_view_ = false;
+               }
+
+               window_->draw(*this);
+
+               static const auto THRESHOLD = 1;
+               int64_t since_last_refresh = display_time_.elapsed() * 1000;
+               int64_t until_next_refresh = refresh_rate_millis_ - since_last_refresh;
+               int64_t sleep_for = until_next_refresh - THRESHOLD;
+
+               if (sleep_for > 0)
+               {
+                       prec_timer timer;
+                       timer.tick_millis(0);
+                       timer.tick_millis(sleep_for);
+               }
+
+               window_->display();
+               display_time_.restart();
+               executor_.begin_invoke([this]{tick();});
+       }
+
+       void render(sf::RenderTarget& target, sf::RenderStates states)
+       {
+               int n = 0;
+
+               for (auto it = drawables_.begin(); it != drawables_.end(); ++n)
+               {
+                       auto drawable = it->lock();
+                       if (drawable)
+                       {
+                               float target_y = n * RENDERING_HEIGHT;
+                               drawable->setPosition(0.0f, target_y);                  
+                               target.draw(*drawable, states);
+                               ++it;           
+                       }
+                       else    
+                               it = drawables_.erase(it);
+               }
+       }       
+       
+       void do_register_drawable(const std::shared_ptr<drawable>& drawable)
+       {
+               drawables_.push_back(drawable);
+               auto it = drawables_.begin();
+               while(it != drawables_.end())
+               {
+                       if(it->lock())
+                               ++it;
+                       else    
+                               it = drawables_.erase(it);                      
+               }
+       }
+       
+       static std::unique_ptr<context>& get_instance()
+       {
+               static auto impl = std::unique_ptr<context>(new context);
+               return impl;
+       }
+};
+
+class line : public drawable
+{
+       size_t                                                                                                          res_;
+       boost::circular_buffer<sf::Vertex>                                                      line_data_      { res_ };
+       boost::circular_buffer<boost::optional<sf::VertexArray>>        line_tags_      { res_ };
+
+       tbb::atomic<float>                                                                                      tick_data_;
+       tbb::atomic<bool>                                                                                       tick_tag_;
+       tbb::atomic<int>                                                                                        color_;
+
+       double                                                                                                          x_delta_        = 1.0 / (res_ - 1);
+       //double                                                                                                                x_pos_          = 1.0;
+public:
+       line(size_t res = 750)
+               : res_(res)
+       {
+               tick_data_      = -1.0f;
+               color_          = 0xFFFFFFFF;
+               tick_tag_       = false;
+       }
+       
+       void set_value(float value)
+       {
+               tick_data_ = value;
+       }
+       
+       void set_tag()
+       {
+               tick_tag_ = true;
+       }
+               
+       void set_color(int color)
+       {
+               color_ = color;
+       }
+
+       int get_color()
+       {
+               return color_;
+       }
+               
+       void render(sf::RenderTarget& target, sf::RenderStates states)
+       {
+               /*states.transform.translate(x_pos_, 0.f);
+
+               if (line_data_.size() == res_)
+                       x_pos_ = -get_insertion_xcoord() + 1.0 - x_delta_; // Otherwise the graph will drift because of floating point precision
+               else
+                       x_pos_ -= x_delta_;*/
+
+               for (auto& vertex : line_data_)
+                       vertex.position.x -= x_delta_;
+
+               auto color = get_sfml_color(color_);
+               color.a = 255 * 0.8;
+               line_data_.push_back(sf::Vertex(sf::Vector2f(get_insertion_xcoord(), std::max(0.05, std::min(0.95, (1.0f - tick_data_) * 0.8 + 0.1f))), color));
+
+               if (tick_tag_)
+               {
+                       sf::VertexArray vertical_dash(sf::LinesStrip);
+                       vertical_dash.append(sf::Vertex(sf::Vector2f(get_insertion_xcoord() - x_delta_, 0.f), color));
+                       vertical_dash.append(sf::Vertex(sf::Vector2f(get_insertion_xcoord() - x_delta_, 1.f), color));
+                       line_tags_.push_back(vertical_dash);
+               }
+               else
+                       line_tags_.push_back(boost::none);
+
+               tick_tag_ = false;
+
+               if (tick_data_ > -0.5)
+               {
+                       auto array_one = line_data_.array_one();
+                       auto array_two = line_data_.array_two();
+                       // since boost::circular_buffer guarantees two contigous views of the buffer we can provide raw access to SFML, which can use glDrawArrays.
+                       target.draw(array_one.first, static_cast<unsigned int>(array_one.second), sf::LinesStrip, states);
+                       target.draw(array_two.first, static_cast<unsigned int>(array_two.second), sf::LinesStrip, states);
+
+                       if (array_one.second > 0 && array_two.second > 0)
+                       {
+                               // Connect the gap between the arrays
+                               sf::VertexArray connecting_line(sf::LinesStrip);
+                               connecting_line.append(*(array_one.first + array_one.second - 1));
+                               connecting_line.append(*(array_two.first));
+                               target.draw(connecting_line, states);
+                       }
+               }
+               else
+               {
+                       glEnable(GL_LINE_STIPPLE);
+                       glLineStipple(3, 0xAAAA);
+
+                       for (size_t n = 0; n < line_tags_.size(); ++n)
+                       {
+                               if (line_tags_[n])
+                               {
+                                       target.draw(*line_tags_[n], states);
+                               }
+                       }
+
+                       glDisable(GL_LINE_STIPPLE);
+               }
+       }
+private:
+       double get_insertion_xcoord() const
+       {
+               return line_data_.empty() ? 1.0 : line_data_.back().position.x + x_delta_;
+       }
+};
+
+struct graph : public drawable, public caspar::diagnostics::spi::graph_sink, public std::enable_shared_from_this<graph>
+{
+       call_context                                                                            context_        = call_context::for_thread();
+       tbb::concurrent_unordered_map<std::string, line>        lines_;
+
+       tbb::spin_mutex                                                                         mutex_;
+       std::wstring                                                                            text_;
+       bool                                                                                            auto_reset_     = false;
+
+       graph()
+       {
+       }
+
+       void activate() override
+       {
+               context::register_drawable(shared_from_this());
+       }
+               
+       void set_text(const std::wstring& value) override
+       {
+               auto temp = value;
+               lock(mutex_, [&]
+               {
+                       text_ = std::move(temp);
+               });
+       }
+
+       void set_value(const std::string& name, double value) override
+       {
+               lines_[name].set_value(value);
+       }
+
+       void set_tag(const std::string& name) override
+       {
+               lines_[name].set_tag();
+       }
+
+       void set_color(const std::string& name, int color) override
+       {
+               lines_[name].set_color(color);
+       }
+
+       void auto_reset() override
+       {
+               lock(mutex_, [this]
+               {
+                       auto_reset_ = true;
+               });
+       }
+               
+private:
+       void render(sf::RenderTarget& target, sf::RenderStates states) override
+       {
+               const size_t text_size = 15;
+               const size_t text_margin = 2;
+               const size_t text_offset = (text_size+text_margin*2)*2;
+
+               std::wstring text_str;
+               bool auto_reset;
+
+               {
+                       tbb::spin_mutex::scoped_lock lock(mutex_);
+                       text_str = text_;
+                       auto_reset = auto_reset_;
+               }
+
+               sf::Text text(text_str.c_str(), get_default_font(), text_size);
+               text.setStyle(sf::Text::Italic);
+               text.move(text_margin, text_margin);
+               
+               target.draw(text, states);
+
+               if (context_.video_channel != -1)
+               {
+                       auto ctx_str = boost::lexical_cast<std::string>(context_.video_channel);
+
+                       if (context_.layer != -1)
+                               ctx_str += "-" + boost::lexical_cast<std::string>(context_.layer);
+
+                       sf::Text context_text(ctx_str, get_default_font(), text_size);
+                       context_text.setStyle(sf::Text::Italic);
+                       context_text.move(RENDERING_WIDTH - text_margin - 5 - context_text.getLocalBounds().width, text_margin);
+
+                       target.draw(context_text, states);
+               }
+
+               float x_offset = text_margin;
+
+               for(auto it = lines_.begin(); it != lines_.end(); ++it)
+               {
+                       sf::Text line_text(it->first, get_default_font(), text_size);
+                       line_text.setPosition(x_offset, text_margin+text_offset/2);
+                       line_text.setColor(get_sfml_color(it->second.get_color()));
+                       target.draw(line_text, states);
+                       x_offset += line_text.getLocalBounds().width + text_margin * 2;
+               }
+
+               static const auto rect = []()
+               {
+                       sf::RectangleShape r(sf::Vector2f(RENDERING_WIDTH, RENDERING_HEIGHT - 2));
+                       r.setFillColor(sf::Color(255, 255, 255, 51));
+                       r.setOutlineThickness(0.00f);
+                       r.move(0, 1);
+                       return r;
+               }();
+               target.draw(rect, states);
+
+               states.transform
+                       .translate(0, text_offset)
+                       .scale(RENDERING_WIDTH, RENDERING_HEIGHT * (static_cast<float>(RENDERING_HEIGHT - text_offset) / static_cast<float>(RENDERING_HEIGHT)));
+               
+               static const sf::Color guide_color(255, 255, 255, 127);
+               static const sf::VertexArray middle_guide = []()
+               {
+                       sf::VertexArray result(sf::LinesStrip);
+                       result.append(sf::Vertex(sf::Vector2f(0.0f, 0.5f), guide_color));
+                       result.append(sf::Vertex(sf::Vector2f(1.0f, 0.5f), guide_color));
+                       return result;
+               }();
+               static const sf::VertexArray bottom_guide = []()
+               {
+                       sf::VertexArray result(sf::LinesStrip);
+                       result.append(sf::Vertex(sf::Vector2f(0.0f, 0.9f), guide_color));
+                       result.append(sf::Vertex(sf::Vector2f(1.0f, 0.9f), guide_color));
+                       return result;
+               }();
+               static const sf::VertexArray top_guide = []()
+               {
+                       sf::VertexArray result(sf::LinesStrip);
+                       result.append(sf::Vertex(sf::Vector2f(0.0f, 0.1f), guide_color));
+                       result.append(sf::Vertex(sf::Vector2f(1.0f, 0.1f), guide_color));
+                       return result;
+               }();
+
+               glEnable(GL_LINE_STIPPLE);
+               glLineStipple(3, 0xAAAA);
+               
+               target.draw(middle_guide, states);
+               target.draw(bottom_guide, states);
+               target.draw(top_guide, states);
+               
+               glDisable(GL_LINE_STIPPLE);
+
+               for (auto it = lines_.begin(); it != lines_.end(); ++it)                
+               {
+                       target.draw(it->second, states);
+                       if(auto_reset)
+                               it->second.set_value(0.0f);
+               }
+       }
+};
+
+void register_sink()
+{
+       caspar::diagnostics::spi::register_sink_factory([]
+       {
+               return spl::make_shared<graph>();
+       });
+}
+
+void show_graphs(bool value)
+{
+       context::show(value);
+}
+
+void shutdown()
+{
+       context::shutdown();
+}
+
+}}}}
diff --git a/core/diagnostics/osd_graph.h b/core/diagnostics/osd_graph.h
new file mode 100644 (file)
index 0000000..067077b
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>
+*
+* This file is part of CasparCG (www.casparcg.com).
+*
+* CasparCG 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 3 of the License, or
+* (at your option) any later version.
+*
+* CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.
+*
+* Author: Robert Nagy, ronag89@gmail.com
+*/
+
+#pragma once
+
+#include <common/memory.h>
+#include <common/diagnostics/graph.h>
+
+#include <string>
+#include <tuple>
+#include <functional>
+
+#include <boost/noncopyable.hpp>
+
+namespace caspar { namespace core { namespace diagnostics { namespace osd {
+
+void register_sink();
+void show_graphs(bool value);
+void shutdown();
+
+}}}}
diff --git a/core/diagnostics/subject_diagnostics.cpp b/core/diagnostics/subject_diagnostics.cpp
new file mode 100644 (file)
index 0000000..5eb40ce
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>
+*
+* This file is part of CasparCG (www.casparcg.com).
+*
+* CasparCG 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 3 of the License, or
+* (at your option) any later version.
+*
+* CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.
+*
+* Author: Helge Norberg, helge.norberg@svt.se
+*/
+
+#include "../StdAfx.h"
+
+#include "subject_diagnostics.h"
+
+#include "call_context.h"
+
+#include <common/diagnostics/graph.h>
+
+#include <boost/lexical_cast.hpp>
+#include <boost/timer.hpp>
+
+#include <atomic>
+#include <mutex>
+#include <unordered_map>
+
+namespace {
+
+int64_t create_id()
+{
+       static std::atomic<int64_t> counter = 0;
+
+       return ++counter;
+}
+
+}
+
+namespace caspar { namespace core { namespace diagnostics {
+
+static const double SECONDS_BETWEEN_FULL_STATE = 0.4;
+
+class subject_graph : public caspar::diagnostics::spi::graph_sink
+{
+       spl::shared_ptr<monitor::subject>               subject_                                                = spl::make_shared<monitor::subject>("/" + boost::lexical_cast<std::string>(create_id()));
+       call_context                                                    context_                                                = call_context::for_thread();
+       std::mutex                                                              mutex_;
+       std::wstring                                                    text_;
+       std::unordered_map<std::string, int>    colors_;
+       boost::timer                                                    time_since_full_state_send_;
+public:
+       subject_graph()
+       {
+       }
+
+       void activate() override
+       {
+               subject_->attach_parent(get_or_create_subject());
+       }
+
+       void set_text(const std::wstring& value) override
+       {
+               std::lock_guard<std::mutex> lock(mutex_);
+
+               text_ = value;
+
+               *subject_ << monitor::message("/text") % text_;
+       }
+
+       void set_value(const std::string& name, double value) override
+       {
+               *subject_ << monitor::message("/value/" + name) % value;
+
+               send_full_state_if_long_ago();
+       }
+       
+       void set_color(const std::string& name, int color) override
+       {
+               std::lock_guard<std::mutex> lock(mutex_);
+
+               colors_[name] = color;
+
+               *subject_ << monitor::message("/color/" + name) % color;
+       }
+       
+       void set_tag(const std::string& name) override
+       {
+               *subject_ << monitor::message("/tag/" + name);
+
+               send_full_state_if_long_ago();
+       }
+       
+       void auto_reset() override
+       {
+       }
+
+       monitor::subject& subject()
+       {
+               return *subject_;
+       }
+private:
+       void send_full_state_if_long_ago()
+       {
+               std::lock_guard<std::mutex> lock(mutex_);
+
+               if (time_since_full_state_send_.elapsed() > SECONDS_BETWEEN_FULL_STATE)
+               {
+                       send_full_state();
+               }
+       }
+
+       void send_full_state()
+       {
+               *subject_ << monitor::message("/text") % text_;
+
+               if (context_.video_channel != -1)
+                       *subject_ << monitor::message("/context/channel") % context_.video_channel;
+
+               if (context_.layer != -1)
+                       *subject_ << monitor::message("/context/layer") % context_.layer;
+
+               for (const auto& color : colors_)
+                       *subject_ << monitor::message("/color/" + color.first) % color.second;
+
+               time_since_full_state_send_.restart();
+       }
+};
+
+spl::shared_ptr<monitor::subject> get_or_create_subject()
+{
+       static auto diag_subject = []()
+       {
+               auto subject = spl::make_shared<monitor::subject>("/diag");
+
+               caspar::diagnostics::spi::register_sink_factory([=]()
+               {
+                       return spl::make_shared<subject_graph>();
+               });
+
+               return subject;
+       }();
+
+       return diag_subject;
+}
+
+}}}
diff --git a/core/diagnostics/subject_diagnostics.h b/core/diagnostics/subject_diagnostics.h
new file mode 100644 (file)
index 0000000..0573676
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>
+*
+* This file is part of CasparCG (www.casparcg.com).
+*
+* CasparCG 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 3 of the License, or
+* (at your option) any later version.
+*
+* CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.
+*
+* Author: Helge Norberg, helge.norberg@svt.se
+*/
+
+#pragma once
+
+#include "../monitor/monitor.h"
+
+namespace caspar { namespace core { namespace diagnostics {
+
+spl::shared_ptr<monitor::subject> get_or_create_subject();
+
+}}}
index e4d3e64f331d4df13f81ac02bf7471a3e491e752..086ad414236927a3991b14c9055614bb2dbbf62e 100644 (file)
@@ -38,6 +38,7 @@
 #include <common/executor.h>
 
 #include <core/mixer/image/image_mixer.h>
+#include <core/diagnostics/call_context.h>
 
 #include <tbb/spin_mutex.h>
 
@@ -49,21 +50,26 @@ namespace caspar { namespace core {
 
 struct video_channel::impl final
 {
-       spl::shared_ptr<monitor::subject>                               monitor_subject_;
+       spl::shared_ptr<monitor::subject>                                       monitor_subject_;
 
-       const int                                                                               index_;
+       const int                                                                                       index_;
 
-       mutable tbb::spin_mutex                                                 format_desc_mutex_;
-       core::video_format_desc                                                 format_desc_;
+       mutable tbb::spin_mutex                                                         format_desc_mutex_;
+       core::video_format_desc                                                         format_desc_;
        
-       const spl::shared_ptr<diagnostics::graph>               graph_;
-
-       caspar::core::output                                                    output_;
-       spl::shared_ptr<image_mixer>                                    image_mixer_;
-       caspar::core::mixer                                                             mixer_;
-       caspar::core::stage                                                             stage_; 
-
-       executor                                                                                executor_                       = L"video_channel";
+       const spl::shared_ptr<caspar::diagnostics::graph>       graph_                          = [](int index)
+                                                                                                                                                         {
+                                                                                                                                                                 core::diagnostics::scoped_call_context save;
+                                                                                                                                                                 core::diagnostics::call_context::for_thread().video_channel = index;
+                                                                                                                                                                 return spl::make_shared<caspar::diagnostics::graph>();
+                                                                                                                                                         }(index_);
+
+       caspar::core::output                                                            output_;
+       spl::shared_ptr<image_mixer>                                            image_mixer_;
+       caspar::core::mixer                                                                     mixer_;
+       caspar::core::stage                                                                     stage_; 
+
+       executor                                                                                        executor_                       = L"video_channel";
 public:
        impl(int index, const core::video_format_desc& format_desc, std::unique_ptr<image_mixer> image_mixer)  
                : monitor_subject_(spl::make_shared<monitor::subject>(
@@ -75,9 +81,9 @@ public:
                , mixer_(graph_, image_mixer_)
                , stage_(graph_)
        {
-               graph_->set_color("tick-time", diagnostics::color(0.0f, 0.6f, 0.9f));   
+               graph_->set_color("tick-time", caspar::diagnostics::color(0.0f, 0.6f, 0.9f));
                graph_->set_text(print());
-               diagnostics::register_graph(graph_);
+               caspar::diagnostics::register_graph(graph_);
                
                output_.monitor_output().attach_parent(monitor_subject_);
                stage_.monitor_output().attach_parent(monitor_subject_);
@@ -125,7 +131,8 @@ public:
                                                
                        output_(std::move(mixed_frame), format_desc);
                
-                       graph_->set_value("tick-time", frame_timer.elapsed()*format_desc.fps*0.5);
+                       auto frame_time = frame_timer.elapsed()*format_desc.fps*0.5;
+                       graph_->set_value("tick-time", frame_time);
 
                        *monitor_subject_       << monitor::message("/profiler/time")   % frame_timer.elapsed() % (1.0/format_desc_.fps)
                                                                << monitor::message("/format")                  % format_desc.name;
@@ -143,6 +150,11 @@ public:
                return L"video_channel[" + boost::lexical_cast<std::wstring>(index_) + L"|" +  video_format_desc().name + L"]";
        }
 
+       int index() const
+       {
+               return index_;
+       }
+
        boost::property_tree::wptree info() const
        {
                boost::property_tree::wptree info;
@@ -171,7 +183,8 @@ output& video_channel::output() { return impl_->output_;}
 spl::shared_ptr<frame_factory> video_channel::frame_factory() { return impl_->image_mixer_;} 
 core::video_format_desc video_channel::video_format_desc() const{return impl_->video_format_desc();}
 void core::video_channel::video_format_desc(const core::video_format_desc& format_desc){impl_->video_format_desc(format_desc);}
-boost::property_tree::wptree video_channel::info() const{return impl_->info();}                
-monitor::subject& video_channel::monitor_output(){return *impl_->monitor_subject_;}
+boost::property_tree::wptree video_channel::info() const{return impl_->info();}
+int video_channel::index() const { return impl_->index(); }
+monitor::subject& video_channel::monitor_output(){ return *impl_->monitor_subject_; }
 
 }}
\ No newline at end of file
index c8dc1f090e20bbef0a62e660f56ddbfc702ec00d..fb747eefea1a09abcdd61aec9e5ccf53e5df068d 100644 (file)
@@ -54,23 +54,24 @@ public:
 
        // Methods
                        
-       monitor::subject& monitor_output();
+       monitor::subject&                                               monitor_output();
 
        // Properties
 
-       const core::stage&                                       stage() const;
-       core::stage&                                             stage();
-       const core::mixer&                                       mixer() const;
-       core::mixer&                                             mixer();
-       const core::output&                                      output() const;
-       core::output&                                            output();
-                                                                                
-       core::video_format_desc                          video_format_desc() const;
-       void                                                             video_format_desc(const core::video_format_desc& format_desc);
-       
-       spl::shared_ptr<core::frame_factory> frame_factory();
+       const core::stage&                                              stage() const;
+       core::stage&                                                    stage();
+       const core::mixer&                                              mixer() const;
+       core::mixer&                                                    mixer();
+       const core::output&                                             output() const;
+       core::output&                                                   output();
+
+       core::video_format_desc                                 video_format_desc() const;
+       void                                                                    video_format_desc(const core::video_format_desc& format_desc);
+
+       spl::shared_ptr<core::frame_factory>    frame_factory();
 
-       boost::property_tree::wptree             info() const;
+       boost::property_tree::wptree                    info() const;
+       int                                                                             index() const;
 private:
        struct impl;
        spl::unique_ptr<impl> impl_;
diff --git a/dependencies64/liberation-fonts/AUTHORS b/dependencies64/liberation-fonts/AUTHORS
new file mode 100644 (file)
index 0000000..3bb7b6a
--- /dev/null
@@ -0,0 +1,12 @@
+AUTHORS
+
+Current Contributors (sorted alphabetically):
+  - Pravin Satpute  <psatpute at redhat dot com>
+      Project Owner (Current)
+      Red Hat, Inc.
+
+Previous Contributors
+
+  - Steve Matteson
+      Original Designer
+      Ascender, Inc.
diff --git a/dependencies64/liberation-fonts/ChangeLog b/dependencies64/liberation-fonts/ChangeLog
new file mode 100644 (file)
index 0000000..cd50871
--- /dev/null
@@ -0,0 +1,14 @@
+* Thu Oct 04 2012 Pravin Satpute <psatpute AT redhat DOT com>
+- Resolved "Glyphs with multiple unicode encodings inhibit subsetting" #851790
+- Resolved #851791, #854601 and #851825
+- Following GASP table version as per Liberation old version. (Anti-aliasing disabled)
+- Added support for Serbian glyphs for wikipedia #657849
+- In Monospace fonts, isFixedPitch bit set via script for getting it recognized as Monospace in putty.exe
+
+* Fri Jul 06 2012 Pravin Satpute <psatpute AT redhat DOT com>
+- Initial version of Liberation fonts based on croscore fonts version 1.21.0
+- Converted TTF files into SFD files to be open source.
+- Update Copyright and License file
+- set fsType bit to 0, Installable Embedding is allowed.
+- Absolute value in HHeadAscent/Descent values for maintaining Metric compatibility.
+
diff --git a/dependencies64/liberation-fonts/LICENSE b/dependencies64/liberation-fonts/LICENSE
new file mode 100644 (file)
index 0000000..aba73e8
--- /dev/null
@@ -0,0 +1,102 @@
+Digitized data copyright (c) 2010 Google Corporation
+       with Reserved Font Arimo, Tinos and Cousine.
+Copyright (c) 2012 Red Hat, Inc.
+       with Reserved Font Name Liberation.
+
+This Font Software is licensed under the SIL Open Font License,
+Version 1.1.
+
+This license is copied below, and is also available with a FAQ at:
+http://scripts.sil.org/OFL
+
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+
+PREAMBLE The goals of the Open Font License (OFL) are to stimulate
+worldwide development of collaborative font projects, to support the font
+creation efforts of academic and linguistic communities, and to provide
+a free and open framework in which fonts may be shared and improved in
+partnership with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves.
+The fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works.  The fonts and derivatives,
+however, cannot be released under any other type of license.  The
+requirement for fonts to remain under this license does not apply to
+any document created using the fonts or their derivatives.
+
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such.
+This may include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components
+as distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting ? in part or in whole ?
+any of the components of the Original Version, by changing formats or
+by porting the Font Software to a new environment.
+
+"Author" refers to any designer, engineer, programmer, technical writer
+or other person who contributed to the Font Software.
+
+
+PERMISSION & CONDITIONS
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,in
+   Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+   redistributed and/or sold with any software, provided that each copy
+   contains the above copyright notice and this license. These can be
+   included either as stand-alone text files, human-readable headers or
+   in the appropriate machine-readable metadata fields within text or
+   binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+   Name(s) unless explicit written permission is granted by the
+   corresponding Copyright Holder. This restriction only applies to the
+   primary font name as presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+   Software shall not be used to promote, endorse or advertise any
+   Modified Version, except to acknowledge the contribution(s) of the
+   Copyright Holder(s) and the Author(s) or with their explicit written
+   permission.
+
+5) The Font Software, modified or unmodified, in part or in whole, must
+   be distributed entirely under this license, and must not be distributed
+   under any other license. The requirement for fonts to remain under
+   this license does not apply to any document created using the Font
+   Software.
+
+
+TERMINATION
+This license becomes null and void if any of the above conditions are not met.
+
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT.  IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER
+DEALINGS IN THE FONT SOFTWARE.
+
diff --git a/dependencies64/liberation-fonts/LiberationMono-Bold.ttf b/dependencies64/liberation-fonts/LiberationMono-Bold.ttf
new file mode 100644 (file)
index 0000000..9997cda
Binary files /dev/null and b/dependencies64/liberation-fonts/LiberationMono-Bold.ttf differ
diff --git a/dependencies64/liberation-fonts/LiberationMono-BoldItalic.ttf b/dependencies64/liberation-fonts/LiberationMono-BoldItalic.ttf
new file mode 100644 (file)
index 0000000..85eb01b
Binary files /dev/null and b/dependencies64/liberation-fonts/LiberationMono-BoldItalic.ttf differ
diff --git a/dependencies64/liberation-fonts/LiberationMono-Italic.ttf b/dependencies64/liberation-fonts/LiberationMono-Italic.ttf
new file mode 100644 (file)
index 0000000..5302690
Binary files /dev/null and b/dependencies64/liberation-fonts/LiberationMono-Italic.ttf differ
diff --git a/dependencies64/liberation-fonts/LiberationMono-Regular.ttf b/dependencies64/liberation-fonts/LiberationMono-Regular.ttf
new file mode 100644 (file)
index 0000000..1a39bc7
Binary files /dev/null and b/dependencies64/liberation-fonts/LiberationMono-Regular.ttf differ
diff --git a/dependencies64/liberation-fonts/LiberationSans-Bold.ttf b/dependencies64/liberation-fonts/LiberationSans-Bold.ttf
new file mode 100644 (file)
index 0000000..4581ebf
Binary files /dev/null and b/dependencies64/liberation-fonts/LiberationSans-Bold.ttf differ
diff --git a/dependencies64/liberation-fonts/LiberationSans-BoldItalic.ttf b/dependencies64/liberation-fonts/LiberationSans-BoldItalic.ttf
new file mode 100644 (file)
index 0000000..bfbcd26
Binary files /dev/null and b/dependencies64/liberation-fonts/LiberationSans-BoldItalic.ttf differ
diff --git a/dependencies64/liberation-fonts/LiberationSans-Italic.ttf b/dependencies64/liberation-fonts/LiberationSans-Italic.ttf
new file mode 100644 (file)
index 0000000..fcdab88
Binary files /dev/null and b/dependencies64/liberation-fonts/LiberationSans-Italic.ttf differ
diff --git a/dependencies64/liberation-fonts/LiberationSans-Regular.ttf b/dependencies64/liberation-fonts/LiberationSans-Regular.ttf
new file mode 100644 (file)
index 0000000..626dd93
Binary files /dev/null and b/dependencies64/liberation-fonts/LiberationSans-Regular.ttf differ
diff --git a/dependencies64/liberation-fonts/LiberationSerif-Bold.ttf b/dependencies64/liberation-fonts/LiberationSerif-Bold.ttf
new file mode 100644 (file)
index 0000000..db3d6f3
Binary files /dev/null and b/dependencies64/liberation-fonts/LiberationSerif-Bold.ttf differ
diff --git a/dependencies64/liberation-fonts/LiberationSerif-BoldItalic.ttf b/dependencies64/liberation-fonts/LiberationSerif-BoldItalic.ttf
new file mode 100644 (file)
index 0000000..8b21277
Binary files /dev/null and b/dependencies64/liberation-fonts/LiberationSerif-BoldItalic.ttf differ
diff --git a/dependencies64/liberation-fonts/LiberationSerif-Italic.ttf b/dependencies64/liberation-fonts/LiberationSerif-Italic.ttf
new file mode 100644 (file)
index 0000000..768b833
Binary files /dev/null and b/dependencies64/liberation-fonts/LiberationSerif-Italic.ttf differ
diff --git a/dependencies64/liberation-fonts/LiberationSerif-Regular.ttf b/dependencies64/liberation-fonts/LiberationSerif-Regular.ttf
new file mode 100644 (file)
index 0000000..6fa9a59
Binary files /dev/null and b/dependencies64/liberation-fonts/LiberationSerif-Regular.ttf differ
diff --git a/dependencies64/liberation-fonts/README b/dependencies64/liberation-fonts/README
new file mode 100644 (file)
index 0000000..572952a
--- /dev/null
@@ -0,0 +1,80 @@
+   1. What's this?
+  =================
+
+  The Liberation Fonts is font collection which aims to provide document 
+  layout compatibility as usage of Times New Roman, Arial, Courier New.
+
+
+   2. Requirements
+  =================
+
+  * fontforge is installed.
+    (http://fontforge.sourceforge.net)
+
+
+   3. Install
+  ============
+
+  3.1 Decompress tarball
+
+    You can extract the files by following command:
+
+      $ tar zxvf liberation-fonts-[VERSION].tar.gz
+
+  3.2 Build from the source
+
+    Change into directory liberation-fonts-[VERSION]/ and build from sources by 
+    following commands:
+
+      $ cd liberation-fonts-[VERSION]
+      $ make
+
+    The built font files will be available in 'build' directory.
+
+  3.3 Install to system
+
+    For Fedora, you could manually install the fonts by copying the TTFs to 
+    ~/.fonts for user wide usage, or to /usr/share/fonts/truetype/liberation 
+    for system-wide availability. Then, run "fc-cache" to let that cached.
+
+    For other distributions, please check out corresponding documentation.
+
+
+   4. Usage
+  ==========
+
+  Simply select preferred liberation font in applications and start using.
+
+
+   5. License
+  ============
+
+  This Font Software is licensed under the SIL Open Font License,
+  Version 1.1.
+
+  Please read file "LICENSE" for details.
+
+
+   6. For Maintainers
+  ====================
+
+  Before packaging a new release based on a new source tarball, you have to
+  update the version suffix in the Makefile:
+
+    VER = [VERSION]
+
+  Make sure that the defined version corresponds to the font software metadata
+  which you can check with ftinfo/otfinfo or fontforge itself. It is highly 
+  recommended that file 'ChangeLog' is updated to reflect changes.
+
+  Create a tarball with the following command:
+
+    $ make dist
+
+  The new versioned tarball will be available in the dist/ folder as
+  'liberation-fonts-[NEW_VERSION].tar.gz'.
+
+  7. Credits
+ ============
+
+  Please read file "AUTHORS" for list of contributors.
diff --git a/dependencies64/liberation-fonts/TODO b/dependencies64/liberation-fonts/TODO
new file mode 100644 (file)
index 0000000..efc0177
--- /dev/null
@@ -0,0 +1,5 @@
+Here are todo for next release
+1) Serbian glyph for wikipedia https://bugzilla.redhat.com/show_bug.cgi?id=657849
+       - Improving shape of S_BE https://bugzilla.redhat.com/show_bug.cgi?id=657849#c96
+2) Liberation Mono not recognizing as Mono in Windows application #861003
+       - presently it is patch, we have to update zero width characters to fixed width
index e7787b1dcb1af59a4c9c6d947ded906df2845c2f..84203b5ec4291414e982af94c6fbd9fae14c2527 100644 (file)
@@ -40,6 +40,7 @@
 #include <common/cache_aligned_vector.h>
 
 #include <core/consumer/frame_consumer.h>
+#include <core/diagnostics/call_context.h>
 
 #include <tbb/concurrent_queue.h>
 
@@ -505,8 +506,10 @@ public:
                : config_(config)
                , executor_(L"decklink_consumer[" + boost::lexical_cast<std::wstring>(config.device_index) + L"]")
        {
+               auto ctx = core::diagnostics::call_context::for_thread();
                executor_.begin_invoke([=]
                {
+                       core::diagnostics::call_context::for_thread() = ctx;
                        ::CoInitialize(nullptr);
                });
        }
index f21892610e54dbf49e024ea9b2d1f98b4f7cf8c8..a738bcdcf9a3b3a958199f669f2e45436ca28695 100644 (file)
@@ -28,6 +28,7 @@
 #include <common/env.h>
 
 #include <core/mixer/mixer.h>
+#include <core/diagnostics/call_context.h>
 
 #include <boost/filesystem.hpp>
 #include <boost/format.hpp>
@@ -173,7 +174,11 @@ cg_proxy create_cg_proxy(const spl::shared_ptr<core::video_channel>& video_chann
        {
                if(flash_producer->name() != L"flash")
                {
-                       flash_producer = flash::create_producer(video_channel->frame_factory(), video_channel->video_format_desc(), { });
+                       core::diagnostics::scoped_call_context save;
+                       core::diagnostics::call_context::for_thread().video_channel = video_channel->index();
+                       core::diagnostics::call_context::for_thread().layer = render_layer;
+
+                       flash_producer = flash::create_producer(video_channel->frame_factory(), video_channel->video_format_desc(), {});
                        video_channel->stage().load(render_layer, flash_producer); 
                        video_channel->stage().play(render_layer);
                }
index 5f5d4fcb3c062d802af9b731f79087688afa973c..1113388211f397251a7f43c43bb81c289ebc2f4d 100644 (file)
@@ -32,7 +32,6 @@
 
 #include <common/log.h>
 #include <common/param.h>
-#include <common/diagnostics/graph.h>
 #include <common/os/windows/current_version.h>
 #include <common/os/windows/system_info.h>
 #include <common/base64.h>
@@ -46,6 +45,8 @@
 #include <core/mixer/mixer.h>
 #include <core/consumer/output.h>
 #include <core/thumbnail_generator.h>
+#include <core/diagnostics/call_context.h>
+#include <core/diagnostics/osd_graph.h>
 
 #include <modules/reroute/producer/reroute_producer.h>
 #include <modules/bluefish/bluefish.h>
@@ -297,7 +298,7 @@ bool DiagnosticsCommand::DoExecute()
 {      
        try
        {
-               diagnostics::show_graphs(true);
+               core::diagnostics::osd::show_graphs(true);
 
                SetReplyString(TEXT("202 DIAG OK\r\n"));
 
@@ -316,6 +317,9 @@ bool ChannelGridCommand::DoExecute()
        int index = 1;
        auto self = channels().back().channel;
        
+       core::diagnostics::scoped_call_context save;
+       core::diagnostics::call_context::for_thread().video_channel = channels().size();
+
        std::vector<std::wstring> params;
        params.push_back(L"SCREEN");
        params.push_back(L"0");
@@ -329,6 +333,7 @@ bool ChannelGridCommand::DoExecute()
        {
                if(channel.channel != self)
                {
+                       core::diagnostics::call_context::for_thread().layer = index;
                        auto producer = reroute::create_producer(*channel.channel);
                        self->stage().load(index, producer, false);
                        self->stage().play(index);
@@ -668,6 +673,9 @@ bool AddCommand::DoExecute()
                        boost::to_upper(str);
                }
 
+               core::diagnostics::scoped_call_context save;
+               core::diagnostics::call_context::for_thread().video_channel = channel_index() + 1;
+
                auto consumer = create_consumer(parameters());
                channel()->output().add(layer_index(consumer->index()), consumer);
        
@@ -731,7 +739,10 @@ bool LoadCommand::DoExecute()
        //Perform loading of the clip
        try
        {
-               auto pFP = create_producer(channel()->frame_factory(), channel()->video_format_desc(), parameters());           
+               core::diagnostics::scoped_call_context save;
+               core::diagnostics::call_context::for_thread().video_channel = channel_index() + 1;
+               core::diagnostics::call_context::for_thread().layer = layer_index();
+               auto pFP = create_producer(channel()->frame_factory(), channel()->video_format_desc(), parameters());
                channel()->stage().load(layer_index(), pFP, true);
        
                SetReplyString(TEXT("202 LOAD OK\r\n"));
@@ -838,6 +849,10 @@ bool LoadbgCommand::DoExecute()
                
                static boost::wregex expr(LR"(\[(?<CHANNEL>\d+)\])", boost::regex::icase);
                        
+               core::diagnostics::scoped_call_context save;
+               core::diagnostics::call_context::for_thread().video_channel = channel_index() + 1;
+               core::diagnostics::call_context::for_thread().layer = layer_index();
+
                boost::wsmatch what;
                if(boost::regex_match(parameters().at(0), what, expr))
                {
index 34a28f723bfd3ceee93f5050f4289a0b4d46e505..83ade84c7b1935c01017a8cc2b3d4db93741be41 100644 (file)
@@ -30,6 +30,7 @@
 #include <modules/flash/producer/flash_producer.h>
 #include <core/producer/transition/transition_producer.h>
 #include <core/mixer/mixer.h>
+#include <core/diagnostics/call_context.h>
 #include <common/env.h>
 
 #include <boost/algorithm/string/replace.hpp>
@@ -160,7 +161,10 @@ void CIIProtocolStrategy::WriteTemplateData(const std::wstring& templateName, co
                CASPAR_LOG(error) << "Failed to save instance of " << templateName << TEXT(" as ") << titleName << TEXT(", template ") << fullTemplateFilename << " not found";
                return;
        }
-       
+       core::diagnostics::scoped_call_context save;
+       core::diagnostics::call_context::for_thread().video_channel = 1;
+       core::diagnostics::call_context::for_thread().layer = 0;
+
        auto producer = flash::create_producer(this->GetChannel()->frame_factory(), this->GetChannel()->video_format_desc(), { env::template_folder() + TEXT("CG.fth") });
 
        std::wstringstream flashParam;
@@ -196,6 +200,10 @@ void CIIProtocolStrategy::DisplayMediaFile(const std::wstring& filename)
        transition.type = transition_type::mix;
        transition.duration = 12;
 
+       core::diagnostics::scoped_call_context save;
+       core::diagnostics::call_context::for_thread().video_channel = 1;
+       core::diagnostics::call_context::for_thread().layer = 0;
+
        auto pFP = create_producer(GetChannel()->frame_factory(), GetChannel()->video_format_desc(), filename);
        auto pTransition = create_transition_producer(GetChannel()->video_format_desc().field_mode, pFP, transition);
 
index 746fa3325ad2617453ed5c15691ea00e27430ad4..762599f564627c8cd5d1b655123b00659a13485f 100644 (file)
@@ -192,7 +192,7 @@ private:
 
        const std::string ipv4_address() const
        {
-               return socket_->is_open() ? socket_->local_endpoint().address().to_string() : "no-address";
+               return socket_->is_open() ? socket_->remote_endpoint().address().to_string() : "no-address";
        }
 
     connection(const spl::shared_ptr<tcp::socket>& socket, const protocol_strategy_factory<char>::ptr& protocol_factory, const spl::shared_ptr<connection_set>& connection_set) 
index ec9cac979a7bbef01e1b9996c221d50cb8985948..6a96760ed4ef089507dab4404f367156038f40fd 100644 (file)
@@ -29,7 +29,6 @@
 #include <common/utf.h>
 #include <common/memory.h>
 #include <common/polling_filesystem_monitor.h>
-#include <common/diagnostics/graph.h>
 
 #include <core/video_channel.h>
 #include <core/video_format.h>
@@ -40,6 +39,9 @@
 #include <core/producer/text/text_producer.h>
 #include <core/consumer/output.h>
 #include <core/thumbnail_generator.h>
+#include <core/diagnostics/subject_diagnostics.h>
+#include <core/diagnostics/call_context.h>
+#include <core/diagnostics/osd_graph.h>
 
 #include <modules/bluefish/bluefish.h>
 #include <modules/decklink/decklink.h>
@@ -82,6 +84,7 @@ struct server::impl : boost::noncopyable
 {
        protocol::asio::io_service_manager                                      io_service_manager_;
        spl::shared_ptr<monitor::subject>                                       monitor_subject_;
+       spl::shared_ptr<monitor::subject>                                       diag_subject_                                   = core::diagnostics::get_or_create_subject();
        accelerator::accelerator                                                        accelerator_;
        std::vector<spl::shared_ptr<IO::AsyncEventServer>>      async_servers_;
        std::shared_ptr<IO::AsyncEventServer>                           primary_amcp_server_;
@@ -95,7 +98,9 @@ struct server::impl : boost::noncopyable
                : accelerator_(env::properties().get(L"configuration.accelerator", L"auto"))
                , osc_client_(io_service_manager_.service())
                , shutdown_server_now_(shutdown_server_now)
-       {       
+       {
+               core::diagnostics::osd::register_sink();
+               diag_subject_->attach_parent(monitor_subject_);
 
                ffmpeg::init();
                CASPAR_LOG(info) << L"Initialized ffmpeg module.";
@@ -151,7 +156,7 @@ struct server::impl : boost::noncopyable
 
                image::uninit();
                ffmpeg::uninit();
-               diagnostics::shutdown();
+               core::diagnostics::osd::shutdown();
        }
                                
        void setup_channels(const boost::property_tree::wptree& pt)
@@ -164,6 +169,9 @@ struct server::impl : boost::noncopyable
                                CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info("Invalid video-mode."));
                        
                        auto channel = spl::make_shared<video_channel>(static_cast<int>(channels_.size()+1), format_desc, accelerator_.create_image_mixer());
+
+                       core::diagnostics::scoped_call_context save;
+                       core::diagnostics::call_context::for_thread().video_channel = channel->index();
                        
                        for (auto& xml_consumer : xml_channel.second.get_child(L"consumers"))
                        {
index f20c23a2175202848df7b0ce5a60aaab109a086f..b2bd900851b5228522acbee96470f5668d18f709 100644 (file)
@@ -181,6 +181,8 @@ copy "$(SolutionDir)dependencies64\freeimage\bin\*.dll" "$(OutDir)"
 copy "$(SolutionDir)dependencies64\openal\bin\*.dll" "$(OutDir)"\r
 copy "$(ProjectDir)casparcg.config" "$(OutDir)"\r
 copy "$(ProjectDir)casparcg_auto_restart.bat" "$(OutDir)"\r
+copy "$(SolutionDir)dependencies64\liberation-fonts\LiberationSans-Regular.ttf" "$(OutDir)"\r
+copy "$(SolutionDir)dependencies64\liberation-fonts\LiberationSans-Regular.ttf" "$(ProjectDir)"\r
 </Command>\r
     </PostBuildEvent>\r
   </ItemDefinitionGroup>\r
@@ -229,7 +231,9 @@ copy "$(SolutionDir)dependencies64\glew\bin\*.dll" "$(OutDir)"
 copy "$(SolutionDir)dependencies64\freeimage\bin\*.dll" "$(OutDir)"\r
 copy "$(SolutionDir)dependencies64\openal\bin\*.dll" "$(OutDir)"\r
 copy "$(ProjectDir)casparcg.config" "$(OutDir)"\r
-copy "$(ProjectDir)casparcg_auto_restart.bat" "$(OutDir)"</Command>\r
+copy "$(ProjectDir)casparcg_auto_restart.bat" "$(OutDir)"\r
+copy "$(SolutionDir)dependencies64\liberation-fonts\LiberationSans-Regular.ttf" "$(OutDir)"\r
+copy "$(SolutionDir)dependencies64\liberation-fonts\LiberationSans-Regular.ttf" "$(ProjectDir)"</Command>\r
     </PostBuildEvent>\r
   </ItemDefinitionGroup>\r
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r