]> git.sesse.net Git - casparcg/blob - shell/main.cpp
2.0.0.2: Fixed loop frame seeking.
[casparcg] / shell / main.cpp
1 /*\r
2 * copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\r
3 *\r
4 *  This file is part of CasparCG.\r
5 *\r
6 *    CasparCG is free software: you can redistribute it and/or modify\r
7 *    it under the terms of the GNU General Public License as published by\r
8 *    the Free Software Foundation, either version 3 of the License, or\r
9 *    (at your option) any later version.\r
10 *\r
11 *    CasparCG is distributed in the hope that it will be useful,\r
12 *    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14 *    GNU General Public License for more details.\r
15 \r
16 *    You should have received a copy of the GNU General Public License\r
17 *    along with CasparCG.  If not, see <http://www.gnu.org/licenses/>.\r
18 *\r
19 */\r
20 \r
21 #include <windows.h>\r
22 #include <conio.h>\r
23 \r
24 #include <tbb/tbbmalloc_proxy.h>\r
25 #include <tbb/task_scheduler_observer.h>\r
26 \r
27 #ifdef _DEBUG\r
28         #define _CRTDBG_MAP_ALLOC\r
29         #include <stdlib.h>\r
30         #include <crtdbg.h>\r
31 #endif\r
32 \r
33 #include "bootstrapper.h"\r
34 \r
35 #include <modules/bluefish/bluefish.h>\r
36 \r
37 #include <modules/decklink/decklink.h>\r
38 #include <modules/flash/flash.h>\r
39 #include <modules/ffmpeg/ffmpeg.h>\r
40 #include <modules/image/image.h>\r
41 \r
42 #include <common/env.h>\r
43 #include <common/exception/win32_exception.h>\r
44 #include <common/exception/exceptions.h>\r
45 #include <common/log/log.h>\r
46 #include <common/utility/assert.h>\r
47 \r
48 #include <mixer/gpu/ogl_device.h>\r
49 \r
50 #include <protocol/amcp/AMCPProtocolStrategy.h>\r
51 \r
52 #include <boost/foreach.hpp>\r
53 \r
54 #include <Glee.h>\r
55 \r
56 using namespace caspar;\r
57 using namespace caspar::core;\r
58 using namespace caspar::protocol;\r
59 \r
60 #include <atlbase.h>\r
61 \r
62 // NOTE: This is needed in order to make CComObject work since this is not a real ATL project.\r
63 CComModule _AtlModule;\r
64 extern __declspec(selectany) CAtlModule* _pAtlModule = &_AtlModule;\r
65 \r
66 class win32_handler_tbb_installer : public tbb::task_scheduler_observer\r
67 {\r
68 public:\r
69         win32_handler_tbb_installer()   {observe(true);}\r
70         void on_scheduler_entry(bool is_worker) \r
71         {\r
72                 //CASPAR_LOG(debug) << L"Started TBB Worker Thread.";\r
73                 win32_exception::install_handler();\r
74         }\r
75         void on_scheduler_exit()\r
76         {\r
77                 //CASPAR_LOG(debug) << L"Stopped TBB Worker Thread.";\r
78         }\r
79 };\r
80 \r
81 void setup_console_window()\r
82 {       \r
83         auto hOut = GetStdHandle(STD_OUTPUT_HANDLE);\r
84 \r
85         EnableMenuItem(GetSystemMenu(GetConsoleWindow(), FALSE), SC_CLOSE , MF_GRAYED);\r
86         DrawMenuBar(GetConsoleWindow());\r
87 \r
88         auto coord = GetLargestConsoleWindowSize(hOut);\r
89         coord.X /= 2;\r
90 \r
91         SetConsoleScreenBufferSize(hOut, coord);\r
92 \r
93         SMALL_RECT DisplayArea = {0, 0, 0, 0};\r
94         DisplayArea.Right = coord.X-1;\r
95         DisplayArea.Bottom = coord.Y-1;\r
96         SetConsoleWindowInfo(hOut, TRUE, &DisplayArea);\r
97                 \r
98         std::wstringstream str;\r
99         str << "CasparCG Server " << env::version();\r
100         SetConsoleTitle(str.str().c_str());\r
101 }\r
102 \r
103 void print_version()\r
104 {\r
105         CASPAR_LOG(info) << L"Copyright (c) 2010 Sveriges Television AB, www.casparcg.com, <info@casparcg.com>";\r
106         CASPAR_LOG(info) << L"Starting CasparCG Video and Graphics Playout Server " << env::version();\r
107         CASPAR_LOG(info) << L"Flash " << get_flash_version();\r
108         CASPAR_LOG(info) << L"Flash-Template-Host " << get_cg_version();\r
109         CASPAR_LOG(info) << L"FreeImage " << get_image_version();\r
110         \r
111         std::wstring decklink_devices;\r
112         BOOST_FOREACH(auto& device, get_decklink_device_list())\r
113                 decklink_devices += L"\t" + device;\r
114         CASPAR_LOG(info) << L"Decklink " << get_decklink_version() << (decklink_devices.empty() ? L"" : L"\n\tDevices:\n" + decklink_devices);\r
115         \r
116         std::wstring bluefish_devices;\r
117         BOOST_FOREACH(auto& device, get_bluefish_device_list())\r
118                 bluefish_devices += L"\t" + device;\r
119         CASPAR_LOG(info) << L"Bluefish " << get_bluefish_version() << (bluefish_devices.empty() ? L"" : L"\n\tDevices:\n" + bluefish_devices);\r
120 \r
121         CASPAR_LOG(info) << L"FFMPEG-avcodec "  << get_avcodec_version();\r
122         CASPAR_LOG(info) << L"FFMPEG-swscale "  << get_avformat_version();\r
123         CASPAR_LOG(info) << L"FFMPEG-avformat " << get_swscale_version();\r
124         CASPAR_LOG(info) << L"OpenGL " << mixer::ogl_device::create()->invoke([]{return reinterpret_cast<const char*>(glGetString(GL_VERSION));})\r
125                                          << L" "           << mixer::ogl_device::create()->invoke([]{return reinterpret_cast<const char*>(glGetString(GL_VENDOR));});\r
126 \r
127         HKEY hkey; \r
128         DWORD dwType, dwSize;\r
129         if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"), 0, KEY_QUERY_VALUE, &hkey) == ERROR_SUCCESS)\r
130         {\r
131                 wchar_t p_name_str[1024];\r
132                 wchar_t csd_ver_str[1024];\r
133 \r
134                 dwType = REG_SZ;\r
135                 dwSize = sizeof(p_name_str);\r
136 \r
137                 if(RegQueryValueEx(hkey, TEXT("ProductName"), NULL, &dwType, (PBYTE)&p_name_str, &dwSize) == ERROR_SUCCESS &&\r
138                    RegQueryValueEx(hkey, TEXT("CSDVersion"), NULL, &dwType, (PBYTE)&csd_ver_str, &dwSize) == ERROR_SUCCESS)             \r
139                 {\r
140                         CASPAR_LOG(info) << p_name_str << L" " << csd_ver_str << L"." << L"\n";\r
141                 }\r
142                 else\r
143                         CASPAR_LOG(warning) << "Could not read OS info." << L"\n";\r
144                  \r
145                 RegCloseKey(hkey);\r
146         }\r
147 }\r
148  \r
149 int main(int argc, wchar_t* argv[])\r
150 {               \r
151         #ifdef _DEBUG\r
152                 _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF | _CRTDBG_CHECK_ALWAYS_DF );\r
153                 _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_DEBUG );\r
154                 _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_DEBUG );\r
155                 _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_DEBUG );\r
156 \r
157                 if(env::properties().get("configuration.debugging.remote", false))\r
158                         MessageBox(nullptr, TEXT("Now is the time to connect for remote debugging..."), TEXT("Debug"), MB_OK | MB_TOPMOST);\r
159         #endif\r
160                 \r
161         // Increase time precision\r
162         timeBeginPeriod(1);\r
163         win32_handler_tbb_installer win32_handler_tbb_installer;\r
164         win32_exception::install_handler();\r
165 \r
166         try \r
167         {\r
168                 env::initialize("caspar.config");\r
169                 \r
170                 setup_console_window();                                                  \r
171                 log::add_file_sink(env::log_folder());\r
172 \r
173                 print_version();\r
174                                 \r
175                 bootstrapper caspar_device;\r
176                                 \r
177                 auto dummy = std::make_shared<IO::ConsoleClientInfo>();\r
178                 amcp::AMCPProtocolStrategy amcp(caspar_device.get_channels());\r
179                 bool is_running = true;\r
180                 while(is_running)\r
181                 {\r
182                         std::wstring wcmd;\r
183                         std::getline(std::wcin, wcmd); // TODO: It's blocking...\r
184                         is_running = wcmd != L"exit" && wcmd != L"q";\r
185                         if(wcmd.substr(0, 2) == L"12")\r
186                         {\r
187                                 wcmd = L"LOADBG 1-1 A LOOP \r\nPLAY 1-1\r\n";\r
188                                 amcp.Parse(wcmd.c_str(), wcmd.length(), dummy);\r
189                                 wcmd = L"LOADBG 1-2 DV LOOP AUTOPLAY\r\nnPLAY 1-1\r\n";\r
190                                 amcp.Parse(wcmd.c_str(), wcmd.length(), dummy);\r
191                                 wcmd = L"MIXER 1-1 VIDEO FIX_RECT 0.0 0.0 0.5 0.5\r\n";\r
192                                 amcp.Parse(wcmd.c_str(), wcmd.length(), dummy);\r
193                                 wcmd = L"MIXER 1-2 VIDEO FIX_RECT 0.5 0.0 0.5 0.5\r\n";\r
194                                 amcp.Parse(wcmd.c_str(), wcmd.length(), dummy);\r
195                         }\r
196                         else if(wcmd.substr(0, 2) == L"10")\r
197                                 wcmd = L"MIXER 1-1 VIDEO CLIP_RECT 0.4 0.4 0.5 0.5";\r
198                         if(wcmd.substr(0, 2) == L"11")\r
199                                 wcmd = L"MIXER 1-1 VIDEO FIX_RECT 0.4 0.4 0.5 0.5";\r
200                         else if(wcmd.substr(0, 1) == L"1")\r
201                                 wcmd = L"LOADBG 1-1 " + wcmd.substr(1, wcmd.length()-1) + L" SLIDE 100 LOOP \r\nPLAY 1-1";\r
202                         else if(wcmd.substr(0, 1) == L"2")\r
203                                 wcmd = L"LOADBG 1-1 " + wcmd.substr(1, wcmd.length()-1) + L" PUSH 100 LOOP \r\nPLAY 1-1";\r
204                         else if(wcmd.substr(0, 1) == L"3")\r
205                                 wcmd = L"LOADBG 1-1 " + wcmd.substr(1, wcmd.length()-1) + L" MIX 100 LOOP \r\nPLAY 1-1";\r
206                         else if(wcmd.substr(0, 1) == L"4")\r
207                                 wcmd = L"LOADBG 1-1 " + wcmd.substr(1, wcmd.length()-1) + L" WIPE 100 LOOP \r\nPLAY 1-1";\r
208                         else if(wcmd.substr(0, 1) == L"5")\r
209                                 wcmd = L"LOADBG 1-2 " + wcmd.substr(1, wcmd.length()-1) + L" LOOP \r\nPLAY 1-2";\r
210                         else if(wcmd.substr(0, 1) == L"6")\r
211                                 wcmd = L"CG 1-2 ADD 1 THING 1";\r
212                         else if(wcmd.substr(0, 1) == L"7")\r
213                                 wcmd = L"LOAD 1-1 720p2500";\r
214                         else if(wcmd.substr(0, 1) == L"8")\r
215                                 wcmd = L"LOAD 1-1 #FFFFFFFF AUTOPLAY";\r
216                         else if(wcmd.substr(0, 1) == L"9")\r
217                                 wcmd = L"LOADBG 1-2 " + wcmd.substr(1, wcmd.length()-1) + L" [1.0-2.0] LOOP AUTOPLAY";\r
218 \r
219                         wcmd += L"\r\n";\r
220                         amcp.Parse(wcmd.c_str(), wcmd.length(), dummy);\r
221                 }\r
222         }\r
223         catch(const std::exception&)\r
224         {\r
225                 CASPAR_LOG(fatal) << "UNHANDLED EXCEPTION in main thread.";\r
226                 CASPAR_LOG_CURRENT_EXCEPTION();\r
227                 std::wcout << L"Press Any Key To Exit\n";\r
228                 _getwch();\r
229         }       \r
230 \r
231         timeEndPeriod(1);\r
232 \r
233         CASPAR_LOG(info) << "Successfully shutdown CasparCG Server";\r
234         \r
235         return 0;\r
236 }