Use existing config option for selecting monitor
This commit is contained in:
@@ -95,7 +95,7 @@
|
|||||||
|
|
||||||
# !! Linux only !!
|
# !! Linux only !!
|
||||||
# Set the display number to stream. I have no idea how they are numbered. They start from 1, usually.
|
# 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
|
# FFmpeg software encoding parameters
|
||||||
|
|||||||
+1
-1
Submodule pre-compiled updated: afd9a9bbfc...bbf5647402
@@ -106,7 +106,6 @@ video_t video {
|
|||||||
{}, // encoder
|
{}, // encoder
|
||||||
{}, // adapter_name
|
{}, // adapter_name
|
||||||
{}, // output_name
|
{}, // output_name
|
||||||
-1
|
|
||||||
};
|
};
|
||||||
|
|
||||||
audio_t audio {};
|
audio_t audio {};
|
||||||
@@ -372,8 +371,6 @@ void apply_config(std::unordered_map<std::string, std::string> &&vars) {
|
|||||||
|
|
||||||
string_f(vars, "audio_sink", audio.sink);
|
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, {
|
string_restricted_f(vars, "origin_pin_allowed", nvhttp.origin_pin_allowed, {
|
||||||
"pc"sv, "lan"sv, "wan"sv
|
"pc"sv, "lan"sv, "wan"sv
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -29,8 +29,6 @@ struct video_t {
|
|||||||
std::string encoder;
|
std::string encoder;
|
||||||
std::string adapter_name;
|
std::string adapter_name;
|
||||||
std::string output_name;
|
std::string output_name;
|
||||||
|
|
||||||
int linux_monitor_id; //Only used on linux
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct audio_t {
|
struct audio_t {
|
||||||
|
|||||||
@@ -43,24 +43,16 @@ using xdisplay_t = util::safe_ptr_v2<Display, int, XCloseDisplay>;
|
|||||||
using ximg_t = util::safe_ptr<XImage, freeImage>;
|
using ximg_t = util::safe_ptr<XImage, freeImage>;
|
||||||
using xcursor_t = util::safe_ptr<XFixesCursorImage, freeX>;
|
using xcursor_t = util::safe_ptr<XFixesCursorImage, freeX>;
|
||||||
|
|
||||||
class shm_id_t
|
class shm_id_t {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
shm_id_t() : 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) {
|
||||||
shm_id_t(int id) : id { id }
|
|
||||||
{
|
|
||||||
}
|
|
||||||
shm_id_t(shm_id_t &&other) noexcept : id(other.id)
|
|
||||||
{
|
|
||||||
other.id = -1;
|
other.id = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
~shm_id_t()
|
~shm_id_t() {
|
||||||
{
|
if (id != -1) {
|
||||||
if (id != -1)
|
|
||||||
{
|
|
||||||
shmctl(id, IPC_RMID, nullptr);
|
shmctl(id, IPC_RMID, nullptr);
|
||||||
id = -1;
|
id = -1;
|
||||||
}
|
}
|
||||||
@@ -68,8 +60,7 @@ public:
|
|||||||
int id;
|
int id;
|
||||||
};
|
};
|
||||||
|
|
||||||
class shm_data_t
|
class shm_data_t {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
shm_data_t() : data { (void*) -1 }
|
shm_data_t() : data { (void*) -1 }
|
||||||
{
|
{
|
||||||
@@ -95,13 +86,11 @@ public:
|
|||||||
void *data;
|
void *data;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct x11_img_t: public img_t
|
struct x11_img_t: public img_t {
|
||||||
{
|
|
||||||
ximg_t img;
|
ximg_t img;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct shm_img_t: public img_t
|
struct shm_img_t: public img_t {
|
||||||
{
|
|
||||||
~shm_img_t() override
|
~shm_img_t() override
|
||||||
{
|
{
|
||||||
delete[] data;
|
delete[] data;
|
||||||
@@ -109,12 +98,10 @@ struct shm_img_t: public img_t
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void blend_cursor(Display *display, img_t &img, int offsetX,int offsetY)
|
void blend_cursor(Display *display, img_t &img, int offsetX, int offsetY) {
|
||||||
{
|
|
||||||
xcursor_t overlay { XFixesGetCursorImage(display) };
|
xcursor_t overlay { XFixesGetCursorImage(display) };
|
||||||
|
|
||||||
if (!overlay)
|
if (!overlay) {
|
||||||
{
|
|
||||||
BOOST_LOG(error)
|
BOOST_LOG(error)
|
||||||
<< "Couldn't get cursor from XFixesGetCursorImage"sv;
|
<< "Couldn't get cursor from XFixesGetCursorImage"sv;
|
||||||
return;
|
return;
|
||||||
@@ -136,26 +123,22 @@ void blend_cursor(Display *display, img_t &img, int offsetX,int offsetY)
|
|||||||
|
|
||||||
auto delta_height = std::min<uint16_t>(overlay->height,std::max(0, screen_height - overlay->y));
|
auto delta_height = std::min<uint16_t>(overlay->height,std::max(0, screen_height - overlay->y));
|
||||||
auto delta_width = std::min<uint16_t>(overlay->width,std::max(0, screen_width - overlay->x));
|
auto delta_width = std::min<uint16_t>(overlay->width,std::max(0, screen_width - overlay->x));
|
||||||
for (auto y = 0; y < delta_height; ++y)
|
for (auto y = 0; y < delta_height; ++y) {
|
||||||
{
|
|
||||||
auto overlay_begin = &overlay->pixels[y * overlay->width];
|
auto overlay_begin = &overlay->pixels[y * overlay->width];
|
||||||
auto overlay_end = &overlay->pixels[y * overlay->width + delta_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)
|
std::for_each(overlay_begin, overlay_end,[&](long pixel) {
|
||||||
{
|
|
||||||
int *pixel_p = (int*) &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;
|
auto alpha = (*(uint*) pixel_p) >> 24u;
|
||||||
if (alpha == 255)
|
if (alpha == 255) {
|
||||||
{
|
|
||||||
*pixels_begin = *pixel_p;
|
*pixels_begin = *pixel_p;
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
auto colors_out = (uint8_t*) pixel_p;
|
auto colors_out = (uint8_t*) pixel_p;
|
||||||
colors_in[0] = colors_out[0] + (colors_in[0] * (255 - alpha) +255 /2) / 255;
|
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[1] = colors_out[1] + (colors_in[1] * (255 - alpha) + 255 / 2) / 255;
|
||||||
@@ -186,10 +169,8 @@ struct x11_attr_t: public display_t
|
|||||||
x11_attr_t() : xdisplay { displayDisplay = XOpenDisplay(nullptr) }, xwindow { }, xattr { }
|
x11_attr_t() : xdisplay { displayDisplay = XOpenDisplay(nullptr) }, xwindow { }, xattr { }
|
||||||
{
|
{
|
||||||
XInitThreads();
|
XInitThreads();
|
||||||
if (!xdisplay)
|
if (!xdisplay) {
|
||||||
{
|
BOOST_LOG(fatal) << "Could not open x11 display"sv;
|
||||||
BOOST_LOG(fatal)
|
|
||||||
<< "Could not open x11 display"sv;
|
|
||||||
log_flush();
|
log_flush();
|
||||||
std::abort();
|
std::abort();
|
||||||
}
|
}
|
||||||
@@ -198,22 +179,23 @@ struct x11_attr_t: public display_t
|
|||||||
|
|
||||||
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;
|
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);
|
XRRScreenResources *screenr = XRRGetScreenResources(displayDisplay, xwindow);
|
||||||
// This is the key right here. Use XRRScreenResources::noutput
|
// This is the key right here. Use XRRScreenResources::noutput
|
||||||
int output = screenr->noutput;
|
int output = screenr->noutput;
|
||||||
|
|
||||||
if (streamedMonitor >= output)
|
if (streamedMonitor >= output) {
|
||||||
{
|
|
||||||
BOOST_LOG(error)<< "Could not stream selected display number because there aren't so many."sv;
|
BOOST_LOG(error)<< "Could not stream selected display number because there aren't so many."sv;
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
XRROutputInfo* out_info = XRRGetOutputInfo(displayDisplay, screenr, screenr->outputs[streamedMonitor]);
|
XRROutputInfo* out_info = XRRGetOutputInfo(displayDisplay, screenr, screenr->outputs[streamedMonitor]);
|
||||||
if (NULL == out_info || out_info->connection != RR_Connected)
|
if (NULL == out_info || out_info->connection != RR_Connected)
|
||||||
{
|
{
|
||||||
@@ -235,8 +217,7 @@ struct x11_attr_t: public display_t
|
|||||||
}
|
}
|
||||||
XRRFreeScreenResources(screenr);
|
XRRFreeScreenResources(screenr);
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
width = xattr.width;
|
width = xattr.width;
|
||||||
height = xattr.height;
|
height = xattr.height;
|
||||||
}
|
}
|
||||||
@@ -253,17 +234,14 @@ struct x11_attr_t: public display_t
|
|||||||
XGetWindowAttributes(xdisplay.get(), xwindow, &xattr); //Update xattr's
|
XGetWindowAttributes(xdisplay.get(), xwindow, &xattr); //Update xattr's
|
||||||
}
|
}
|
||||||
|
|
||||||
capture_e snapshot(img_t *img_out_base, std::chrono::milliseconds timeout, bool cursor) override
|
capture_e snapshot(img_t *img_out_base, std::chrono::milliseconds timeout, bool cursor) override {
|
||||||
{
|
|
||||||
refresh();
|
refresh();
|
||||||
capture_e toReturn;
|
|
||||||
if (xattr.width != lastWidth || xattr.height != lastHeight) //The whole X server changed, so we gotta reinit everything
|
//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;
|
BOOST_LOG(warning)<< "X dimensions changed in non-SHM mode, request reinit"sv;
|
||||||
toReturn = capture_e::reinit;
|
return capture_e::reinit;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
XImage *img { XGetImage(xdisplay.get(), xwindow, displayOffsetX, displayOffsetY, width,height, AllPlanes, ZPixmap) };
|
XImage *img { XGetImage(xdisplay.get(), xwindow, displayOffsetX, displayOffsetY, width,height, AllPlanes, ZPixmap) };
|
||||||
|
|
||||||
auto img_out = (x11_img_t*) img_out_base;
|
auto img_out = (x11_img_t*) img_out_base;
|
||||||
@@ -274,29 +252,24 @@ struct x11_attr_t: public display_t
|
|||||||
img_out->pixel_pitch = img->bits_per_pixel / 8;
|
img_out->pixel_pitch = img->bits_per_pixel / 8;
|
||||||
img_out->img.reset(img);
|
img_out->img.reset(img);
|
||||||
|
|
||||||
if (cursor)
|
if (cursor) {
|
||||||
{
|
|
||||||
blend_cursor(xdisplay.get(), *img_out_base,displayOffsetX,displayOffsetY);
|
blend_cursor(xdisplay.get(), *img_out_base,displayOffsetX,displayOffsetY);
|
||||||
}
|
}
|
||||||
toReturn = capture_e::ok;
|
|
||||||
}
|
return capture_e::ok;
|
||||||
return toReturn;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<img_t> alloc_img() override
|
std::shared_ptr<img_t> alloc_img() override {
|
||||||
{
|
|
||||||
return std::make_shared<x11_img_t>();
|
return std::make_shared<x11_img_t>();
|
||||||
}
|
}
|
||||||
|
|
||||||
int dummy_img(img_t *img) override
|
int dummy_img(img_t *img) override {
|
||||||
{
|
|
||||||
snapshot(img, 0s, true);
|
snapshot(img, 0s, true);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct shm_attr_t: public x11_attr_t
|
struct shm_attr_t: public x11_attr_t {
|
||||||
{
|
|
||||||
xdisplay_t shm_xdisplay; // Prevent race condition with x11_attr_t::xdisplay
|
xdisplay_t shm_xdisplay; // Prevent race condition with x11_attr_t::xdisplay
|
||||||
xcb_connect_t xcb;
|
xcb_connect_t xcb;
|
||||||
xcb_screen_t *display;
|
xcb_screen_t *display;
|
||||||
@@ -307,38 +280,32 @@ struct shm_attr_t: public x11_attr_t
|
|||||||
shm_data_t data;
|
shm_data_t data;
|
||||||
|
|
||||||
util::TaskPool::task_id_t refresh_task_id;
|
util::TaskPool::task_id_t refresh_task_id;
|
||||||
void delayed_refresh()
|
|
||||||
{
|
void delayed_refresh() {
|
||||||
refresh();
|
refresh();
|
||||||
|
|
||||||
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() : x11_attr_t(), shm_xdisplay { XOpenDisplay(nullptr) }
|
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
|
~shm_attr_t() override {
|
||||||
{
|
|
||||||
while (!task_pool.cancel(refresh_task_id));
|
while (!task_pool.cancel(refresh_task_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
capture_e snapshot(img_t *img, std::chrono::milliseconds timeout, bool cursor) override
|
capture_e snapshot(img_t *img, std::chrono::milliseconds timeout, bool cursor) override {
|
||||||
{
|
//The whole X server changed, so we gotta reinit everything
|
||||||
capture_e toReturn;
|
if (xattr.width != lastWidth || xattr.height != lastHeight) {
|
||||||
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;
|
BOOST_LOG(warning)<< "X dimensions changed in SHM mode, request reinit"sv;
|
||||||
toReturn = capture_e::reinit;
|
return capture_e::reinit;
|
||||||
}
|
}
|
||||||
else
|
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);
|
auto img_cookie = xcb_shm_get_image_unchecked(xcb.get(), display->root,displayOffsetX, displayOffsetY, width, height, ~0, XCB_IMAGE_FORMAT_Z_PIXMAP, seg, 0);
|
||||||
|
|
||||||
xcb_img_t img_reply { xcb_shm_get_image_reply(xcb.get(), img_cookie,nullptr) };
|
xcb_img_t img_reply { xcb_shm_get_image_reply(xcb.get(), img_cookie,nullptr) };
|
||||||
if (!img_reply)
|
if (!img_reply) {
|
||||||
{
|
|
||||||
BOOST_LOG(error)
|
BOOST_LOG(error)
|
||||||
<< "Could not get image reply"sv;
|
<< "Could not get image reply"sv;
|
||||||
return capture_e::reinit;
|
return capture_e::reinit;
|
||||||
@@ -346,18 +313,15 @@ struct shm_attr_t: public x11_attr_t
|
|||||||
|
|
||||||
std::copy_n((std::uint8_t*) data.data, frame_size(), img->data);
|
std::copy_n((std::uint8_t*) data.data, frame_size(), img->data);
|
||||||
|
|
||||||
if (cursor)
|
if (cursor) {
|
||||||
{
|
|
||||||
blend_cursor(shm_xdisplay.get(), *img,displayOffsetX,displayOffsetY);
|
blend_cursor(shm_xdisplay.get(), *img,displayOffsetX,displayOffsetY);
|
||||||
}
|
}
|
||||||
|
|
||||||
toReturn = capture_e::ok;
|
return capture_e::ok;
|
||||||
}
|
}
|
||||||
return toReturn;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<img_t> alloc_img() override
|
std::shared_ptr<img_t> alloc_img() override {
|
||||||
{
|
|
||||||
auto img = std::make_shared<shm_img_t>();
|
auto img = std::make_shared<shm_img_t>();
|
||||||
img->width = width;
|
img->width = width;
|
||||||
img->height = height;
|
img->height = height;
|
||||||
@@ -368,13 +332,11 @@ struct shm_attr_t: public x11_attr_t
|
|||||||
return img;
|
return img;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dummy_img(platf::img_t *img) override
|
int dummy_img(platf::img_t *img) override {
|
||||||
{
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int init()
|
int init() {
|
||||||
{
|
|
||||||
shm_xdisplay.reset(XOpenDisplay(nullptr));
|
shm_xdisplay.reset(XOpenDisplay(nullptr));
|
||||||
xcb.reset(xcb_connect(nullptr, nullptr));
|
xcb.reset(xcb_connect(nullptr, nullptr));
|
||||||
if (xcb_connection_has_error(xcb.get()))
|
if (xcb_connection_has_error(xcb.get()))
|
||||||
@@ -422,23 +384,19 @@ struct shm_attr_t: public x11_attr_t
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::uint32_t frame_size()
|
std::uint32_t frame_size() {
|
||||||
{
|
|
||||||
return width * height * 4;
|
return width * height * 4;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mic_attr_t: public mic_t
|
struct mic_attr_t: public mic_t {
|
||||||
{
|
|
||||||
pa_sample_spec ss;
|
pa_sample_spec ss;
|
||||||
util::safe_ptr<pa_simple, pa_simple_free> mic;
|
util::safe_ptr<pa_simple, pa_simple_free> mic;
|
||||||
|
|
||||||
explicit mic_attr_t(pa_sample_format format, std::uint32_t sample_rate,
|
explicit mic_attr_t(pa_sample_format format, std::uint32_t sample_rate,
|
||||||
std::uint8_t channels) : ss { format, sample_rate, channels }, mic { }
|
std::uint8_t channels) : ss { format, sample_rate, channels }, mic { } { }
|
||||||
{
|
|
||||||
}
|
capture_e sample(std::vector<std::int16_t> &sample_buf) override {
|
||||||
capture_e sample(std::vector<std::int16_t> &sample_buf) override
|
|
||||||
{
|
|
||||||
auto sample_size = sample_buf.size();
|
auto sample_size = sample_buf.size();
|
||||||
|
|
||||||
auto buf = sample_buf.data();
|
auto buf = sample_buf.data();
|
||||||
@@ -455,45 +413,38 @@ struct mic_attr_t: public mic_t
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::shared_ptr<display_t> shm_display()
|
std::shared_ptr<display_t> shm_display() {
|
||||||
{
|
|
||||||
auto shm = std::make_shared<shm_attr_t>();
|
auto shm = std::make_shared<shm_attr_t>();
|
||||||
|
|
||||||
if (shm->init())
|
if (shm->init()) {
|
||||||
{
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return shm;
|
return shm;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<display_t> display(platf::dev_type_e hwdevice_type)
|
std::shared_ptr<display_t> display(platf::dev_type_e hwdevice_type) {
|
||||||
{
|
if (hwdevice_type != platf::dev_type_e::none) {
|
||||||
if (hwdevice_type != platf::dev_type_e::none)
|
|
||||||
{
|
|
||||||
BOOST_LOG(error)<< "Could not initialize display with the given hw device type."sv;
|
BOOST_LOG(error)<< "Could not initialize display with the given hw device type."sv;
|
||||||
return nullptr;
|
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)
|
if (!shm_disp) {
|
||||||
{
|
|
||||||
return std::make_shared<x11_attr_t>(); //Fallback to standard way if else
|
return std::make_shared<x11_attr_t>(); //Fallback to standard way if else
|
||||||
}
|
}
|
||||||
|
|
||||||
return shm_disp;
|
return shm_disp;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<mic_t> microphone(std::uint32_t sample_rate)
|
std::unique_ptr<mic_t> microphone(std::uint32_t sample_rate) {
|
||||||
{
|
|
||||||
auto mic = std::make_unique<mic_attr_t>(PA_SAMPLE_S16LE, sample_rate, 2);
|
auto mic = std::make_unique<mic_attr_t>(PA_SAMPLE_S16LE, sample_rate, 2);
|
||||||
|
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
const char *audio_sink = "@DEFAULT_MONITOR@";
|
const char *audio_sink = "@DEFAULT_MONITOR@";
|
||||||
if (!config::audio.sink.empty())
|
if (!config::audio.sink.empty()) {
|
||||||
{
|
|
||||||
audio_sink = config::audio.sink.c_str();
|
audio_sink = config::audio.sink.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -502,11 +453,9 @@ std::unique_ptr<mic_t> microphone(std::uint32_t sample_rate)
|
|||||||
pa_stream_direction_t::PA_STREAM_RECORD, audio_sink,
|
pa_stream_direction_t::PA_STREAM_RECORD, audio_sink,
|
||||||
"sunshine-record", &mic->ss, nullptr, nullptr, &status));
|
"sunshine-record", &mic->ss, nullptr, nullptr, &status));
|
||||||
|
|
||||||
if (!mic->mic)
|
if (!mic->mic) {
|
||||||
{
|
|
||||||
auto err_str = pa_strerror(status);
|
auto err_str = pa_strerror(status);
|
||||||
BOOST_LOG(error)
|
BOOST_LOG(error) << "pa_simple_new() failed: "sv << err_str;
|
||||||
<< "pa_simple_new() failed: "sv << err_str;
|
|
||||||
|
|
||||||
log_flush();
|
log_flush();
|
||||||
std::abort();
|
std::abort();
|
||||||
@@ -515,8 +464,7 @@ std::unique_ptr<mic_t> microphone(std::uint32_t sample_rate)
|
|||||||
return mic;
|
return mic;
|
||||||
}
|
}
|
||||||
|
|
||||||
ifaddr_t get_ifaddrs()
|
ifaddr_t get_ifaddrs() {
|
||||||
{
|
|
||||||
ifaddrs *p { nullptr };
|
ifaddrs *p { nullptr };
|
||||||
|
|
||||||
getifaddrs(&p);
|
getifaddrs(&p);
|
||||||
@@ -524,19 +472,16 @@ ifaddr_t get_ifaddrs()
|
|||||||
return ifaddr_t { p };
|
return ifaddr_t { p };
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string from_sockaddr(const sockaddr *const ip_addr)
|
std::string from_sockaddr(const sockaddr *const ip_addr) {
|
||||||
{
|
|
||||||
char data[INET6_ADDRSTRLEN];
|
char data[INET6_ADDRSTRLEN];
|
||||||
|
|
||||||
auto family = ip_addr->sa_family;
|
auto family = ip_addr->sa_family;
|
||||||
if (family == AF_INET6)
|
if (family == AF_INET6) {
|
||||||
{
|
|
||||||
inet_ntop(AF_INET6, &((sockaddr_in6*) ip_addr)->sin6_addr, data,
|
inet_ntop(AF_INET6, &((sockaddr_in6*) ip_addr)->sin6_addr, data,
|
||||||
INET6_ADDRSTRLEN);
|
INET6_ADDRSTRLEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (family == AF_INET)
|
if (family == AF_INET) {
|
||||||
{
|
|
||||||
inet_ntop(AF_INET, &((sockaddr_in*) ip_addr)->sin_addr, data,
|
inet_ntop(AF_INET, &((sockaddr_in*) ip_addr)->sin_addr, data,
|
||||||
INET_ADDRSTRLEN);
|
INET_ADDRSTRLEN);
|
||||||
}
|
}
|
||||||
@@ -544,43 +489,33 @@ std::string from_sockaddr(const sockaddr *const ip_addr)
|
|||||||
return std::string { data };
|
return std::string { data };
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<std::uint16_t, std::string> from_sockaddr_ex(
|
std::pair<std::uint16_t, std::string> from_sockaddr_ex(const sockaddr *const ip_addr) {
|
||||||
const sockaddr *const ip_addr)
|
|
||||||
{
|
|
||||||
char data[INET6_ADDRSTRLEN];
|
char data[INET6_ADDRSTRLEN];
|
||||||
|
|
||||||
auto family = ip_addr->sa_family;
|
auto family = ip_addr->sa_family;
|
||||||
std::uint16_t port;
|
std::uint16_t port;
|
||||||
if (family == AF_INET6)
|
if (family == AF_INET6) {
|
||||||
{
|
|
||||||
inet_ntop(AF_INET6, &((sockaddr_in6*) ip_addr)->sin6_addr, data,
|
inet_ntop(AF_INET6, &((sockaddr_in6*) ip_addr)->sin6_addr, data,
|
||||||
INET6_ADDRSTRLEN);
|
INET6_ADDRSTRLEN);
|
||||||
port = ((sockaddr_in6*) ip_addr)->sin6_port;
|
port = ((sockaddr_in6*) ip_addr)->sin6_port;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (family == AF_INET)
|
if (family == AF_INET) {
|
||||||
{
|
|
||||||
inet_ntop(AF_INET, &((sockaddr_in*) ip_addr)->sin_addr, data,
|
inet_ntop(AF_INET, &((sockaddr_in*) ip_addr)->sin_addr, data,
|
||||||
INET_ADDRSTRLEN);
|
INET_ADDRSTRLEN);
|
||||||
port = ((sockaddr_in*) ip_addr)->sin_port;
|
port = ((sockaddr_in*) ip_addr)->sin_port;
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
{ port, std::string
|
{ port, std::string {data}};
|
||||||
{ data}};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string get_mac_address(const std::string_view &address)
|
std::string get_mac_address(const std::string_view &address) {
|
||||||
{
|
|
||||||
auto ifaddrs = get_ifaddrs();
|
auto ifaddrs = get_ifaddrs();
|
||||||
for (auto pos = ifaddrs.get(); pos != nullptr; pos = pos->ifa_next)
|
for (auto pos = ifaddrs.get(); pos != nullptr; pos = pos->ifa_next) {
|
||||||
{
|
if (pos->ifa_addr && address == from_sockaddr(pos->ifa_addr)) {
|
||||||
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::ifstream mac_file(
|
|
||||||
"/sys/class/net/"s + pos->ifa_name + "/address");
|
|
||||||
if (mac_file.good())
|
|
||||||
{
|
|
||||||
std::string mac_address;
|
std::string mac_address;
|
||||||
std::getline(mac_file, mac_address);
|
std::getline(mac_file, mac_address);
|
||||||
return mac_address;
|
return mac_address;
|
||||||
@@ -592,12 +527,10 @@ std::string get_mac_address(const std::string_view &address)
|
|||||||
return "00:00:00:00:00:00"s;
|
return "00:00:00:00:00:00"s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void freeImage(XImage *p)
|
void freeImage(XImage *p) {
|
||||||
{
|
|
||||||
XDestroyImage(p);
|
XDestroyImage(p);
|
||||||
}
|
}
|
||||||
void freeX(XFixesCursorImage *p)
|
void freeX(XFixesCursorImage *p) {
|
||||||
{
|
|
||||||
XFree(p);
|
XFree(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user