]> git.sesse.net Git - casparcg/blob - protocol/amcp/amcp_command_repository.cpp
06249814def23a49a9bbaed5bc2229f9c7d68b3f
[casparcg] / protocol / amcp / amcp_command_repository.cpp
1 /*
2 * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>
3 *
4 * This file is part of CasparCG (www.casparcg.com).
5 *
6 * CasparCG is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * CasparCG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with CasparCG. If not, see <http://www.gnu.org/licenses/>.
18 *
19 * Author: Helge Norberg, helge.norberg@svt.se
20 */
21
22 #include "../StdAfx.h"
23
24 #include "amcp_command_repository.h"
25
26 #include <map>
27
28 namespace caspar { namespace protocol { namespace amcp {
29
30 AMCPCommand::ptr_type find_command(
31                 const std::map<std::wstring, std::pair<amcp_command_func, int>>& commands,
32                 const std::wstring& str,
33                 const command_context& ctx,
34                 std::list<std::wstring>& tokens)
35 {
36         std::wstring subcommand;
37
38         if (!tokens.empty())
39                 subcommand = boost::to_upper_copy(tokens.front());
40
41         // Start with subcommand syntax like MIXER CLEAR etc
42         if (!subcommand.empty())
43         {
44                 auto s = str + L" " + subcommand;
45                 auto subcmd = commands.find(s);
46
47                 if (subcmd != commands.end())
48                 {
49                         tokens.pop_front();
50                         return std::make_shared<AMCPCommand>(ctx, subcmd->second.first, subcmd->second.second, s);
51                 }
52         }
53
54         // Resort to ordinary command
55         auto s = str;
56         auto command = commands.find(s);
57
58         if (command != commands.end())
59                 return std::make_shared<AMCPCommand>(ctx, command->second.first, command->second.second, s);
60
61         return nullptr;
62 }
63
64 struct amcp_command_repository::impl
65 {
66         std::vector<channel_context>                                                            channels;
67         std::shared_ptr<core::thumbnail_generator>                                      thumb_gen;
68         spl::shared_ptr<core::media_info_repository>                            media_info_repo;
69         spl::shared_ptr<core::system_info_provider_repository>          system_info_provider_repo;
70         spl::shared_ptr<core::cg_producer_registry>                                     cg_registry;
71         spl::shared_ptr<core::help_repository>                                          help_repo;
72         spl::shared_ptr<const core::frame_producer_registry>            producer_registry;
73         spl::shared_ptr<const core::frame_consumer_registry>            consumer_registry;
74         std::shared_ptr<accelerator::ogl::device>                                       ogl_device;
75         std::promise<bool>&                                                                                     shutdown_server_now;
76
77         std::map<std::wstring, std::pair<amcp_command_func, int>>       commands;
78         std::map<std::wstring, std::pair<amcp_command_func, int>>       channel_commands;
79
80         impl(
81                         const std::vector<spl::shared_ptr<core::video_channel>>& channels,
82                         const std::shared_ptr<core::thumbnail_generator>& thumb_gen,
83                         const spl::shared_ptr<core::media_info_repository>& media_info_repo,
84                         const spl::shared_ptr<core::system_info_provider_repository>& system_info_provider_repo,
85                         const spl::shared_ptr<core::cg_producer_registry>& cg_registry,
86                         const spl::shared_ptr<core::help_repository>& help_repo,
87                         const spl::shared_ptr<const core::frame_producer_registry>& producer_registry,
88                         const spl::shared_ptr<const core::frame_consumer_registry>& consumer_registry,
89                         const std::shared_ptr<accelerator::ogl::device>& ogl_device,
90                         std::promise<bool>& shutdown_server_now)
91                 : thumb_gen(thumb_gen)
92                 , media_info_repo(media_info_repo)
93                 , system_info_provider_repo(system_info_provider_repo)
94                 , cg_registry(cg_registry)
95                 , help_repo(help_repo)
96                 , producer_registry(producer_registry)
97                 , consumer_registry(consumer_registry)
98                 , ogl_device(ogl_device)
99                 , shutdown_server_now(shutdown_server_now)
100         {
101                 int index = 0;
102                 for (const auto& channel : channels)
103                 {
104                         std::wstring lifecycle_key = L"lock" + boost::lexical_cast<std::wstring>(index);
105                         this->channels.push_back(channel_context(channel, lifecycle_key));
106                         ++index;
107                 }
108         }
109 };
110
111 amcp_command_repository::amcp_command_repository(
112                 const std::vector<spl::shared_ptr<core::video_channel>>& channels,
113                 const std::shared_ptr<core::thumbnail_generator>& thumb_gen,
114                 const spl::shared_ptr<core::media_info_repository>& media_info_repo,
115                 const spl::shared_ptr<core::system_info_provider_repository>& system_info_provider_repo,
116                 const spl::shared_ptr<core::cg_producer_registry>& cg_registry,
117                 const spl::shared_ptr<core::help_repository>& help_repo,
118                 const spl::shared_ptr<const core::frame_producer_registry>& producer_registry,
119                 const spl::shared_ptr<const core::frame_consumer_registry>& consumer_registry,
120                 const std::shared_ptr<accelerator::ogl::device>& ogl_device,
121                 std::promise<bool>& shutdown_server_now)
122                 : impl_(new impl(
123                                 channels,
124                                 thumb_gen,
125                                 media_info_repo,
126                                 system_info_provider_repo,
127                                 cg_registry,
128                                 help_repo,
129                                 producer_registry,
130                                 consumer_registry,
131                                 ogl_device,
132                                 shutdown_server_now))
133 {
134 }
135
136 AMCPCommand::ptr_type amcp_command_repository::create_command(const std::wstring& s, IO::ClientInfoPtr client, std::list<std::wstring>& tokens) const
137 {
138         auto& self = *impl_;
139
140         command_context ctx(
141                         std::move(client),
142                         channel_context(),
143                         -1,
144                         -1,
145                         self.channels,
146                         self.help_repo,
147                         self.media_info_repo,
148                         self.cg_registry,
149                         self.system_info_provider_repo,
150                         self.thumb_gen,
151                         self.producer_registry,
152                         self.consumer_registry,
153                         self.ogl_device,
154                         self.shutdown_server_now);
155
156         auto command = find_command(self.commands, s, ctx, tokens);
157
158         if (command)
159                 return command;
160
161         return nullptr;
162 }
163
164 const std::vector<channel_context>& amcp_command_repository::channels() const
165 {
166         return impl_->channels;
167 }
168
169 AMCPCommand::ptr_type amcp_command_repository::create_channel_command(
170                 const std::wstring& s,
171                 IO::ClientInfoPtr client,
172                 unsigned int channel_index,
173                 int layer_index,
174                 std::list<std::wstring>& tokens) const
175 {
176         auto& self = *impl_;
177
178         auto channel = self.channels.at(channel_index);
179
180         command_context ctx(
181                         std::move(client),
182                         channel,
183                         channel_index,
184                         layer_index,
185                         self.channels,
186                         self.help_repo,
187                         self.media_info_repo,
188                         self.cg_registry,
189                         self.system_info_provider_repo,
190                         self.thumb_gen,
191                         self.producer_registry,
192                         self.consumer_registry,
193                         self.ogl_device,
194                         self.shutdown_server_now);
195
196         auto command = find_command(self.channel_commands, s, ctx, tokens);
197
198         if (command)
199                 return command;
200
201         return nullptr;
202 }
203
204 void amcp_command_repository::register_command(
205                 std::wstring category,
206                 std::wstring name,
207                 core::help_item_describer describer,
208                 amcp_command_func command,
209                 int min_num_params)
210 {
211         auto& self = *impl_;
212         self.help_repo->register_item({ L"AMCP", category }, name, describer);
213         self.commands.insert(std::make_pair(std::move(name), std::make_pair(std::move(command), min_num_params)));
214 }
215
216 void amcp_command_repository::register_channel_command(
217                 std::wstring category,
218                 std::wstring name,
219                 core::help_item_describer describer,
220                 amcp_command_func command,
221                 int min_num_params)
222 {
223         auto& self = *impl_;
224         self.help_repo->register_item({ L"AMCP", category }, name, describer);
225         self.channel_commands.insert(std::make_pair(std::move(name), std::make_pair(std::move(command), min_num_params)));
226 }
227
228 }}}