diff --git a/CMakeLists.txt b/CMakeLists.txt index 27551cba..9e6252df 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}) find_package(Threads REQUIRED) find_package(OpenSSL REQUIRED) find_package(FFmpeg REQUIRED) -find_package(Boost COMPONENTS filesystem REQUIRED) +find_package(Boost COMPONENTS filesystem log REQUIRED) add_subdirectory(Simple-Web-Server) add_subdirectory(moonlight-common-c/enet) diff --git a/assets/sunshine.conf b/assets/sunshine.conf index ecc500fa..45749b93 100644 --- a/assets/sunshine.conf +++ b/assets/sunshine.conf @@ -10,6 +10,20 @@ # The name displayed by Moonlight sunshine_name = Sunshine +# The minimum log level printed to standard out +# +# none -> no logs are printed to standard out +# +# verbose = [0] +# debug = [1] +# info = [2] +# warning = [3] +# error = [4] +# fatal = [5] +# none = [6] +# +# min_log_level = info + # The origin of the remote endpoint address that is not denied for HTTP method /pin # Could be any of the following values: # pc|lan|wan diff --git a/sunshine/audio.cpp b/sunshine/audio.cpp index 1d78175a..936064a3 100644 --- a/sunshine/audio.cpp +++ b/sunshine/audio.cpp @@ -1,5 +1,4 @@ #include -#include #include @@ -8,6 +7,7 @@ #include "utility.h" #include "thread_safe.h" #include "audio.h" +#include "main.h" namespace audio { using namespace std::literals; @@ -69,8 +69,10 @@ void encodeThread(std::shared_ptr> packets, sample_queue int bytes = opus_multistream_encode(opus.get(), sample->data(), frame_size, std::begin(packet), packet.size()); if(bytes < 0) { - std::cout << "Error: "sv << opus_strerror(bytes) << std::endl; - exit(7); + BOOST_LOG(error) << opus_strerror(bytes); + packets->stop(); + + return; } packet.fake_resize(bytes); @@ -83,7 +85,7 @@ void capture(std::shared_ptr> packets, config_t config) auto mic = platf::microphone(); if(!mic) { - std::cout << "Error creating audio input"sv << std::endl; + BOOST_LOG(error) << "Couldn't create audio input"sv ; } //FIXME: Pick correct opus_stream_config_t based on config.channels diff --git a/sunshine/config.cpp b/sunshine/config.cpp index 31aa9b29..01c09cfe 100644 --- a/sunshine/config.cpp +++ b/sunshine/config.cpp @@ -1,6 +1,5 @@ -#include #include -#include +#include #include #include @@ -49,6 +48,10 @@ input_t input { 2s }; +sunshine_t sunshine { + 2 // min_log_level +}; + bool whitespace(char ch) { return ch == ' ' || ch == '\t'; } @@ -150,7 +153,7 @@ void parse_file(const char *file) { }); for(auto &[name, val] : vars) { - std::cout << "["sv << name << "] -- ["sv << val << "]"sv << std::endl; + std::cout << "["sv << name << "] -- ["sv << val << ']' << std::endl; } int_f(vars, "max_b_frames", video.max_b_frames); @@ -187,6 +190,35 @@ void parse_file(const char *file) { if(to > std::numeric_limits::min()) { input.back_button_timeout = std::chrono::milliseconds {to }; } + + std::string log_level_string; + string_restricted_f(vars, "min_log_level", log_level_string, { + "verbose"sv, "debug"sv, "info"sv, "warning"sv, "error"sv, "fatal"sv, "none"sv + }); + + if(log_level_string.empty()) { + if(log_level_string == "verbose"sv) { + sunshine.min_log_level = 0; + } + else if(log_level_string == "debug"sv) { + sunshine.min_log_level = 1; + } + else if(log_level_string == "info"sv) { + sunshine.min_log_level = 2; + } + else if(log_level_string == "warning"sv) { + sunshine.min_log_level = 3; + } + else if(log_level_string == "error"sv) { + sunshine.min_log_level = 4; + } + else if(log_level_string == "fatal"sv) { + sunshine.min_log_level = 5; + } + else if(log_level_string == "none"sv) { + sunshine.min_log_level = 6; + } + } } diff --git a/sunshine/config.h b/sunshine/config.h index 521eeabb..1fa7b13e 100644 --- a/sunshine/config.h +++ b/sunshine/config.h @@ -47,10 +47,15 @@ struct input_t { std::chrono::milliseconds back_button_timeout; }; +struct sunshine_t { + int min_log_level; +}; + extern video_t video; extern stream_t stream; extern nvhttp_t nvhttp; extern input_t input; +extern sunshine_t sunshine; void parse_file(const char *file); } diff --git a/sunshine/input.cpp b/sunshine/input.cpp index 8b82ee11..0940a54f 100644 --- a/sunshine/input.cpp +++ b/sunshine/input.cpp @@ -7,7 +7,6 @@ extern "C" { } #include -#include #include "main.h" #include "config.h" @@ -34,55 +33,50 @@ constexpr std::uint16_t X = 0x4000; constexpr std::uint16_t Y = 0x8000; void print(PNV_MOUSE_MOVE_PACKET packet) { - std::cout << "--begin mouse move packet--"sv << std::endl; - - std::cout << "deltaX ["sv << util::endian::big(packet->deltaX) << ']' << std::endl; - std::cout << "deltaY ["sv << util::endian::big(packet->deltaY) << ']' << std::endl; - - std::cout << "--end mouse move packet--"sv << std::endl; + BOOST_LOG(debug) + << "--begin mouse move packet--"sv << std::endl + << "deltaX ["sv << util::endian::big(packet->deltaX) << ']' << std::endl + << "deltaY ["sv << util::endian::big(packet->deltaY) << ']' << std::endl + << "--end mouse move packet--"sv; } void print(PNV_MOUSE_BUTTON_PACKET packet) { - std::cout << "--begin mouse button packet--"sv << std::endl; - - std::cout << "action ["sv << util::hex(packet->action).to_string_view() << ']' << std::endl; - std::cout << "button ["sv << util::hex(packet->button).to_string_view() << ']' << std::endl; - - std::cout << "--end mouse button packet--"sv << std::endl; + BOOST_LOG(debug) + << "--begin mouse button packet--"sv << std::endl + << "action ["sv << util::hex(packet->action).to_string_view() << ']' << std::endl + << "button ["sv << util::hex(packet->button).to_string_view() << ']' << std::endl + << "--end mouse button packet--"sv; } void print(PNV_SCROLL_PACKET packet) { - std::cout << "--begin mouse scroll packet--"sv << std::endl; - - std::cout << "scrollAmt1 ["sv << util::endian::big(packet->scrollAmt1) << ']' << std::endl; - - std::cout << "--end mouse scroll packet--"sv << std::endl; + BOOST_LOG(debug) + << "--begin mouse scroll packet--"sv << std::endl + << "scrollAmt1 ["sv << util::endian::big(packet->scrollAmt1) << ']' << std::endl + << "--end mouse scroll packet--"sv; } void print(PNV_KEYBOARD_PACKET packet) { - std::cout << "--begin keyboard packet--"sv << std::endl; - - std::cout << "keyAction ["sv << util::hex(packet->keyAction).to_string_view() << ']' << std::endl; - std::cout << "keyCode ["sv << util::hex(packet->keyCode).to_string_view() << ']' << std::endl; - std::cout << "modifiers ["sv << util::hex(packet->modifiers).to_string_view() << ']' << std::endl; - - std::cout << "--end keyboard packet--"sv << std::endl; + BOOST_LOG(debug) + << "--begin keyboard packet--"sv << std::endl + << "keyAction ["sv << util::hex(packet->keyAction).to_string_view() << ']' << std::endl + << "keyCode ["sv << util::hex(packet->keyCode).to_string_view() << ']' << std::endl + << "modifiers ["sv << util::hex(packet->modifiers).to_string_view() << ']' << std::endl + << "--end keyboard packet--"sv; } void print(PNV_MULTI_CONTROLLER_PACKET packet) { - std::cout << "--begin controller packet--"sv << std::endl; - - std::cout << "controllerNumber ["sv << packet->controllerNumber << ']' << std::endl; - std::cout << "activeGamepadMask ["sv << util::hex(packet->activeGamepadMask).to_string_view() << ']' << std::endl; - std::cout << "buttonFlags ["sv << util::hex(packet->buttonFlags).to_string_view() << ']' << std::endl; - std::cout << "leftTrigger ["sv << util::hex(packet->leftTrigger).to_string_view() << ']' << std::endl; - std::cout << "rightTrigger ["sv << util::hex(packet->rightTrigger).to_string_view() << ']' << std::endl; - std::cout << "leftStickX ["sv << packet->leftStickX << ']' << std::endl; - std::cout << "leftStickY ["sv << packet->leftStickY << ']' << std::endl; - std::cout << "rightStickX ["sv << packet->rightStickX << ']' << std::endl; - std::cout << "rightStickY ["sv << packet->rightStickY << ']' << std::endl; - - std::cout << "--end controller packet--"sv << std::endl; + BOOST_LOG(debug) + << "--begin controller packet--"sv << std::endl + << "controllerNumber ["sv << packet->controllerNumber << ']' << std::endl + << "activeGamepadMask ["sv << util::hex(packet->activeGamepadMask).to_string_view() << ']' << std::endl + << "buttonFlags ["sv << util::hex(packet->buttonFlags).to_string_view() << ']' << std::endl + << "leftTrigger ["sv << util::hex(packet->leftTrigger).to_string_view() << ']' << std::endl + << "rightTrigger ["sv << util::hex(packet->rightTrigger).to_string_view() << ']' << std::endl + << "leftStickX ["sv << packet->leftStickX << ']' << std::endl + << "leftStickY ["sv << packet->leftStickY << ']' << std::endl + << "rightStickX ["sv << packet->rightStickX << ']' << std::endl + << "rightStickY ["sv << packet->rightStickY << ']' << std::endl + << "--end controller packet--"sv; } constexpr int PACKET_TYPE_SCROLL_OR_KEYBOARD = PACKET_TYPE_SCROLL; diff --git a/sunshine/main.cpp b/sunshine/main.cpp index 43d70344..c2331608 100644 --- a/sunshine/main.cpp +++ b/sunshine/main.cpp @@ -8,6 +8,11 @@ #include #include +#include +#include +#include +#include + #include "nvhttp.h" #include "stream.h" #include "config.h" @@ -17,22 +22,81 @@ extern "C" { #include } -#include "platform/common.h" using namespace std::literals; +namespace bl = boost::log; util::ThreadPool task_pool; +bl::sources::severity_logger verbose(0); // Dominating output +bl::sources::severity_logger debug(1); // Follow what is happening +bl::sources::severity_logger info(2); // Should be informed about +bl::sources::severity_logger warning(3); // Strange events +bl::sources::severity_logger error(4); // Recoverable errors +bl::sources::severity_logger fatal(5); // Unrecoverable errors + bool display_cursor; +using text_sink = bl::sinks::asynchronous_sink; +boost::shared_ptr sink; + +struct NoDelete { + void operator()(void *) {} +}; + +BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", int) + +void log_flush() { + sink->flush(); +} + int main(int argc, char *argv[]) { if(argc > 1) { if(!std::filesystem::exists(argv[1])) { - std::cout << "Error: Couldn't find configuration file ["sv << argv[1] << ']' << std::endl; + std::cout << "Fatal Error: Couldn't find configuration file ["sv << argv[1] << ']' << std::endl; return 7; } config::parse_file(argv[1]); } + sink = boost::make_shared(); + + boost::shared_ptr stream { &std::cout, NoDelete {} }; + sink->locked_backend()->add_stream(stream); + sink->set_filter(severity >= config::sunshine.min_log_level); +// sink->set_formatter(bl::expressions::stream +// << "log level "sv << severity << ": "sv << bl::expressions::smessage); + + sink->set_formatter([severity="Severity"s](const bl::record_view &view, bl::formatting_ostream &os) { + auto log_level = view.attribute_values()[severity].extract().get(); + + std::string_view log_type; + switch(log_level) { + case 0: + log_type = "Verbose: "sv; + break; + case 1: + log_type = "Debug: "sv; + break; + case 2: + log_type = "Info: "sv; + break; + case 3: + log_type = "Warning: "sv; + break; + case 4: + log_type = "Error: "sv; + break; + case 5: + log_type = "Fatal: "sv; + break; + }; + + os << log_type << view.attribute_values()["Message"].extract(); + }); + + bl::core::get()->add_sink(sink); + auto fg = util::fail_guard(log_flush); + auto proc_opt = proc::parse(config::stream.file_apps); if(!proc_opt) { return 7; diff --git a/sunshine/main.h b/sunshine/main.h index 3564b781..b8a85e5b 100644 --- a/sunshine/main.h +++ b/sunshine/main.h @@ -5,9 +5,18 @@ #ifndef SUNSHINE_MAIN_H #define SUNSHINE_MAIN_H +#include #include "thread_pool.h" extern util::ThreadPool task_pool; extern bool display_cursor; +extern boost::log::sources::severity_logger verbose; +extern boost::log::sources::severity_logger debug; +extern boost::log::sources::severity_logger info; +extern boost::log::sources::severity_logger warning; +extern boost::log::sources::severity_logger error; +extern boost::log::sources::severity_logger fatal; + +void log_flush(); #endif //SUNSHINE_MAIN_H diff --git a/sunshine/nvhttp.cpp b/sunshine/nvhttp.cpp index 8bd7d333..18c5e4ec 100644 --- a/sunshine/nvhttp.cpp +++ b/sunshine/nvhttp.cpp @@ -4,7 +4,6 @@ #include "process.h" -#include #include #include @@ -17,13 +16,13 @@ #include #include -#include "uuid.h" #include "config.h" #include "utility.h" #include "stream.h" #include "nvhttp.h" #include "platform/common.h" #include "network.h" +#include "main.h" namespace nvhttp { @@ -124,7 +123,7 @@ void load_devices() { try { pt::read_json(config::nvhttp.file_devices, root); } catch (std::exception &e) { - std::cout << e.what() << std::endl; + BOOST_LOG(warning) << e.what(); return; } @@ -289,22 +288,22 @@ struct tunnel { template void print_req(std::shared_ptr::Request> request) { - std::cout << "TUNNEL :: "sv << tunnel::to_string << std::endl; + BOOST_LOG(debug) << "TUNNEL :: "sv << tunnel::to_string; - std::cout << "METHOD :: "sv << request->method << std::endl; - std::cout << "DESTINATION :: "sv << request->path << std::endl; + BOOST_LOG(debug) << "METHOD :: "sv << request->method; + BOOST_LOG(debug) << "DESTINATION :: "sv << request->path; for(auto &[name, val] : request->header) { - std::cout << name << " -- " << val << std::endl; + BOOST_LOG(debug) << name << " -- " << val; } - std::cout << std::endl; + BOOST_LOG(debug) << " [--] "sv; for(auto &[name, val] : request->parse_query_string()) { - std::cout << name << " -- " << val << std::endl; + BOOST_LOG(debug) << name << " -- " << val; } - std::cout << std::endl; + BOOST_LOG(debug) << " [--] "sv; } template @@ -340,7 +339,7 @@ void pair(std::shared_ptr> &add_cert, std::shared_ sess.client.uniqueID = std::move(uniqID); sess.client.cert = util::from_hex_vec(args.at("clientcert"s), true); - std::cout << sess.client.cert; + BOOST_LOG(debug) << sess.client.cert; auto ptr = map_id_sess.emplace(sess.client.uniqueID, std::move(sess)).first; ptr->second.async_insert_pin.salt = std::move(args.at("salt"s)); @@ -378,7 +377,7 @@ void pin(std::shared_ptr::Response> response, auto address = request->remote_endpoint_address(); auto ip_type = net::from_address(address); if(ip_type > origin_pin_allowed) { - std::cout << '[' << address << "] -- denied"sv << std::endl; + BOOST_LOG(info) << '[' << address << "] -- denied"sv; response->write(SimpleWeb::StatusCode::client_error_forbidden); @@ -646,9 +645,9 @@ void start() { origin_pin_allowed = net::from_enum_string(config::nvhttp.origin_pin_allowed); if(local_ip.empty()) { - std::cout << "Error: Could not determine the local ip-address"sv << std::endl; - - exit(8); + BOOST_LOG(fatal) << "Could not determine the local ip-address"sv; + log_flush(); + std::abort(); } load_devices(); @@ -677,7 +676,7 @@ void start() { auto x509 = ctx.native_handle(); X509_NAME_oneline(X509_get_subject_name(X509_STORE_CTX_get_current_cert(x509)), subject_name, sizeof(subject_name)); - std::cout << subject_name << " -- "sv << (verified ? "verfied"sv : "denied"sv) << std::endl; + BOOST_LOG(info) << subject_name << " -- "sv << (verified ? "verfied"sv : "denied"sv); }); if(verified) { @@ -690,17 +689,17 @@ void start() { auto cert = add_cert->pop(); X509_NAME_oneline(X509_get_subject_name(cert.get()), subject_name, sizeof(subject_name)); - std::cout << "Added cert ["sv << subject_name << "]"sv << std::endl; + BOOST_LOG(debug) << "Added cert ["sv << subject_name << ']'; cert_chain.add(std::move(cert)); } auto err_str = cert_chain.verify(X509_STORE_CTX_get_current_cert(ctx.native_handle())); if(err_str) { - std::cout << "SSL Verification error :: "sv << err_str << std::endl; + BOOST_LOG(warning) << "SSL Verification error :: "sv << err_str; return 0; } - verified = true; + verified = 1; return 1; }); diff --git a/sunshine/platform/linux.cpp b/sunshine/platform/linux.cpp index b971cf15..b6b4dcc1 100644 --- a/sunshine/platform/linux.cpp +++ b/sunshine/platform/linux.cpp @@ -21,7 +21,6 @@ #include #include -#include #include #include @@ -216,7 +215,7 @@ struct shm_attr_t : public x11_attr_t { xcb_img_t img_reply { xcb_shm_get_image_reply(xcb.get(), img_cookie, nullptr) }; if(!img_reply) { - std::cout << "Info: Could not get image reply"sv << std::endl; + BOOST_LOG(error) << "Could not get image reply"sv; return capture_e::reinit; } @@ -253,7 +252,7 @@ struct shm_attr_t : public x11_attr_t { } if(!xcb_get_extension_data(xcb.get(), &xcb_shm_id)->present) { - std::cout << "Missing SHM extension"sv << std::endl; + BOOST_LOG(error) << "Missing SHM extension"sv; return -1; } @@ -264,7 +263,7 @@ struct shm_attr_t : public x11_attr_t { shm_id.id = shmget(IPC_PRIVATE, frame_size(), IPC_CREAT | 0777); if(shm_id.id == -1) { - std::cout << "shmget failed"sv << std::endl; + BOOST_LOG(error) << "shmget failed"sv; return -1; } @@ -272,7 +271,7 @@ struct shm_attr_t : public x11_attr_t { data.data = shmat(shm_id.id, nullptr, 0); if ((uintptr_t)data.data == -1) { - std::cout << "shmat failed"sv << std::endl; + BOOST_LOG(error) << "shmat failed"sv; return -1; } @@ -295,9 +294,9 @@ struct mic_attr_t : public mic_t { sample_buf.resize(sample_size); auto buf = sample_buf.data(); - int error; - if(pa_simple_read(mic.get(), buf, sample_size * 2, &error)) { - std::cout << "pa_simple_read() failed: "sv << pa_strerror(error) << std::endl; + int status; + if(pa_simple_read(mic.get(), buf, sample_size * 2, &status)) { + BOOST_LOG(error) << "pa_simple_read() failed: "sv << pa_strerror(status); } return sample_buf; @@ -332,14 +331,14 @@ std::unique_ptr microphone() { } }; - int error; + int status; mic->mic.reset( - pa_simple_new(nullptr, "sunshine", pa_stream_direction_t::PA_STREAM_RECORD, nullptr, "sunshine_record", &mic->ss, nullptr, nullptr, &error) + pa_simple_new(nullptr, "sunshine", pa_stream_direction_t::PA_STREAM_RECORD, nullptr, "sunshine_record", &mic->ss, nullptr, nullptr, &status) ); if(!mic->mic) { - auto err_str = pa_strerror(error); - std::cout << "pa_simple_new() failed: "sv << err_str << std::endl; + auto err_str = pa_strerror(status); + BOOST_LOG(error) << "pa_simple_new() failed: "sv << err_str; exit(1); } diff --git a/sunshine/platform/linux_evdev.cpp b/sunshine/platform/linux_evdev.cpp index eb88d2ec..0668d813 100644 --- a/sunshine/platform/linux_evdev.cpp +++ b/sunshine/platform/linux_evdev.cpp @@ -8,9 +8,9 @@ #include #include -#include #include "common.h" +#include "sunshine/main.h" #include "sunshine/utility.h" namespace platf { @@ -331,7 +331,7 @@ int mouse(input_raw_t &gp) { gp.mouse_input.reset(buf); if(err) { - std::cout << "Could not create Sunshine Mouse: "sv << strerror(-err) << std::endl; + BOOST_LOG(error) << "Could not create Sunshine Mouse: "sv << strerror(-err); return -1; } @@ -400,7 +400,7 @@ int gamepad(input_raw_t &gp) { gp.gamepad_input.reset(buf); if(err) { - std::cout << "Could not create Sunshine Gamepad: "sv << strerror(-err) << std::endl; + BOOST_LOG(error) << "Could not create Sunshine Gamepad: "sv << strerror(-err); return -1; } diff --git a/sunshine/platform/windows.cpp b/sunshine/platform/windows.cpp index 4bcb3405..ba9cd283 100644 --- a/sunshine/platform/windows.cpp +++ b/sunshine/platform/windows.cpp @@ -1,4 +1,3 @@ -#include #include #include @@ -6,6 +5,7 @@ #include #include +#include "sunshine/main.h" #include "common.h" namespace platf { @@ -52,7 +52,7 @@ public: case DXGI_ERROR_ACCESS_DENIED: return capture_e::reinit; default: - std::cout << "Error: Couldn't release frame [0x"sv << util::hex(status).to_string_view() << std::endl; + BOOST_LOG(error) << "Couldn't release frame [0x"sv << util::hex(status).to_string_view(); return capture_e::error; } } @@ -69,7 +69,7 @@ public: case DXGI_ERROR_ACCESS_DENIED: return capture_e::reinit; default: - std::cout << "Error: Couldn't acquire next frame [0x"sv << util::hex(status).to_string_view() << std::endl; + BOOST_LOG(error) << "Couldn't acquire next frame [0x"sv << util::hex(status).to_string_view(); return capture_e::error; } } @@ -96,7 +96,7 @@ public: case DXGI_ERROR_ACCESS_DENIED: return capture_e::reinit; default: - std::cout << "Error: Couldn't release frame [0x"sv << util::hex(status).to_string_view() << std::endl; + BOOST_LOG(error) << "Couldn't release frame [0x"sv << util::hex(status).to_string_view(); return capture_e::error; } } @@ -153,13 +153,13 @@ public: UINT dummy; status = dup.dup->GetFramePointerShape(img_data.size(), img_data.data(), &dummy, &shape_info); if (FAILED(status)) { - std::cout << "Error: Failed to get new pointer shape [0x"sv << util::hex(status).to_string_view() << ']' << std::endl; + BOOST_LOG(error) << "Failed to get new pointer shape [0x"sv << util::hex(status).to_string_view() << ']'; return capture_e::error; } if (shape_info.Type != DXGI_OUTDUPL_POINTER_SHAPE_TYPE_COLOR) { - std::cout << "Warning: Unsupported cursor format ["sv << shape_info.Type << ']' << std::endl; + BOOST_LOG(warning) << "Unsupported cursor format ["sv << shape_info.Type << ']'; } cursor.width = shape_info.Width; @@ -177,7 +177,7 @@ public: texture2d_t src{src_p}; if (FAILED(status)) { - std::cout << "Error: Couldn't query interface [0x"sv << util::hex(status).to_string_view() << ']' << std::endl; + BOOST_LOG(error) << "Couldn't query interface [0x"sv << util::hex(status).to_string_view() << ']'; return capture_e::error; } @@ -195,7 +195,7 @@ public: return capture_e::timeout; } - std::cout << "Error: Failed to map texture [0x"sv << util::hex(status).to_string_view() << ']' << std::endl; + BOOST_LOG(error) << "Failed to map texture [0x"sv << util::hex(status).to_string_view() << ']'; return capture_e::error; } @@ -221,7 +221,7 @@ public: dxgi::output1_t output1 {output1_p }; if(FAILED(status)) { - std::cout << "Error: Failed to query IDXGIOutput1 from the output"sv << std::endl; + BOOST_LOG(error) << "Failed to query IDXGIOutput1 from the output"sv; return -1; } @@ -237,7 +237,7 @@ public: } if(FAILED(status)) { - std::cout << "Error: DuplicateOutput Failed [0x"sv << util::hex(status).to_string_view() << ']' << std::endl; + BOOST_LOG(error) << "DuplicateOutput Failed [0x"sv << util::hex(status).to_string_view() << ']'; return -1; } } @@ -247,7 +247,7 @@ public: format = dup_desc.ModeDesc.Format; - std::cout << "Source format ["sv << format_str[dup_desc.ModeDesc.Format] << ']' << std::endl; + BOOST_LOG(debug) << "Source format ["sv << format_str[dup_desc.ModeDesc.Format] << ']'; D3D11_TEXTURE2D_DESC t {}; t.Width = width; @@ -264,7 +264,7 @@ public: dxgi::texture2d_t tex { tex_p }; if(FAILED(status)) { - std::cout << "Error: Failed to create texture [0x"sv << util::hex(status).to_string_view() << ']' << std::endl; + BOOST_LOG(error) << "Failed to create texture [0x"sv << util::hex(status).to_string_view() << ']'; return -1; } @@ -273,7 +273,7 @@ public: status = device_ctx->Map((ID3D11Resource *)tex.get(), 0, D3D11_MAP_READ, 0, &mapping); if(FAILED(status)) { - std::cout << "Error: Failed to map the texture [0x"sv << util::hex(status).to_string_view() << ']' << std::endl; + BOOST_LOG(error) << "Error: Failed to map the texture [0x"sv << util::hex(status).to_string_view() << ']'; return -1; } @@ -303,7 +303,7 @@ public: dxgi::texture2d_t tex { tex_p }; if(FAILED(status)) { - std::cout << "Error: Failed to create texture [0x"sv << util::hex(status).to_string_view() << ']' << std::endl; + BOOST_LOG(error) << "Failed to create texture [0x"sv << util::hex(status).to_string_view() << ']'; return nullptr; } @@ -340,7 +340,7 @@ public: status = CreateDXGIFactory1(IID_IDXGIFactory1, (void**)&factory_p); factory.reset(factory_p); if(FAILED(status)) { - std::cout << "Error: Failed to create DXGIFactory1 [0x"sv << util::hex(status).to_string_view() << ']' << std::endl; + BOOST_LOG(error) << "Failed to create DXGIFactory1 [0x"sv << util::hex(status).to_string_view() << ']'; return -1; } @@ -369,7 +369,7 @@ public: } if(!output) { - std::cout << "Error: Failed to locate an output device"sv << std::endl; + BOOST_LOG(error) << "Failed to locate an output device"sv; return -1; } @@ -387,7 +387,7 @@ public: status = adapter->QueryInterface(IID_IDXGIAdapter, (void**)&adapter_p); if(FAILED(status)) { - std::cout << "Error: Failed to query IDXGIAdapter interface"sv <GetDesc(&adapter_desc); - std::cout + BOOST_LOG(info) << "Device Description : "sv << adapter_desc.Description << std::endl << "Device Vendor ID : 0x"sv << util::hex(adapter_desc.VendorId).to_string_view() << std::endl << "Device Device ID : 0x"sv << util::hex(adapter_desc.DeviceId).to_string_view() << std::endl @@ -423,7 +423,7 @@ public: << "Device Sys Mem : "sv << adapter_desc.DedicatedSystemMemory / 1048576 << " MiB"sv << std::endl << "Share Sys Mem : "sv << adapter_desc.SharedSystemMemory / 1048576 << " MiB"sv << std::endl << "Feature Level : 0x"sv << util::hex(feature_level).to_string_view() << std::endl - << "Capture size : "sv << width << 'x' << height << std::endl; + << "Capture size : "sv << width << 'x' << height; // Bump up thread priority { @@ -432,7 +432,7 @@ public: dxgi::dxgi_t dxgi { dxgi_p }; if(FAILED(status)) { - std::cout << "Error: Failed to query DXGI interface from device [0x"sv << util::hex(status).to_string_view() << ']' << std::endl; + BOOST_LOG(error) << "Failed to query DXGI interface from device [0x"sv << util::hex(status).to_string_view() << ']'; return -1; } @@ -446,7 +446,7 @@ public: dxgi::dxgi1_t dxgi { dxgi_p }; if(FAILED(status)) { - std::cout << "Error: Failed to query DXGI interface from device [0x"sv << util::hex(status).to_string_view() << ']' << std::endl; + BOOST_LOG(error) << "Failed to query DXGI interface from device [0x"sv << util::hex(status).to_string_view() << ']'; return -1; } @@ -456,17 +456,6 @@ public: return reinit(); } - int deinit() { - dup.reset(); - device_ctx.reset(); - device.reset(); - output.reset(); - adapter.reset(); - factory.reset(); - - return 0; - } - factory1_t factory; adapter_t adapter; output_t output; diff --git a/sunshine/process.cpp b/sunshine/process.cpp index bd7633ac..2ae6f045 100644 --- a/sunshine/process.cpp +++ b/sunshine/process.cpp @@ -6,14 +6,12 @@ #include #include -#include #include #include -#include "config.h" #include "utility.h" -#include "platform/common.h" +#include "main.h" namespace proc { using namespace std::literals; @@ -27,7 +25,7 @@ void process_end(bp::child &proc, bp::group &proc_handle) { return; } - std::cout << "Force termination Child-Process"sv << std::endl; + BOOST_LOG(debug) << "Force termination Child-Process"sv; proc_handle.terminate(); // avoid zombie process @@ -51,7 +49,7 @@ int proc_t::execute(int app_id) { } if(app_id >= _apps.size()) { - std::cout << "Error: Couldn't find app with ID ["sv << app_id << ']' << std::endl; + BOOST_LOG(error) << "Couldn't find app with ID ["sv << app_id << ']'; return 404; } @@ -78,21 +76,21 @@ int proc_t::execute(int app_id) { for(; _undo_it != std::end(proc.prep_cmds); ++_undo_it) { auto &cmd = _undo_it->do_cmd; - std::cout << "Executing: ["sv << cmd << ']' << std::endl; + BOOST_LOG(info) << "Executing: ["sv << cmd << ']'; auto ret = exe(cmd, _env, _pipe, ec); if(ec) { - std::cout << "Error: System: "sv << ec.message() << std::endl; + BOOST_LOG(error) << "System: "sv << ec.message(); return -1; } if(ret != 0) { - std::cout << "Error: return code ["sv << ret << ']'; + BOOST_LOG(error) << "Return code ["sv << ret << ']'; return -1; } } - std::cout << "Starting ["sv << proc.cmd << ']' << std::endl; + BOOST_LOG(debug) << "Starting ["sv << proc.cmd << ']'; if(proc.output.empty() || proc.output == "null"sv) { _process = bp::child(_process_handle, proc.cmd, _env, bp::std_out > bp::null, bp::std_err > bp::null, ec); } @@ -101,7 +99,7 @@ int proc_t::execute(int app_id) { } if(ec) { - std::cout << "Error: System: "sv << ec.message() << std::endl; + BOOST_LOG(info) << "System: "sv << ec.message(); return -1; } @@ -126,7 +124,8 @@ void proc_t::terminate() { _app_id = -1; if(ec) { - std::cout << "FATAL Error: System: "sv << ec.message() << std::endl; + BOOST_LOG(fatal) << "System: "sv << ec.message(); + log_flush(); std::abort(); } @@ -137,17 +136,19 @@ void proc_t::terminate() { continue; } - std::cout << "Executing: ["sv << cmd << ']' << std::endl; + BOOST_LOG(debug) << "Executing: ["sv << cmd << ']'; auto ret = exe(cmd, _env, _pipe, ec); if(ec) { - std::cout << "FATAL Error: System: "sv << ec.message() << std::endl; + BOOST_LOG(fatal) << "System: "sv << ec.message(); + log_flush(); std::abort(); } if(ret != 0) { - std::cout << "FATAL Error: return code ["sv << ret << ']'; + BOOST_LOG(fatal) << "Return code ["sv << ret << ']'; + log_flush(); std::abort(); } } @@ -283,7 +284,7 @@ std::optional parse(const std::string& file_name) { std::move(this_env), std::move(apps) }; } catch (std::exception &e) { - std::cout << e.what() << std::endl; + BOOST_LOG(error) << e.what(); } return std::nullopt; diff --git a/sunshine/stream.cpp b/sunshine/stream.cpp index b9fa4224..ebd5f2df 100644 --- a/sunshine/stream.cpp +++ b/sunshine/stream.cpp @@ -13,7 +13,6 @@ #include -#include #include #include #include @@ -35,6 +34,7 @@ extern "C" { #include "thread_safe.h" #include "crypto.h" #include "input.h" +#include "main.h" #define IDX_START_A 0 #define IDX_REQUEST_IDR_FRAME 0 @@ -229,10 +229,10 @@ public: } break; case ENET_EVENT_TYPE_CONNECT: - std::cout << "CLIENT CONNECTED TO RTSP" << std::endl; + BOOST_LOG(info) << "CLIENT CONNECTED TO RTSP"sv; break; case ENET_EVENT_TYPE_DISCONNECT: - std::cout << "CLIENT DISCONNECTED FROM RTSP" << std::endl; + BOOST_LOG(info) << "CLIENT DISCONNECTED FROM RTSP"sv; break; case ENET_EVENT_TYPE_NONE: break; @@ -277,8 +277,9 @@ public: auto cb = _map_type_cb.find(*type); if(cb == std::end(_map_type_cb)) { - std::cout << "type [Unknown] { " << util::hex(*type).to_string_view() << " }" << std::endl; - std::cout << "---data---" << std::endl << util::hex_vec(payload) << std::endl << "---end data---" << std::endl; + BOOST_LOG(warning) + << "type [Unknown] { "sv << util::hex(*type).to_string_view() << " }"sv << std::endl + << "---data---"sv << std::endl << util::hex_vec(payload) << std::endl << "---end data---"sv; } else { @@ -287,10 +288,10 @@ public: } break; case ENET_EVENT_TYPE_CONNECT: - std::cout << "CLIENT CONNECTED" << std::endl; + BOOST_LOG(info) << "CLIENT CONNECTED"sv; break; case ENET_EVENT_TYPE_DISCONNECT: - std::cout << "CLIENT DISCONNECTED" << std::endl; + BOOST_LOG(info) << "CLIENT DISCONNECTED"sv; break; case ENET_EVENT_TYPE_NONE: break; @@ -335,8 +336,9 @@ fec_t encode(const std::string_view &payload, size_t blocksize, size_t fecpercen auto nr_shards = data_shards + parity_shards; if(nr_shards > DATA_SHARDS_MAX) { - std::cout << "Error: number of fragments for reed solomon exceeds DATA_SHARDS_MAX"sv << std::endl; - std::cout << nr_shards << " > "sv << DATA_SHARDS_MAX << std::endl; + BOOST_LOG(error) + << "Number of fragments for reed solomon exceeds DATA_SHARDS_MAX"sv << std::endl + << nr_shards << " > "sv << DATA_SHARDS_MAX; return { 0 }; } @@ -403,10 +405,10 @@ void print_msg(PRTSP_MESSAGE msg) { auto seqnm = msg->sequenceNumber; std::string_view messageBuffer { msg->messageBuffer }; - std::cout << "type ["sv << type << ']' << std::endl; - std::cout << "sequence number ["sv << seqnm << ']' << std::endl; - std::cout << "protocol :: "sv << protocol << std::endl; - std::cout << "payload :: "sv << payload << std::endl; + BOOST_LOG(debug) << "type ["sv << type << ']'; + BOOST_LOG(debug) << "sequence number ["sv << seqnm << ']'; + BOOST_LOG(debug) << "protocol :: "sv << protocol; + BOOST_LOG(debug) << "payload :: "sv << payload; if(msg->type == TYPE_RESPONSE) { auto &resp = msg->message.response; @@ -414,8 +416,8 @@ void print_msg(PRTSP_MESSAGE msg) { auto statuscode = resp.statusCode; std::string_view status { resp.statusString }; - std::cout << "statuscode :: "sv << statuscode << std::endl; - std::cout << "status :: "sv << status << std::endl; + BOOST_LOG(debug) << "statuscode :: "sv << statuscode; + BOOST_LOG(debug) << "status :: "sv << status; } else { auto& req = msg->message.request; @@ -423,18 +425,18 @@ void print_msg(PRTSP_MESSAGE msg) { std::string_view command { req.command }; std::string_view target { req.target }; - std::cout << "command :: "sv << command << std::endl; - std::cout << "target :: "sv << target << std::endl; + BOOST_LOG(debug) << "command :: "sv << command; + BOOST_LOG(debug) << "target :: "sv << target; } for(auto option = msg->options; option != nullptr; option = option->next) { std::string_view content { option->content }; std::string_view name { option->option }; - std::cout << name << " :: "sv << content << std::endl; + BOOST_LOG(debug) << name << " :: "sv << content; } - std::cout << "---Begin MessageBuffer---"sv << std::endl << messageBuffer << std::endl << "---End MessageBuffer---"sv << std::endl << std::endl; + BOOST_LOG(debug) << "---Begin MessageBuffer---"sv << std::endl << messageBuffer << std::endl << "---End MessageBuffer---"sv << std::endl; } std::vector replace(const std::string_view &original, const std::string_view &old, const std::string_view &_new) { @@ -475,44 +477,44 @@ void controlThread(video::idr_event_t idr_events) { server.map(packetTypes[IDX_START_A], [](const std::string_view &payload) { session.pingTimeout = std::chrono::steady_clock::now() + config::stream.ping_timeout; - std::cout << "type [IDX_START_A]"sv << std::endl; + BOOST_LOG(debug) << "type [IDX_START_A]"sv; }); server.map(packetTypes[IDX_START_B], [](const std::string_view &payload) { session.pingTimeout = std::chrono::steady_clock::now() + config::stream.ping_timeout; - std::cout << "type [IDX_START_B]"sv << std::endl; + BOOST_LOG(debug) << "type [IDX_START_B]"sv; }); server.map(packetTypes[IDX_LOSS_STATS], [](const std::string_view &payload) { session.pingTimeout = std::chrono::steady_clock::now() + config::stream.ping_timeout; - std::cout << "type [IDX_LOSS_STATS]"sv << std::endl; - int32_t *stats = (int32_t*)payload.data(); auto count = stats[0]; std::chrono::milliseconds t { stats[1] }; auto lastGoodFrame = stats[3]; - std::cout << "---begin stats---" << std::endl; - std::cout << "loss count since last report [" << count << ']' << std::endl; - std::cout << "time in milli since last report [" << t.count() << ']' << std::endl; - std::cout << "last good frame [" << lastGoodFrame << ']' << std::endl; - std::cout << "---end stats---" << std::endl; + BOOST_LOG(debug) + << "type [IDX_LOSS_STATS]"sv << std::endl + << "---begin stats---" << std::endl + << "loss count since last report [" << count << ']' << std::endl + << "time in milli since last report [" << t.count() << ']' << std::endl + << "last good frame [" << lastGoodFrame << ']' << std::endl + << "---end stats---"; }); server.map(packetTypes[IDX_INVALIDATE_REF_FRAMES], [idr_events](const std::string_view &payload) { session.pingTimeout = std::chrono::steady_clock::now() + config::stream.ping_timeout; - std::cout << "type [IDX_INVALIDATE_REF_FRAMES]"sv << std::endl; - - std::int64_t *frames = (std::int64_t *)payload.data(); + std::int64_t *frames = (std::int64_t *) payload.data(); auto firstFrame = frames[0]; - auto lastFrame = frames[1]; + auto lastFrame = frames[1]; - std::cout << "firstFrame [" << firstFrame << ']' << std::endl; - std::cout << "lastFrame [" << lastFrame << ']' << std::endl; + BOOST_LOG(debug) + << "type [IDX_INVALIDATE_REF_FRAMES]"sv << std::endl + << "firstFrame [" << firstFrame << ']' << std::endl + << "lastFrame [" << lastFrame << ']'; idr_events->raise(std::make_pair(firstFrame, lastFrame)); }); @@ -520,7 +522,7 @@ void controlThread(video::idr_event_t idr_events) { server.map(packetTypes[IDX_INPUT_DATA], [](const std::string_view &payload) mutable { session.pingTimeout = std::chrono::steady_clock::now() + config::stream.ping_timeout; - std::cout << "type [IDX_INPUT_DATA]"sv << std::endl; + BOOST_LOG(debug) << "type [IDX_INPUT_DATA]"sv; int32_t tagged_cipher_length = util::endian::big(*(int32_t*)payload.data()); std::string_view tagged_cipher { payload.data() + sizeof(tagged_cipher_length), (size_t)tagged_cipher_length }; @@ -532,7 +534,7 @@ void controlThread(video::idr_event_t idr_events) { if(cipher.decrypt_gcm(session.iv, tagged_cipher, plaintext)) { // something went wrong :( - std::cout << "failed to verify tag"sv << std::endl; + BOOST_LOG(error) << "Failed to verify tag"sv; stop(session); } @@ -547,13 +549,13 @@ void controlThread(video::idr_event_t idr_events) { while(has_session) { if(std::chrono::steady_clock::now() > session.pingTimeout) { - std::cout << "ping timeout"sv << std::endl; + BOOST_LOG(debug) << "Ping timeout"sv; stop(session); } if(session.has_process && proc::proc.running() == -1) { - std::cout << "Process terminated"sv << std::endl; + BOOST_LOG(debug) << "Process terminated"sv; std::uint16_t reason = 0x0100; @@ -625,12 +627,12 @@ std::optional recv_peer(std::shared_ptr> &queue, auto len = len_or_err.left(); if (len == 4 && !std::memcmp(ping, buf.data(), sizeof(ping))) { - std::cout << "PING from ["sv << peer.address().to_string() << ':' << peer.port() << ']' << std::endl; + BOOST_LOG(debug) << "PING from ["sv << peer.address().to_string() << ':' << peer.port() << ']'; return std::make_optional(std::move(peer)); } - std::cout << "Unknown transmission: "sv << util::hex_vec(std::string_view{buf.data(), len}) << std::endl; + BOOST_LOG(warning) << "Unknown transmission: "sv << util::hex_vec(std::string_view{buf.data(), len}); } return std::nullopt; @@ -660,9 +662,10 @@ void audioThread() { std::copy(std::begin(*packet), std::end(*packet), audio_packet->payload()); sock.send_to(asio::buffer((char*)audio_packet.get(), sizeof(audio_packet_raw_t) + packet->size()), *peer); - // std::cout << "Audio ["sv << frame << "] :: send..."sv << std::endl; + BOOST_LOG(verbose) << "Audio ["sv << frame - 1 << "] :: send..."sv; } + stop(session); captureThread.join(); } @@ -739,7 +742,7 @@ void videoThread(video::idr_event_t idr_events) { auto shards = fec::encode(payload, blocksize, fecPercentage); if(shards.data_shards == 0) { - std::cout << "skipping frame..."sv << std::endl; + BOOST_LOG(info) << "skipping frame..."sv << std::endl; continue; } @@ -761,14 +764,16 @@ void videoThread(video::idr_event_t idr_events) { } if(packet->flags & AV_PKT_FLAG_KEY) { - std::cout << "Key "sv; + BOOST_LOG(verbose) << "Key Frame ["sv << packet->pts << "] :: send ["sv << shards.size() << "] shards..."sv; + } + else { + BOOST_LOG(verbose) << "Frame ["sv << packet->pts << "] :: send ["sv << shards.size() << "] shards..."sv << std::endl; } - std::cout << "Frame ["sv << packet->pts << "] :: send ["sv << shards.size() << "] shards..."sv << std::endl; lowseq += shards.size(); - } + stop(session); captureThread.join(); } @@ -785,11 +790,11 @@ void respond(host_t &host, peer_t peer, msg_t &resp) { int serialized_len; util::c_ptr raw_resp { serializeRtspMessage(resp.get(), &serialized_len) }; - std::cout << "---Begin Response---"sv << std::endl - << std::string_view { raw_resp.get(), (std::size_t)serialized_len } << std::endl - << std::string_view { payload.first, (std::size_t)payload.second } << std::endl - << "---End Response---"sv << std::endl - << std::endl; + BOOST_LOG(debug) + << "---Begin Response---"sv << std::endl + << std::string_view { raw_resp.get(), (std::size_t)serialized_len } << std::endl + << std::string_view { payload.first, (std::size_t)payload.second } << std::endl + << "---End Response---"sv << std::endl; std::string_view tmp_resp { raw_resp.get(), (size_t)serialized_len }; @@ -1022,14 +1027,14 @@ void rtpThread() { // Ensure all threads are stopping stop(session); - std::cout << "Waiting for Audio to end..."sv << std::endl; + BOOST_LOG(debug) << "Waiting for Audio to end..."sv; session.audioThread.join(); - std::cout << "Waiting for Video to end..."sv << std::endl; + BOOST_LOG(debug) << "Waiting for Video to end..."sv; session.videoThread.join(); - std::cout << "Waiting for Control to end..."sv << std::endl; + BOOST_LOG(debug) << "Waiting for Control to end..."sv; session.controlThread.join(); - std::cout << "Resetting Session..."sv << std::endl; + BOOST_LOG(debug) << "Resetting Session..."sv << std::endl; session.video_packets = video::packet_queue_t(); session.audio_packets = audio::packet_queue_t(); } diff --git a/sunshine/video.cpp b/sunshine/video.cpp index bc1eb2e0..414bcccd 100644 --- a/sunshine/video.cpp +++ b/sunshine/video.cpp @@ -2,8 +2,6 @@ // Created by loki on 6/6/19. // -#include -#include #include extern "C" { @@ -225,7 +223,7 @@ void capture_display(packet_queue_t packets, idr_event_t idr_events, config_t co auto t = std::chrono::steady_clock::now(); if(t > next_snapshot) { - std::cout << "Taking snapshot took "sv << std::chrono::floor(t - next_snapshot).count() << " milliseconds too long"sv << std::endl; + BOOST_LOG(warning) << "Taking snapshot took "sv << std::chrono::floor(t - next_snapshot).count() << " milliseconds too long"sv; } std::this_thread::sleep_until(next_snapshot);