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