]> git.sesse.net Git - casparcg/blob - shell/server.cpp
2.0.0.2: - Cleanup and improvements in main.cpp.
[casparcg] / shell / server.cpp
1 #include "server.h"\r
2 \r
3 #include <common/env.h>\r
4 #include <common/exception/exceptions.h>\r
5 #include <common/utility/string.h>\r
6 \r
7 #include <core/channel.h>\r
8 \r
9 #include <modules/bluefish/bluefish.h>\r
10 #include <modules/decklink/decklink.h>\r
11 #include <modules/ffmpeg/ffmpeg.h>\r
12 #include <modules/flash/flash.h>\r
13 #include <modules/oal/oal.h>\r
14 #include <modules/ogl/ogl.h>\r
15 #include <modules/silverlight/silverlight.h>\r
16 #include <modules/image/image.h>\r
17 \r
18 #include <modules/oal/consumer/oal_consumer.h>\r
19 #include <modules/bluefish/consumer/bluefish_consumer.h>\r
20 #include <modules/decklink/consumer/decklink_consumer.h>\r
21 #include <modules/ogl/consumer/ogl_consumer.h>\r
22 #include <modules/ffmpeg/consumer/ffmpeg_consumer.h>\r
23 \r
24 #include <protocol/amcp/AMCPProtocolStrategy.h>\r
25 #include <protocol/cii/CIIProtocolStrategy.h>\r
26 #include <protocol/CLK/CLKProtocolStrategy.h>\r
27 #include <protocol/util/AsyncEventServer.h>\r
28 \r
29 #include <boost/algorithm/string.hpp>\r
30 #include <boost/lexical_cast.hpp>\r
31 #include <boost/filesystem.hpp>\r
32 #include <boost/foreach.hpp>\r
33 #include <boost/property_tree/ptree.hpp>\r
34 #include <boost/property_tree/xml_parser.hpp>\r
35 \r
36 namespace caspar {\r
37 \r
38 using namespace core;\r
39 using namespace protocol;\r
40 \r
41 struct server::implementation : boost::noncopyable\r
42 {\r
43         std::vector<safe_ptr<IO::AsyncEventServer>> async_servers_;     \r
44         std::vector<safe_ptr<channel>> channels_;\r
45 \r
46         implementation()                                                                                                \r
47         {                       \r
48                 init_ffmpeg();\r
49                 init_bluefish();\r
50                 init_decklink();\r
51                 init_flash();\r
52                 init_oal();\r
53                 init_ogl();\r
54                 init_silverlight();\r
55                 init_image();\r
56 \r
57                 setup_channels(env::properties());\r
58                 setup_controllers(env::properties());\r
59         }\r
60 \r
61         ~implementation()\r
62         {                               \r
63                 async_servers_.clear();\r
64                 channels_.clear();\r
65         }\r
66                                 \r
67         void setup_channels(const boost::property_tree::ptree& pt)\r
68         {   \r
69                 using boost::property_tree::ptree;\r
70                 BOOST_FOREACH(auto& xml_channel, pt.get_child("configuration.channels"))\r
71                 {               \r
72                         auto format_desc = video_format_desc::get(widen(xml_channel.second.get("videomode", "PAL")));           \r
73                         if(format_desc.format == video_format::invalid)\r
74                                 BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("Invalid videomode."));\r
75                         \r
76                         channels_.push_back(channel(channels_.size(), format_desc));\r
77                         \r
78                         int index = 0;\r
79                         BOOST_FOREACH(auto& xml_consumer, xml_channel.second.get_child("consumers"))\r
80                         {\r
81                                 try\r
82                                 {\r
83                                         std::string name = xml_consumer.first;\r
84                                         if(name == "ogl")\r
85                                         {                       \r
86                                                 int device = xml_consumer.second.get("device", 0);\r
87                         \r
88                                                 stretch stretch = stretch::fill;\r
89                                                 std::string stretchStr = xml_consumer.second.get("stretch", "");\r
90                                                 if(stretchStr == "none")\r
91                                                         stretch = stretch::none;\r
92                                                 else if(stretchStr == "uniform")\r
93                                                         stretch = stretch::uniform;\r
94                                                 else if(stretchStr == "uniformtofill")\r
95                                                         stretch = stretch::uniform_to_fill;\r
96 \r
97                                                 bool windowed = xml_consumer.second.get("windowed", false);\r
98                                                 channels_.back()->consumer()->add(index++, ogl_consumer(device, stretch, windowed));\r
99                                         }\r
100                                         else if(name == "bluefish")                                     \r
101                                                 channels_.back()->consumer()->add(index++, bluefish_consumer(xml_consumer.second.get("device", 0), \r
102                                                                                                                                                                         xml_consumer.second.get("embedded-audio", true)));                                      \r
103                                         else if(name == "decklink")\r
104                                                 channels_.back()->consumer()->add(index++, decklink_consumer(xml_consumer.second.get("device", 0), \r
105                                                                                                                                                                         xml_consumer.second.get("embedded-audio", true), \r
106                                                                                                                                                                         xml_consumer.second.get("internal-key", false)));\r
107                                         else if(name == "audio")\r
108                                                 channels_.back()->consumer()->add(index++, oal_consumer());                     \r
109                                 }\r
110                                 catch(...)\r
111                                 {\r
112                                         CASPAR_LOG_CURRENT_EXCEPTION();\r
113                                 }\r
114                         }                                                       \r
115                 }\r
116         }\r
117                 \r
118         void setup_controllers(const boost::property_tree::ptree& pt)\r
119         {               \r
120                 using boost::property_tree::ptree;\r
121                 BOOST_FOREACH(auto& xml_controller, pt.get_child("configuration.controllers"))\r
122                 {\r
123                         try\r
124                         {\r
125                                 std::string name = xml_controller.first;\r
126                                 std::string protocol = xml_controller.second.get<std::string>("protocol");      \r
127 \r
128                                 if(name == "tcp")\r
129                                 {                                       \r
130                                         unsigned int port = xml_controller.second.get("port", 5250);\r
131                                         auto asyncbootstrapper = make_safe<IO::AsyncEventServer>(create_protocol(protocol), port);\r
132                                         asyncbootstrapper->Start();\r
133                                         async_servers_.push_back(asyncbootstrapper);\r
134                                 }\r
135                                 else\r
136                                         BOOST_THROW_EXCEPTION(invalid_bootstrapper() << arg_name_info(name) << msg_info("Invalid controller."));\r
137                         }\r
138                         catch(...)\r
139                         {\r
140                                 CASPAR_LOG_CURRENT_EXCEPTION();\r
141                         }\r
142                 }\r
143         }\r
144 \r
145         safe_ptr<IO::IProtocolStrategy> create_protocol(const std::string& name) const\r
146         {\r
147                 if(name == "AMCP")\r
148                         return make_safe<amcp::AMCPProtocolStrategy>(channels_);\r
149                 else if(name == "CII")\r
150                         return make_safe<cii::CIIProtocolStrategy>(channels_);\r
151                 else if(name == "CLOCK")\r
152                         return make_safe<CLK::CLKProtocolStrategy>(channels_);\r
153                 \r
154                 BOOST_THROW_EXCEPTION(invalid_bootstrapper() << arg_name_info("name") << arg_value_info(name) << msg_info("Invalid protocol"));\r
155         }\r
156 };\r
157 \r
158 server::server() : impl_(new implementation()){}\r
159 \r
160 const std::vector<safe_ptr<channel>> server::get_channels() const\r
161 {\r
162         return impl_->channels_;\r
163 }\r
164 \r
165 }