]> git.sesse.net Git - casparcg/blob - core/server.cpp
2.0.0.2:
[casparcg] / core / server.cpp
1 #include "StdAfx.h"\r
2 \r
3 #include "server.h"\r
4 \r
5 #include "consumer/oal/oal_consumer.h"\r
6 #ifndef DISABLE_BLUEFISH\r
7 #include "consumer/bluefish/bluefish_consumer.h"\r
8 #endif\r
9 #include "consumer/decklink/DecklinkVideoConsumer.h"\r
10 #include "consumer/ogl/ogl_consumer.h"\r
11 \r
12 #include <FreeImage.h>\r
13 \r
14 #include "protocol/amcp/AMCPProtocolStrategy.h"\r
15 #include "protocol/cii/CIIProtocolStrategy.h"\r
16 #include "protocol/CLK/CLKProtocolStrategy.h"\r
17 #include "producer/flash/FlashAxContainer.h"\r
18 \r
19 #include "../common/io/AsyncEventServer.h"\r
20 #include "../common/utility/string_convert.h"\r
21 \r
22 #include <boost/algorithm/string.hpp>\r
23 #include <boost/lexical_cast.hpp>\r
24 #include <boost/filesystem.hpp>\r
25 #include <boost/foreach.hpp>\r
26 #include <boost/property_tree/ptree.hpp>\r
27 #include <boost/property_tree/xml_parser.hpp>\r
28 \r
29 namespace caspar{\r
30 \r
31 struct server::implementation : boost::noncopyable\r
32 {\r
33         implementation()                                                                                                \r
34         {\r
35                 FreeImage_Initialise(true);     \r
36                                 \r
37                 boost::property_tree::ptree pt;\r
38                 boost::property_tree::read_xml(boost::filesystem::initial_path().file_string() + "\\caspar.config", pt);\r
39 \r
40                 setup_paths();\r
41                 setup_channels(pt);\r
42                 setup_controllers(pt);\r
43         \r
44                 //if(!flash::FlashAxContainer::CheckForFlashSupport())\r
45                 //      CASPAR_LOG(error) << "No flashplayer activex-control installed. Flash support will be disabled";\r
46         }\r
47 \r
48         ~implementation()\r
49         {               \r
50                 FreeImage_DeInitialise();\r
51                 async_servers_.clear();\r
52                 channels_.clear();\r
53         }\r
54 \r
55         static void setup_paths()\r
56         {\r
57                 if(!media_folder_.empty())\r
58                         return;\r
59 \r
60                 std::string initialPath = boost::filesystem::initial_path().file_string();\r
61                 boost::property_tree::ptree pt;\r
62                 boost::property_tree::read_xml(initialPath + "\\caspar.config", pt);\r
63 \r
64                 auto paths = pt.get_child("configuration.paths");\r
65                 media_folder_ = common::widen(paths.get("media-path", initialPath + "\\media\\"));\r
66                 log_folder_ = common::widen(paths.get("log-path", initialPath + "\\log\\"));\r
67                 template_folder_ = common::widen(paths.get("template-path", initialPath + "\\template\\"));\r
68                 data_folder_ = common::widen(paths.get("data-path", initialPath + "\\data\\"));\r
69         }\r
70                         \r
71         void setup_channels(boost::property_tree::ptree& pt)\r
72         {   \r
73                 using boost::property_tree::ptree;\r
74                 BOOST_FOREACH(auto& xml_channel, pt.get_child("configuration.channels"))\r
75                 {               \r
76                         auto format_desc = get_video_format_desc(common::widen(xml_channel.second.get("videomode", "PAL")));                    \r
77                         std::vector<frame_consumer_ptr> consumers;\r
78 \r
79                         BOOST_FOREACH(auto& xml_consumer, xml_channel.second.get_child("consumers"))\r
80                         {\r
81                                 try\r
82                                 {\r
83                                         frame_consumer_ptr pConsumer;\r
84                                         std::string name = xml_consumer.first;\r
85                                         if(name == "ogl")\r
86                                         {                       \r
87                                                 int device = xml_consumer.second.get("device", 0);\r
88                         \r
89                                                 ogl::stretch stretch = ogl::stretch::fill;\r
90                                                 std::string stretchStr = xml_consumer.second.get("stretch", "");\r
91                                                 if(stretchStr == "none")\r
92                                                         stretch = ogl::stretch::none;\r
93                                                 else if(stretchStr == "uniform")\r
94                                                         stretch = ogl::stretch::uniform;\r
95                                                 else if(stretchStr == "uniformtofill")\r
96                                                         stretch = ogl::stretch::uniform_to_fill;\r
97 \r
98                                                 bool windowed = xml_consumer.second.get("windowed", false);\r
99                                                 pConsumer = std::make_shared<ogl::consumer>(format_desc, device, stretch, windowed);\r
100                                         }\r
101                                 #ifndef DISABLE_BLUEFISH\r
102                                         else if(name == "bluefish")                                     \r
103                                                 pConsumer = std::make_shared<bluefish::consumer>(format_desc, xml_consumer.second.get("device", 0), xml_consumer.second.get("embedded-audio", false));                                  \r
104                                 #endif\r
105                                         else if(name == "decklink")\r
106                                                 pConsumer = std::make_shared<decklink::DecklinkVideoConsumer>(format_desc, xml_consumer.second.get("internalkey", false));\r
107                                         else if(name == "audio")\r
108                                                 pConsumer = std::make_shared<audio::consumer>(format_desc);\r
109 \r
110                                         if(pConsumer)                                   \r
111                                                 consumers.push_back(pConsumer);                                 \r
112                                 }\r
113                                 catch(...)\r
114                                 {\r
115                                         CASPAR_LOG_CURRENT_EXCEPTION();\r
116                                 }\r
117                         }\r
118                         \r
119                         channels_.push_back(std::make_shared<renderer::render_device>(format_desc, channels_.size() + 1, consumers));\r
120                 }\r
121         }\r
122                 \r
123         void setup_controllers(boost::property_tree::ptree& pt)\r
124         {               \r
125                 using boost::property_tree::ptree;\r
126                 BOOST_FOREACH(auto& xml_controller, pt.get_child("configuration.controllers"))\r
127                 {\r
128                         try\r
129                         {\r
130                                 std::string name = xml_controller.first;\r
131                                 std::string protocol = xml_controller.second.get<std::string>("protocol");      \r
132 \r
133                                 if(name == "tcpcontroller")\r
134                                 {                                       \r
135                                         unsigned int port = xml_controller.second.get<unsigned int>("port");\r
136                                         port = port != 0 ? port : 5250;\r
137                                         auto asyncserver = std::make_shared<caspar::IO::AsyncEventServer>(create_protocol(protocol), port);\r
138                                         asyncserver->Start();\r
139                                         async_servers_.push_back(asyncserver);\r
140                                 }\r
141                                 else\r
142                                         BOOST_THROW_EXCEPTION(invalid_configuration() << arg_name_info(name) << msg_info("Invalid controller"));\r
143                         }\r
144                         catch(...)\r
145                         {\r
146                                 CASPAR_LOG_CURRENT_EXCEPTION();\r
147                                 throw;\r
148                         }\r
149                 }\r
150         }\r
151 \r
152         IO::ProtocolStrategyPtr create_protocol(const std::string& name) const\r
153         {\r
154                 if(name == "AMCP")\r
155                         return std::make_shared<amcp::AMCPProtocolStrategy>(channels_);\r
156                 else if(name == "CII")\r
157                         return std::make_shared<cii::CIIProtocolStrategy>(channels_);\r
158                 else if(name == "CLOCK")\r
159                         return std::make_shared<CLK::CLKProtocolStrategy>(channels_);\r
160                 \r
161                 BOOST_THROW_EXCEPTION(invalid_configuration() << arg_name_info("name") << arg_value_info(name) << msg_info("Invalid protocol"));\r
162         }\r
163 \r
164         std::vector<IO::AsyncEventServerPtr> async_servers_;\r
165 \r
166         std::vector<renderer::render_device_ptr> channels_;\r
167 \r
168         int logLevel_;\r
169 \r
170         static std::wstring media_folder_;\r
171         static std::wstring log_folder_;\r
172         static std::wstring template_folder_;\r
173         static std::wstring data_folder_;\r
174 };\r
175 \r
176 std::wstring server::implementation::media_folder_ = L"";\r
177 std::wstring server::implementation::log_folder_ = L"";\r
178 std::wstring server::implementation::template_folder_ = L"";\r
179 std::wstring server::implementation::data_folder_ = L"";\r
180 \r
181 server::server() : impl_(new implementation()){}\r
182 \r
183 const std::wstring& server::media_folder()\r
184 {\r
185         server::implementation::setup_paths();\r
186         return server::implementation::media_folder_;\r
187 }\r
188 \r
189 const std::wstring& server::log_folder()\r
190 {\r
191         server::implementation::setup_paths();\r
192         return server::implementation::log_folder_;\r
193 }\r
194 \r
195 const std::wstring& server::template_folder()\r
196 {\r
197         server::implementation::setup_paths();\r
198         return server::implementation::template_folder_;\r
199 }\r
200 \r
201 const std::wstring& server::data_folder()\r
202 {\r
203         server::implementation::setup_paths();\r
204         return server::implementation::data_folder_;\r
205 }\r
206 \r
207 const std::vector<renderer::render_device_ptr>& server::get_channels() const{ return impl_->channels_; }\r
208 \r
209 }