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