diff --git a/assets/sunshine.conf b/assets/sunshine.conf index 46e4516b..7a318ed4 100644 --- a/assets/sunshine.conf +++ b/assets/sunshine.conf @@ -95,7 +95,7 @@ # !! Linux only !! # Set the display number to stream. I have no idea how they are numbered. They start from 1, usually. -# linux_monitor_id = 2 +# output_name = 1 ############################################### # FFmpeg software encoding parameters diff --git a/pre-compiled b/pre-compiled index afd9a9bb..bbf56474 160000 --- a/pre-compiled +++ b/pre-compiled @@ -1 +1 @@ -Subproject commit afd9a9bbfc6ee1a064b0c1f9210bc20b2170c416 +Subproject commit bbf5647402859945dee541a300b22702a2ee9271 diff --git a/sunshine/config.cpp b/sunshine/config.cpp index cccce8be..26878011 100644 --- a/sunshine/config.cpp +++ b/sunshine/config.cpp @@ -106,7 +106,6 @@ video_t video { {}, // encoder {}, // adapter_name {}, // output_name - -1 }; audio_t audio {}; @@ -372,8 +371,6 @@ void apply_config(std::unordered_map &&vars) { string_f(vars, "audio_sink", audio.sink); - int_between_f(vars, "linux_monitor_id", video.linux_monitor_id, { 0, 32 }); - string_restricted_f(vars, "origin_pin_allowed", nvhttp.origin_pin_allowed, { "pc"sv, "lan"sv, "wan"sv }); diff --git a/sunshine/config.h b/sunshine/config.h index 0102fd84..9c14b1fe 100644 --- a/sunshine/config.h +++ b/sunshine/config.h @@ -29,8 +29,6 @@ struct video_t { std::string encoder; std::string adapter_name; std::string output_name; - - int linux_monitor_id; //Only used on linux }; struct audio_t { diff --git a/sunshine/platform/linux/display.cpp b/sunshine/platform/linux/display.cpp index 5729afbf..cde96cf7 100644 --- a/sunshine/platform/linux/display.cpp +++ b/sunshine/platform/linux/display.cpp @@ -43,561 +43,494 @@ using xdisplay_t = util::safe_ptr_v2; using ximg_t = util::safe_ptr; using xcursor_t = util::safe_ptr; -class shm_id_t -{ +class shm_id_t { public: - shm_id_t() : id { -1 } - { - } - shm_id_t(int id) : id { id } - { - } - shm_id_t(shm_id_t &&other) noexcept : id(other.id) - { - other.id = -1; - } + shm_id_t() : id { -1 } {} + shm_id_t(int id) : id { id } {} + shm_id_t(shm_id_t &&other) noexcept : id(other.id) { + other.id = -1; + } - ~shm_id_t() - { - if (id != -1) - { - shmctl(id, IPC_RMID, nullptr); - id = -1; - } - } - int id; + ~shm_id_t() { + if (id != -1) { + shmctl(id, IPC_RMID, nullptr); + id = -1; + } + } + int id; }; -class shm_data_t -{ +class shm_data_t { public: - shm_data_t() : data { (void*) -1 } - { - } - shm_data_t(void *data) : data { data } - { - } + shm_data_t() : data { (void*) -1 } + { + } + shm_data_t(void *data) : data { data } + { + } - shm_data_t(shm_data_t &&other) noexcept : data(other.data) - { - other.data = (void*) -1; - } + shm_data_t(shm_data_t &&other) noexcept : data(other.data) + { + other.data = (void*) -1; + } - ~shm_data_t() - { - if ((std::uintptr_t) data != -1) - { - shmdt(data); - data = (void*) -1; - } - } + ~shm_data_t() + { + if ((std::uintptr_t) data != -1) + { + shmdt(data); + data = (void*) -1; + } + } - void *data; + void *data; }; -struct x11_img_t: public img_t -{ - ximg_t img; +struct x11_img_t: public img_t { + ximg_t img; }; -struct shm_img_t: public img_t -{ - ~shm_img_t() override - { - delete[] data; - data = nullptr; - } +struct shm_img_t: public img_t { + ~shm_img_t() override + { + delete[] data; + data = nullptr; + } }; -void blend_cursor(Display *display, img_t &img, int offsetX,int offsetY) -{ - xcursor_t overlay { XFixesGetCursorImage(display) }; +void blend_cursor(Display *display, img_t &img, int offsetX, int offsetY) { + xcursor_t overlay { XFixesGetCursorImage(display) }; - if (!overlay) - { - BOOST_LOG(error) - << "Couldn't get cursor from XFixesGetCursorImage"sv; - return; - } + if (!overlay) { + BOOST_LOG(error) + << "Couldn't get cursor from XFixesGetCursorImage"sv; + return; + } - overlay->x -= overlay->xhot; - overlay->y -= overlay->yhot; + overlay->x -= overlay->xhot; + overlay->y -= overlay->yhot; - overlay->x -= offsetX; - overlay->y -= offsetY; + overlay->x -= offsetX; + overlay->y -= offsetY; - overlay->x = std::max((short) 0, overlay->x); - overlay->y = std::max((short) 0, overlay->y); + overlay->x = std::max((short) 0, overlay->x); + overlay->y = std::max((short) 0, overlay->y); - auto pixels = (int*) img.data; + auto pixels = (int*) img.data; - auto screen_height = img.height; - auto screen_width = img.width; + auto screen_height = img.height; + auto screen_width = img.width; - auto delta_height = std::min(overlay->height,std::max(0, screen_height - overlay->y)); - auto delta_width = std::min(overlay->width,std::max(0, screen_width - overlay->x)); - for (auto y = 0; y < delta_height; ++y) - { - auto overlay_begin = &overlay->pixels[y * overlay->width]; - auto overlay_end = &overlay->pixels[y * overlay->width + delta_width]; + auto delta_height = std::min(overlay->height,std::max(0, screen_height - overlay->y)); + auto delta_width = std::min(overlay->width,std::max(0, screen_width - overlay->x)); + for (auto y = 0; y < delta_height; ++y) { + auto overlay_begin = &overlay->pixels[y * overlay->width]; + auto overlay_end = &overlay->pixels[y * overlay->width + delta_width]; - auto pixels_begin = &pixels[(y + overlay->y)* (img.row_pitch / img.pixel_pitch) + overlay->x]; + auto pixels_begin = &pixels[(y + overlay->y)* (img.row_pitch / img.pixel_pitch) + overlay->x]; - std::for_each(overlay_begin, overlay_end,[&](long pixel) - { - int *pixel_p = (int*) &pixel; + std::for_each(overlay_begin, overlay_end,[&](long pixel) { + int *pixel_p = (int*) &pixel; - auto colors_in = (uint8_t*) pixels_begin; + auto colors_in = (uint8_t*) pixels_begin; - auto alpha = (*(uint*) pixel_p) >> 24u; - if (alpha == 255) - { - *pixels_begin = *pixel_p; - } - else - { - auto colors_out = (uint8_t*) pixel_p; - colors_in[0] = colors_out[0] + (colors_in[0] * (255 - alpha) +255 /2) / 255; - colors_in[1] = colors_out[1] + (colors_in[1] * (255 - alpha) + 255 / 2) / 255; - colors_in[2] = colors_out[2] + (colors_in[2] * (255 - alpha) + 255 / 2) / 255; - } - ++pixels_begin; - }); - } + auto alpha = (*(uint*) pixel_p) >> 24u; + if (alpha == 255) { + *pixels_begin = *pixel_p; + } + else { + auto colors_out = (uint8_t*) pixel_p; + colors_in[0] = colors_out[0] + (colors_in[0] * (255 - alpha) +255 /2) / 255; + colors_in[1] = colors_out[1] + (colors_in[1] * (255 - alpha) + 255 / 2) / 255; + colors_in[2] = colors_out[2] + (colors_in[2] * (255 - alpha) + 255 / 2) / 255; + } + ++pixels_begin; + }); + } } struct x11_attr_t: public display_t { - xdisplay_t xdisplay; - Window xwindow; - XWindowAttributes xattr; + xdisplay_t xdisplay; + Window xwindow; + XWindowAttributes xattr; - Display* displayDisplay; + Display* displayDisplay; - /* - * Remember last X (NOT the streamed monitor!) size. This way we can trigger reinitialization if the dimensions changed while streaming - */ - int lastWidth,lastHeight; + /* + * Remember last X (NOT the streamed monitor!) size. This way we can trigger reinitialization if the dimensions changed while streaming + */ + int lastWidth,lastHeight; - /* - * Offsets for when streaming a specific monitor. By default, they are 0. - */ - int displayOffsetX,displayOffsetY; + /* + * Offsets for when streaming a specific monitor. By default, they are 0. + */ + int displayOffsetX,displayOffsetY; - x11_attr_t() : xdisplay { displayDisplay = XOpenDisplay(nullptr) }, xwindow { }, xattr { } - { - XInitThreads(); - if (!xdisplay) - { - BOOST_LOG(fatal) - << "Could not open x11 display"sv; - log_flush(); - std::abort(); - } + x11_attr_t() : xdisplay { displayDisplay = XOpenDisplay(nullptr) }, xwindow { }, xattr { } + { + XInitThreads(); + if (!xdisplay) { + BOOST_LOG(fatal) << "Could not open x11 display"sv; + log_flush(); + std::abort(); + } - xwindow = DefaultRootWindow(xdisplay.get()); + xwindow = DefaultRootWindow(xdisplay.get()); - refresh(); + refresh(); - int streamedMonitor = config::video.linux_monitor_id; + int streamedMonitor = -1; + if(!config::video.output_name.empty()) { + streamedMonitor = (int)util::from_view(config::video.output_name); + } - if (streamedMonitor != -1) //If the value has been set at all - { + //If the value has been set at all + if (streamedMonitor != -1) { - BOOST_LOG(info) << "Configuring selected monitor ("<< streamedMonitor<<") to stream. If it fails here, you may need Xrandr >= 1.5"sv; - XRRScreenResources *screenr = XRRGetScreenResources(displayDisplay, xwindow); - // This is the key right here. Use XRRScreenResources::noutput - int output = screenr->noutput; + BOOST_LOG(info) << "Configuring selected monitor ("<< streamedMonitor<<") to stream. If it fails here, you may need Xrandr >= 1.5"sv; + XRRScreenResources *screenr = XRRGetScreenResources(displayDisplay, xwindow); + // This is the key right here. Use XRRScreenResources::noutput + int output = screenr->noutput; - if (streamedMonitor >= output) - { - BOOST_LOG(error)<< "Could not stream selected display number because there aren't so many."sv; - } - else - { - XRROutputInfo* out_info = XRRGetOutputInfo(displayDisplay, screenr, screenr->outputs[streamedMonitor]); - if (NULL == out_info || out_info->connection != RR_Connected) - { - BOOST_LOG(error)<< "Could not stream selected display because it doesn't seem to be connected"sv; - } - else - { - XRRCrtcInfo* crt_info = XRRGetCrtcInfo(displayDisplay, screenr, out_info->crtc); - BOOST_LOG(info)<<"Streaming display: "<name<<" with res "<width<<" x "<height<<+" offset by "<x<<" x "<y<<"."sv; + if (streamedMonitor >= output) { + BOOST_LOG(error)<< "Could not stream selected display number because there aren't so many."sv; + } + else { + XRROutputInfo* out_info = XRRGetOutputInfo(displayDisplay, screenr, screenr->outputs[streamedMonitor]); + if (NULL == out_info || out_info->connection != RR_Connected) + { + BOOST_LOG(error)<< "Could not stream selected display because it doesn't seem to be connected"sv; + } + else + { + XRRCrtcInfo* crt_info = XRRGetCrtcInfo(displayDisplay, screenr, out_info->crtc); + BOOST_LOG(info)<<"Streaming display: "<name<<" with res "<width<<" x "<height<<+" offset by "<x<<" x "<y<<"."sv; - width = crt_info -> width; - height = crt_info -> height; - displayOffsetX = crt_info -> x; - displayOffsetY = crt_info -> y; + width = crt_info -> width; + height = crt_info -> height; + displayOffsetX = crt_info -> x; + displayOffsetY = crt_info -> y; - XRRFreeCrtcInfo(crt_info); - } - XRRFreeOutputInfo(out_info); - } - XRRFreeScreenResources(screenr); - } - else - { - width = xattr.width; - height = xattr.height; - } + XRRFreeCrtcInfo(crt_info); + } + XRRFreeOutputInfo(out_info); + } + XRRFreeScreenResources(screenr); + } + else { + width = xattr.width; + height = xattr.height; + } - lastWidth = xattr.width; - lastHeight = xattr.height; - } + lastWidth = xattr.width; + lastHeight = xattr.height; + } - /** - * Called when the display attributes should change. - */ - void refresh() - { - XGetWindowAttributes(xdisplay.get(), xwindow, &xattr); //Update xattr's - } + /** + * Called when the display attributes should change. + */ + void refresh() + { + XGetWindowAttributes(xdisplay.get(), xwindow, &xattr); //Update xattr's + } - capture_e snapshot(img_t *img_out_base, std::chrono::milliseconds timeout, bool cursor) override - { - refresh(); - capture_e toReturn; - if (xattr.width != lastWidth || xattr.height != lastHeight) //The whole X server changed, so we gotta reinit everything - { - BOOST_LOG(warning)<< "X dimensions changed in non-SHM mode, request reinit"sv; - toReturn = capture_e::reinit; - } - else - { - XImage *img { XGetImage(xdisplay.get(), xwindow, displayOffsetX, displayOffsetY, width,height, AllPlanes, ZPixmap) }; + capture_e snapshot(img_t *img_out_base, std::chrono::milliseconds timeout, bool cursor) override { + refresh(); - auto img_out = (x11_img_t*) img_out_base; - img_out->width = img->width; - img_out->height = img->height; - img_out->data = (uint8_t*) img->data; - img_out->row_pitch = img->bytes_per_line; - img_out->pixel_pitch = img->bits_per_pixel / 8; - img_out->img.reset(img); + //The whole X server changed, so we gotta reinit everything + if (xattr.width != lastWidth || xattr.height != lastHeight) { + BOOST_LOG(warning)<< "X dimensions changed in non-SHM mode, request reinit"sv; + return capture_e::reinit; + } + XImage *img { XGetImage(xdisplay.get(), xwindow, displayOffsetX, displayOffsetY, width,height, AllPlanes, ZPixmap) }; - if (cursor) - { - blend_cursor(xdisplay.get(), *img_out_base,displayOffsetX,displayOffsetY); - } - toReturn = capture_e::ok; - } - return toReturn; - } + auto img_out = (x11_img_t*) img_out_base; + img_out->width = img->width; + img_out->height = img->height; + img_out->data = (uint8_t*) img->data; + img_out->row_pitch = img->bytes_per_line; + img_out->pixel_pitch = img->bits_per_pixel / 8; + img_out->img.reset(img); - std::shared_ptr alloc_img() override - { - return std::make_shared(); - } + if (cursor) { + blend_cursor(xdisplay.get(), *img_out_base,displayOffsetX,displayOffsetY); + } - int dummy_img(img_t *img) override - { - snapshot(img, 0s, true); - return 0; - } + return capture_e::ok; + } + + std::shared_ptr alloc_img() override { + return std::make_shared(); + } + + int dummy_img(img_t *img) override { + snapshot(img, 0s, true); + return 0; + } }; -struct shm_attr_t: public x11_attr_t -{ - xdisplay_t shm_xdisplay; // Prevent race condition with x11_attr_t::xdisplay - xcb_connect_t xcb; - xcb_screen_t *display; - std::uint32_t seg; +struct shm_attr_t: public x11_attr_t { + xdisplay_t shm_xdisplay; // Prevent race condition with x11_attr_t::xdisplay + xcb_connect_t xcb; + xcb_screen_t *display; + std::uint32_t seg; - shm_id_t shm_id; + shm_id_t shm_id; - shm_data_t data; + shm_data_t data; - util::TaskPool::task_id_t refresh_task_id; - void delayed_refresh() - { - refresh(); + util::TaskPool::task_id_t refresh_task_id; - refresh_task_id = task_pool.pushDelayed(&shm_attr_t::delayed_refresh,2s, this).task_id; - } + void delayed_refresh() { + refresh(); - shm_attr_t() : x11_attr_t(), shm_xdisplay { XOpenDisplay(nullptr) } - { - refresh_task_id = task_pool.pushDelayed(&shm_attr_t::delayed_refresh,2s, this).task_id; - } + refresh_task_id = task_pool.pushDelayed(&shm_attr_t::delayed_refresh,2s, this).task_id; + } - ~shm_attr_t() override - { - while (!task_pool.cancel(refresh_task_id)); - } + shm_attr_t() : x11_attr_t(), shm_xdisplay { XOpenDisplay(nullptr) } { + refresh_task_id = task_pool.pushDelayed(&shm_attr_t::delayed_refresh,2s, this).task_id; + } - capture_e snapshot(img_t *img, std::chrono::milliseconds timeout, bool cursor) override - { - capture_e toReturn; - if (xattr.width != lastWidth || xattr.height != lastHeight) //The whole X server changed, so we gotta reinit everything - { - BOOST_LOG(warning)<< "X dimensions changed in SHM mode, request reinit"sv; - toReturn = capture_e::reinit; - } - else - { - auto img_cookie = xcb_shm_get_image_unchecked(xcb.get(), display->root,displayOffsetX, displayOffsetY, width, height, ~0, XCB_IMAGE_FORMAT_Z_PIXMAP, seg, 0); + ~shm_attr_t() override { + while (!task_pool.cancel(refresh_task_id)); + } - xcb_img_t img_reply { xcb_shm_get_image_reply(xcb.get(), img_cookie,nullptr) }; - if (!img_reply) - { - BOOST_LOG(error) - << "Could not get image reply"sv; - return capture_e::reinit; - } + capture_e snapshot(img_t *img, std::chrono::milliseconds timeout, bool cursor) override { + //The whole X server changed, so we gotta reinit everything + if (xattr.width != lastWidth || xattr.height != lastHeight) { + BOOST_LOG(warning)<< "X dimensions changed in SHM mode, request reinit"sv; + return capture_e::reinit; + } + else { + auto img_cookie = xcb_shm_get_image_unchecked(xcb.get(), display->root,displayOffsetX, displayOffsetY, width, height, ~0, XCB_IMAGE_FORMAT_Z_PIXMAP, seg, 0); - std::copy_n((std::uint8_t*) data.data, frame_size(), img->data); + xcb_img_t img_reply { xcb_shm_get_image_reply(xcb.get(), img_cookie,nullptr) }; + if (!img_reply) { + BOOST_LOG(error) + << "Could not get image reply"sv; + return capture_e::reinit; + } - if (cursor) - { - blend_cursor(shm_xdisplay.get(), *img,displayOffsetX,displayOffsetY); - } + std::copy_n((std::uint8_t*) data.data, frame_size(), img->data); - toReturn = capture_e::ok; - } - return toReturn; - } + if (cursor) { + blend_cursor(shm_xdisplay.get(), *img,displayOffsetX,displayOffsetY); + } - std::shared_ptr alloc_img() override - { - auto img = std::make_shared(); - img->width = width; - img->height = height; - img->pixel_pitch = 4; - img->row_pitch = img->pixel_pitch * width; - img->data = new std::uint8_t[height * img->row_pitch]; + return capture_e::ok; + } + } - return img; - } + std::shared_ptr alloc_img() override { + auto img = std::make_shared(); + img->width = width; + img->height = height; + img->pixel_pitch = 4; + img->row_pitch = img->pixel_pitch * width; + img->data = new std::uint8_t[height * img->row_pitch]; - int dummy_img(platf::img_t *img) override - { - return 0; - } + return img; + } - int init() - { - shm_xdisplay.reset(XOpenDisplay(nullptr)); - xcb.reset(xcb_connect(nullptr, nullptr)); - if (xcb_connection_has_error(xcb.get())) - { - return -1; - } + int dummy_img(platf::img_t *img) override { + return 0; + } - if (!xcb_get_extension_data(xcb.get(), &xcb_shm_id)->present) - { - BOOST_LOG(error) - << "Missing SHM extension"sv; + int init() { + shm_xdisplay.reset(XOpenDisplay(nullptr)); + xcb.reset(xcb_connect(nullptr, nullptr)); + if (xcb_connection_has_error(xcb.get())) + { + return -1; + } - return -1; - } + if (!xcb_get_extension_data(xcb.get(), &xcb_shm_id)->present) + { + BOOST_LOG(error) + << "Missing SHM extension"sv; - auto iter = xcb_setup_roots_iterator(xcb_get_setup(xcb.get())); - display = iter.data; - seg = xcb_generate_id(xcb.get()); + return -1; + } - shm_id.id = shmget(IPC_PRIVATE, frame_size(), IPC_CREAT | 0777); - if (shm_id.id == -1) - { - BOOST_LOG(error) - << "shmget failed"sv; - return -1; - } + auto iter = xcb_setup_roots_iterator(xcb_get_setup(xcb.get())); + display = iter.data; + seg = xcb_generate_id(xcb.get()); - xcb_shm_attach(xcb.get(), seg, shm_id.id, false); - data.data = shmat(shm_id.id, nullptr, 0); + shm_id.id = shmget(IPC_PRIVATE, frame_size(), IPC_CREAT | 0777); + if (shm_id.id == -1) + { + BOOST_LOG(error) + << "shmget failed"sv; + return -1; + } - if ((uintptr_t) data.data == -1) - { - BOOST_LOG(error) - << "shmat failed"sv; + xcb_shm_attach(xcb.get(), seg, shm_id.id, false); + data.data = shmat(shm_id.id, nullptr, 0); - return -1; - } + if ((uintptr_t) data.data == -1) + { + BOOST_LOG(error) + << "shmat failed"sv; - /* - * Commented out resetting of the sizes when intializing X in SHM mode. It might be wrong. Expect issues. This is the default mode, so poisoning those variables is not desired - */ -// width = display->width_in_pixels; -// height = display->height_in_pixels; + return -1; + } - return 0; - } + /* + * Commented out resetting of the sizes when intializing X in SHM mode. It might be wrong. Expect issues. This is the default mode, so poisoning those variables is not desired + */ +// width = display->width_in_pixels; +// height = display->height_in_pixels; - std::uint32_t frame_size() - { - return width * height * 4; - } + return 0; + } + + std::uint32_t frame_size() { + return width * height * 4; + } }; -struct mic_attr_t: public mic_t -{ - pa_sample_spec ss; - util::safe_ptr mic; +struct mic_attr_t: public mic_t { + pa_sample_spec ss; + util::safe_ptr mic; - explicit mic_attr_t(pa_sample_format format, std::uint32_t sample_rate, - std::uint8_t channels) : ss { format, sample_rate, channels }, mic { } - { - } - capture_e sample(std::vector &sample_buf) override - { - auto sample_size = sample_buf.size(); + explicit mic_attr_t(pa_sample_format format, std::uint32_t sample_rate, + std::uint8_t channels) : ss { format, sample_rate, channels }, mic { } { } - auto buf = sample_buf.data(); - int status; - if (pa_simple_read(mic.get(), buf, sample_size * 2, &status)) - { - BOOST_LOG(error) - << "pa_simple_read() failed: "sv << pa_strerror(status); + capture_e sample(std::vector &sample_buf) override { + auto sample_size = sample_buf.size(); - return capture_e::error; - } + auto buf = sample_buf.data(); + 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 capture_e::ok; - } + return capture_e::error; + } + + return capture_e::ok; + } }; -std::shared_ptr shm_display() -{ - auto shm = std::make_shared(); +std::shared_ptr shm_display() { + auto shm = std::make_shared(); - if (shm->init()) - { - return nullptr; - } + if (shm->init()) { + return nullptr; + } - return shm; + return shm; } -std::shared_ptr display(platf::dev_type_e hwdevice_type) -{ - if (hwdevice_type != platf::dev_type_e::none) - { - BOOST_LOG(error)<< "Could not initialize display with the given hw device type."sv; - return nullptr; - } +std::shared_ptr display(platf::dev_type_e hwdevice_type) { + if (hwdevice_type != platf::dev_type_e::none) { + BOOST_LOG(error)<< "Could not initialize display with the given hw device type."sv; + return nullptr; + } - auto shm_disp = shm_display(); //Attempt to use shared memory X11 to avoid copying the frame + auto shm_disp = shm_display(); //Attempt to use shared memory X11 to avoid copying the frame - if (!shm_disp) - { - return std::make_shared(); //Fallback to standard way if else - } + if (!shm_disp) { + return std::make_shared(); //Fallback to standard way if else + } - return shm_disp; + return shm_disp; } -std::unique_ptr microphone(std::uint32_t sample_rate) -{ - auto mic = std::make_unique(PA_SAMPLE_S16LE, sample_rate, 2); +std::unique_ptr microphone(std::uint32_t sample_rate) { + auto mic = std::make_unique(PA_SAMPLE_S16LE, sample_rate, 2); - int status; + int status; - const char *audio_sink = "@DEFAULT_MONITOR@"; - if (!config::audio.sink.empty()) - { - audio_sink = config::audio.sink.c_str(); - } + const char *audio_sink = "@DEFAULT_MONITOR@"; + if (!config::audio.sink.empty()) { + audio_sink = config::audio.sink.c_str(); + } - mic->mic.reset( - pa_simple_new(nullptr, "sunshine", - pa_stream_direction_t::PA_STREAM_RECORD, audio_sink, - "sunshine-record", &mic->ss, nullptr, nullptr, &status)); + mic->mic.reset( + pa_simple_new(nullptr, "sunshine", + pa_stream_direction_t::PA_STREAM_RECORD, audio_sink, + "sunshine-record", &mic->ss, nullptr, nullptr, &status)); - if (!mic->mic) - { - auto err_str = pa_strerror(status); - BOOST_LOG(error) - << "pa_simple_new() failed: "sv << err_str; + if (!mic->mic) { + auto err_str = pa_strerror(status); + BOOST_LOG(error) << "pa_simple_new() failed: "sv << err_str; - log_flush(); - std::abort(); - } + log_flush(); + std::abort(); + } - return mic; + return mic; } -ifaddr_t get_ifaddrs() -{ - ifaddrs *p { nullptr }; +ifaddr_t get_ifaddrs() { + ifaddrs *p { nullptr }; - getifaddrs(&p); + getifaddrs(&p); - return ifaddr_t { p }; + return ifaddr_t { p }; } -std::string from_sockaddr(const sockaddr *const ip_addr) -{ - char data[INET6_ADDRSTRLEN]; +std::string from_sockaddr(const sockaddr *const ip_addr) { + char data[INET6_ADDRSTRLEN]; - auto family = ip_addr->sa_family; - if (family == AF_INET6) - { - inet_ntop(AF_INET6, &((sockaddr_in6*) ip_addr)->sin6_addr, data, - INET6_ADDRSTRLEN); - } + auto family = ip_addr->sa_family; + if (family == AF_INET6) { + inet_ntop(AF_INET6, &((sockaddr_in6*) ip_addr)->sin6_addr, data, + INET6_ADDRSTRLEN); + } - if (family == AF_INET) - { - inet_ntop(AF_INET, &((sockaddr_in*) ip_addr)->sin_addr, data, - INET_ADDRSTRLEN); - } + if (family == AF_INET) { + inet_ntop(AF_INET, &((sockaddr_in*) ip_addr)->sin_addr, data, + INET_ADDRSTRLEN); + } - return std::string { data }; + return std::string { data }; } -std::pair from_sockaddr_ex( - const sockaddr *const ip_addr) -{ - char data[INET6_ADDRSTRLEN]; +std::pair from_sockaddr_ex(const sockaddr *const ip_addr) { + char data[INET6_ADDRSTRLEN]; - auto family = ip_addr->sa_family; - std::uint16_t port; - if (family == AF_INET6) - { - inet_ntop(AF_INET6, &((sockaddr_in6*) ip_addr)->sin6_addr, data, - INET6_ADDRSTRLEN); - port = ((sockaddr_in6*) ip_addr)->sin6_port; - } + auto family = ip_addr->sa_family; + std::uint16_t port; + if (family == AF_INET6) { + inet_ntop(AF_INET6, &((sockaddr_in6*) ip_addr)->sin6_addr, data, + INET6_ADDRSTRLEN); + port = ((sockaddr_in6*) ip_addr)->sin6_port; + } - if (family == AF_INET) - { - inet_ntop(AF_INET, &((sockaddr_in*) ip_addr)->sin_addr, data, - INET_ADDRSTRLEN); - port = ((sockaddr_in*) ip_addr)->sin_port; - } + if (family == AF_INET) { + inet_ntop(AF_INET, &((sockaddr_in*) ip_addr)->sin_addr, data, + INET_ADDRSTRLEN); + port = ((sockaddr_in*) ip_addr)->sin_port; + } - return - { port, std::string - { data}}; + return + { port, std::string {data}}; } -std::string get_mac_address(const std::string_view &address) -{ - auto ifaddrs = get_ifaddrs(); - for (auto pos = ifaddrs.get(); pos != nullptr; pos = pos->ifa_next) - { - if (pos->ifa_addr && address == from_sockaddr(pos->ifa_addr)) - { - std::ifstream mac_file( - "/sys/class/net/"s + pos->ifa_name + "/address"); - if (mac_file.good()) - { - std::string mac_address; - std::getline(mac_file, mac_address); - return mac_address; - } - } - } - BOOST_LOG(warning) - << "Unable to find MAC address for "sv << address; - return "00:00:00:00:00:00"s; +std::string get_mac_address(const std::string_view &address) { + auto ifaddrs = get_ifaddrs(); + for (auto pos = ifaddrs.get(); pos != nullptr; pos = pos->ifa_next) { + if (pos->ifa_addr && address == from_sockaddr(pos->ifa_addr)) { + std::ifstream mac_file("/sys/class/net/"s + pos->ifa_name + "/address"); + if (mac_file.good()) { + std::string mac_address; + std::getline(mac_file, mac_address); + return mac_address; + } + } + } + BOOST_LOG(warning) + << "Unable to find MAC address for "sv << address; + return "00:00:00:00:00:00"s; } -void freeImage(XImage *p) -{ - XDestroyImage(p); +void freeImage(XImage *p) { + XDestroyImage(p); } -void freeX(XFixesCursorImage *p) -{ - XFree(p); +void freeX(XFixesCursorImage *p) { + XFree(p); } }