void format_terminal_message(TerminalData *data, TerminalText *text) { struct tm *local = localtime(&(data->time)); char date_string[20]; char day_string[20]; char time_string[20]; format_date(date_string, 20, local); strftime(day_string, 20, "%A", local); clock_copy_time_string(time_string, 20); make_upper_case(date_string, 20); make_upper_case(day_string, 20); make_upper_case(time_string, 20); const char * format_string = "%s\n" //City "%s\n" //Temperature "%s\n" //Forecast "%s\n" //Date "%s\n" //Day of week "BATTERY %u\n" //Battery "%u STEPS\n" //Step count "%s"; //Time snprintf(text->text_buffer, TERMINAL_BUFFER_SIZE, format_string, data->city, data->temperature, data->forecast, date_string, day_string, data->battery_level, data->step_count, time_string); }
int main(int argc, wchar_t* argv[]) { static_assert(sizeof(void*) == 4, "64-bit code generation is not supported."); SetUnhandledExceptionFilter(UserUnhandledExceptionFilter); setup_global_locale(); std::wcout << L"Type \"q\" to close application." << std::endl; // Set debug mode. #ifdef _DEBUG HANDLE hLogFile; hLogFile = CreateFile(L"crt_log.txt", GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); std::shared_ptr<void> crt_log(nullptr, [](HANDLE h){::CloseHandle(h);}); _CrtSetDbgFlag (_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); _CrtSetReportFile(_CRT_WARN, hLogFile); _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); _CrtSetReportFile(_CRT_ERROR, hLogFile); _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); _CrtSetReportFile(_CRT_ASSERT, hLogFile); #endif // Increase process priotity. SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS); // Install structured exception handler. caspar::win32_exception::install_handler(); // Increase time precision. This will increase accuracy of function like Sleep(1) from 10 ms to 1 ms. struct inc_prec { inc_prec(){timeBeginPeriod(1);} ~inc_prec(){timeEndPeriod(1);} } inc_prec; // Install unstructured exception handlers into all tbb threads. struct tbb_thread_installer : public tbb::task_scheduler_observer { tbb_thread_installer(){observe(true);} void on_scheduler_entry(bool is_worker) { //caspar::detail::SetThreadName(GetCurrentThreadId(), "tbb-worker-thread"); caspar::win32_exception::install_handler(); } } tbb_thread_installer; tbb::task_scheduler_init init; try { // Configure environment properties from configuration. caspar::env::configure(L"casparcg.config"); caspar::log::set_log_level(caspar::env::properties().get(L"configuration.log-level", L"debug")); #ifdef _DEBUG if(caspar::env::properties().get(L"configuration.debugging.remote", false)) MessageBox(nullptr, TEXT("Now is the time to connect for remote debugging..."), TEXT("Debug"), MB_OK | MB_TOPMOST); #endif // Start logging to file. caspar::log::add_file_sink(caspar::env::log_folder()); std::wcout << L"Logging [info] or higher severity to " << caspar::env::log_folder() << std::endl << std::endl; // Setup console window. setup_console_window(); // Print environment information. print_info(); std::wstringstream str; boost::property_tree::xml_writer_settings<wchar_t> w(' ', 3); boost::property_tree::write_xml(str, caspar::env::properties(), w); CASPAR_LOG(info) << L"casparcg.config:\n-----------------------------------------\n" << str.str().c_str() << L"-----------------------------------------"; bool wait_for_keypress; { boost::promise<bool> shutdown_server_now; boost::unique_future<bool> shutdown_server = shutdown_server_now.get_future(); // Create server object which initializes channels, protocols and controllers. caspar::server caspar_server(shutdown_server_now); // Use separate thread for the blocking console input, will be terminated // anyway when the main thread terminates. boost::thread stdin_thread([&caspar_server, &shutdown_server_now] { // Create a amcp parser for console commands. caspar::protocol::amcp::AMCPProtocolStrategy amcp( caspar_server.get_channels(), caspar_server.get_thumbnail_generator(), shutdown_server_now); // Create a dummy client which prints amcp responses to console. auto console_client = std::make_shared<caspar::IO::ConsoleClientInfo>(); std::wstring wcmd; while(true) { std::getline(std::wcin, wcmd); // TODO: It's blocking... //boost::to_upper(wcmd); // TODO COMPILER crashes on this line, Strange! make_upper_case(wcmd); if(wcmd == L"EXIT" || wcmd == L"Q" || wcmd == L"QUIT" || wcmd == L"BYE") { shutdown_server_now.set_value(true); // True to wait for keypress break; } try { // This is just dummy code for testing. if(wcmd.substr(0, 1) == L"1") wcmd = L"LOADBG 1-1 " + wcmd.substr(1, wcmd.length()-1) + L" SLIDE 100 LOOP \r\nPLAY 1-1"; else if(wcmd.substr(0, 1) == L"2") wcmd = L"MIXER 1-0 VIDEO IS_KEY 1"; else if(wcmd.substr(0, 1) == L"3") wcmd = L"CG 1-2 ADD 1 BBTELEFONARE 1"; else if(wcmd.substr(0, 1) == L"4") wcmd = L"PLAY 1-1 DV FILTER yadif=1:-1 LOOP"; else if(wcmd.substr(0, 1) == L"5") { auto file = wcmd.substr(2, wcmd.length()-1); wcmd = L"PLAY 1-1 " + file + L" LOOP\r\n" L"PLAY 1-2 " + file + L" LOOP\r\n" L"PLAY 1-3 " + file + L" LOOP\r\n" L"PLAY 2-1 " + file + L" LOOP\r\n" L"PLAY 2-2 " + file + L" LOOP\r\n" L"PLAY 2-3 " + file + L" LOOP\r\n"; } else if(wcmd.substr(0, 1) == L"X") { int num = 0; std::wstring file; try { num = boost::lexical_cast<int>(wcmd.substr(1, 2)); file = wcmd.substr(4, wcmd.length()-1); } catch(...) { num = boost::lexical_cast<int>(wcmd.substr(1, 1)); file = wcmd.substr(3, wcmd.length()-1); } int n = 0; int num2 = num; while(num2 > 0) { num2 >>= 1; n++; } wcmd = L"MIXER 1 GRID " + boost::lexical_cast<std::wstring>(n); for(int i = 1; i <= num; ++i) wcmd += L"\r\nPLAY 1-" + boost::lexical_cast<std::wstring>(i) + L" " + file + L" LOOP";// + L" SLIDE 100 LOOP"; } } catch (...) { CASPAR_LOG_CURRENT_EXCEPTION(); continue; } wcmd += L"\r\n"; amcp.Parse(wcmd.c_str(), wcmd.length(), console_client); } }); stdin_thread.detach(); wait_for_keypress = shutdown_server.get(); } Sleep(500); CASPAR_LOG(info) << "Successfully shutdown CasparCG Server."; if (wait_for_keypress) system("pause"); }