Replace X11-based screen capture with cross-platform library
Unfortunately this brings back the C++ requirement, but later on this will happen anyway, what with me wanting some CV funsies.
This commit is contained in:
parent
e510d92b17
commit
0384176de6
13
Makefile
13
Makefile
@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
CXXFLAGS := -D_POSIX_C_SOURCE=200809L -Wno-narrowing -march=native -flto -Wall -fvisibility=hidden -fPIC -msse4 -I./ -I/usr/local/include/sail `pkg-config --cflags pango opus libv4l2` '-Wl,-rpath,$$ORIGIN' -Wno-multichar
|
CXXFLAGS := -D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=200809L -Wno-narrowing -march=native -flto -Wall -fvisibility=hidden -fPIC -msse4 -I./ -I/usr/local/include/sail -L/usr/local/lib `pkg-config --cflags pango opus libv4l2` '-Wl,-rpath,$$ORIGIN' -Wno-multichar
|
||||||
LDFLAGS := -lwebm -lpng -lvpx -lsail -lsail-manip `pkg-config --libs pango opus libv4l2` -lportaudio -lXtst -lrtmp -lfdk-aac
|
LDFLAGS := -lwebm -lpng -lvpx -lsail -lsail-manip `pkg-config --libs pango opus libv4l2` -lportaudio -lXtst -lrtmp -lfdk-aac -leebie -lscreen_capture_lite_shared
|
||||||
|
|
||||||
ifneq ($(RELEASE),0)
|
ifneq ($(RELEASE),0)
|
||||||
CXXFLAGS := $(CXXFLAGS) -O0 -gdwarf-2 -DMTR_ENABLED
|
CXXFLAGS := $(CXXFLAGS) -O0 -gdwarf-2 -DMTR_ENABLED
|
||||||
@ -10,12 +10,12 @@ endif
|
|||||||
|
|
||||||
all:
|
all:
|
||||||
$(CC) $(CXXFLAGS) -std=c99 -shared -c -o node.o hi/node.c $(LDFLAGS)
|
$(CC) $(CXXFLAGS) -std=c99 -shared -c -o node.o hi/node.c $(LDFLAGS)
|
||||||
$(CC) $(CXXFLAGS) -std=c99 -shared -c -o window.o hi/window.c $(LDFLAGS)
|
$(CXX) $(CXXFLAGS) -std=c++17 -shared -c -o window.o hi/window.cpp $(LDFLAGS)
|
||||||
$(CC) $(CXXFLAGS) -std=c99 -shared -c -o microphone.o hi/microphone.c $(LDFLAGS)
|
$(CC) $(CXXFLAGS) -std=c99 -shared -c -o microphone.o hi/microphone.c $(LDFLAGS)
|
||||||
$(CC) $(CXXFLAGS) -std=c99 -shared -c -o mode.o hi/mode.c $(LDFLAGS)
|
$(CC) $(CXXFLAGS) -std=c99 -shared -c -o mode.o hi/mode.c $(LDFLAGS)
|
||||||
$(CC) $(CXXFLAGS) -std=c99 -shared -c -o img.o hi/img.c $(LDFLAGS)
|
$(CC) $(CXXFLAGS) -std=c99 -shared -c -o img.o hi/img.c $(LDFLAGS)
|
||||||
$(CXX) $(CXXFLAGS) -std=c++11 -shared -c -o webmdec.o hi/webmdec.cpp $(LDFLAGS)
|
$(CXX) $(CXXFLAGS) -std=c++17 -shared -c -o webmdec.o hi/webmdec.cpp $(LDFLAGS)
|
||||||
$(CXX) $(CXXFLAGS) -std=c++11 -shared -c -o webmenc.o hi/webmenc.cpp $(LDFLAGS)
|
$(CXX) $(CXXFLAGS) -std=c++17 -shared -c -o webmenc.o hi/webmenc.cpp $(LDFLAGS)
|
||||||
$(CC) $(CXXFLAGS) -std=c99 -shared -c -o vpxenc.o hi/vpxenc.c $(LDFLAGS)
|
$(CC) $(CXXFLAGS) -std=c99 -shared -c -o vpxenc.o hi/vpxenc.c $(LDFLAGS)
|
||||||
$(CC) $(CXXFLAGS) -std=c99 -shared -c -o opus.o hi/opus.c $(LDFLAGS)
|
$(CC) $(CXXFLAGS) -std=c99 -shared -c -o opus.o hi/opus.c $(LDFLAGS)
|
||||||
$(CC) $(CXXFLAGS) -std=c99 -shared -c -o webcam.o hi/webcam.c $(LDFLAGS)
|
$(CC) $(CXXFLAGS) -std=c99 -shared -c -o webcam.o hi/webcam.c $(LDFLAGS)
|
||||||
@ -25,6 +25,7 @@ all:
|
|||||||
$(CC) $(CXXFLAGS) -std=c99 -shared -c -o rtmp.o hi/rtmp.c $(LDFLAGS)
|
$(CC) $(CXXFLAGS) -std=c99 -shared -c -o rtmp.o hi/rtmp.c $(LDFLAGS)
|
||||||
$(CC) $(CXXFLAGS) -std=c99 -shared -c -o aaclc.o hi/aaclc.c $(LDFLAGS)
|
$(CC) $(CXXFLAGS) -std=c99 -shared -c -o aaclc.o hi/aaclc.c $(LDFLAGS)
|
||||||
$(CC) $(CXXFLAGS) -std=c99 -shared -c -o mkv.o hi/mkv.c $(LDFLAGS)
|
$(CC) $(CXXFLAGS) -std=c99 -shared -c -o mkv.o hi/mkv.c $(LDFLAGS)
|
||||||
$(CC) $(CXXFLAGS) -shared -o libcutihi.so -shared node.o webmdec.o webmenc.o window.o microphone.o mode.o img.o opus.o webcam.o scale.o minitrace.o h264enc.o rtmp.o aaclc.o vpxenc.o mkv.o $(LDFLAGS)
|
$(CC) $(CXXFLAGS) -std=c99 -shared -c -o serialize.o hi/serialize.c $(LDFLAGS)
|
||||||
|
$(CC) $(CXXFLAGS) -shared -o libcutihi.so -shared node.o webmdec.o webmenc.o window.o microphone.o mode.o img.o opus.o webcam.o scale.o minitrace.o h264enc.o rtmp.o aaclc.o vpxenc.o mkv.o serialize.o $(LDFLAGS)
|
||||||
|
|
||||||
$(CXX) $(CXXFLAGS) -std=c++11 `wx-config --cflags base,adv,core,aui` -o cuticle ui/main.cpp ui/frame.cpp ui/textctrl.cpp ui/timeline.cpp -L./ -lcutihi $(LDFLAGS) `wx-config --libs base,adv,core,aui`
|
$(CXX) $(CXXFLAGS) -std=c++11 `wx-config --cflags base,adv,core,aui` -o cuticle ui/main.cpp ui/frame.cpp ui/textctrl.cpp ui/timeline.cpp -L./ -lcutihi $(LDFLAGS) `wx-config --libs base,adv,core,aui`
|
||||||
|
@ -246,10 +246,10 @@ CUTIVIS int CHi_MuxWebm_Stop(CHiPubNode*);
|
|||||||
#define CUTIHI_WINDOW_OUT_SAMPLE 1
|
#define CUTIHI_WINDOW_OUT_SAMPLE 1
|
||||||
CUTIVIS CHiPubNode *CHi_Window();
|
CUTIVIS CHiPubNode *CHi_Window();
|
||||||
|
|
||||||
CUTIVIS size_t CHi_Window_GetSourceCount();
|
CUTIVIS size_t CHi_Window_GetList(void **buf);
|
||||||
CUTIVIS const char *CHi_Window_GetSourceName(size_t);
|
CUTIVIS const char *CHi_Window_GetName(void *buf, size_t i);
|
||||||
CUTIVIS uintptr_t CHi_Window_GetSourceData(size_t);
|
CUTIVIS size_t CHi_Window_GetHandle(void *buf, size_t i);
|
||||||
CUTIVIS size_t CHi_Window_GetNextSource(size_t);
|
CUTIVIS void CHi_Window_FreeList(void *buf);
|
||||||
|
|
||||||
#define CUTIHI_MICROPHONE_IN_NAME 0
|
#define CUTIHI_MICROPHONE_IN_NAME 0
|
||||||
#define CUTIHI_MICROPHONE_OUT_AUDIO 1
|
#define CUTIHI_MICROPHONE_OUT_AUDIO 1
|
||||||
|
218
hi/window.c
218
hi/window.c
@ -1,218 +0,0 @@
|
|||||||
#include"node.h"
|
|
||||||
|
|
||||||
#include<stdlib.h>
|
|
||||||
|
|
||||||
#include<X11/Xlib.h>
|
|
||||||
#include<X11/Xutil.h>
|
|
||||||
#include<sys/ipc.h>
|
|
||||||
#include<sys/shm.h>
|
|
||||||
#include<X11/extensions/XShm.h>
|
|
||||||
#include<tmmintrin.h>
|
|
||||||
#include<smmintrin.h>
|
|
||||||
|
|
||||||
#include<time.h>
|
|
||||||
|
|
||||||
#include<string.h>
|
|
||||||
|
|
||||||
#include"img.h"
|
|
||||||
|
|
||||||
#include"linearity.h"
|
|
||||||
|
|
||||||
#include"minitrace.h"
|
|
||||||
|
|
||||||
static Display *d;
|
|
||||||
static Window root;
|
|
||||||
|
|
||||||
static int find_window(Display *d, Window *w, const char *contains) {
|
|
||||||
if(contains) {
|
|
||||||
int found = 0;
|
|
||||||
Atom atom = XInternAtom(d, "_NET_CLIENT_LIST", 1);
|
|
||||||
Atom actualType;
|
|
||||||
int format;
|
|
||||||
unsigned long numItems, bytesAfter;
|
|
||||||
|
|
||||||
Window *list;
|
|
||||||
XTextProperty windowName;
|
|
||||||
|
|
||||||
int status = XGetWindowProperty(d, root, atom, 0L, ~0L, 0, AnyPropertyType, &actualType, &format, &numItems, &bytesAfter, (unsigned char**) &list);
|
|
||||||
|
|
||||||
if(status >= Success) {
|
|
||||||
for(int i = 0; i < numItems; i++) {
|
|
||||||
status = XGetWMName(d, list[i], &windowName);
|
|
||||||
if(status >= Success) {
|
|
||||||
if(windowName.value && strstr(windowName.value, contains)) {
|
|
||||||
*w = list[i];
|
|
||||||
found = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
XFree(list);
|
|
||||||
|
|
||||||
return found;
|
|
||||||
} else {
|
|
||||||
*w = root;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
CHiPubNode pub;
|
|
||||||
|
|
||||||
Window xcache;
|
|
||||||
XImage *ximg;
|
|
||||||
XShmSegmentInfo shminfo;
|
|
||||||
|
|
||||||
CHiImage *vcache;
|
|
||||||
} CHiWindowNode;
|
|
||||||
|
|
||||||
static int window_perform(CHiPubNode *n) {
|
|
||||||
CHiWindowNode *w = (CHiWindowNode*) n;
|
|
||||||
|
|
||||||
MTR_BEGIN("CHi", "window_perform");
|
|
||||||
|
|
||||||
Window toshoot;
|
|
||||||
if(!find_window(d, &toshoot, CHi_Crawl(&n->sinks[0])->data.text)) return 0;
|
|
||||||
|
|
||||||
size_t stride;
|
|
||||||
if(!w->xcache || w->xcache != toshoot) {
|
|
||||||
w->xcache = toshoot;
|
|
||||||
|
|
||||||
XWindowAttributes attrs;
|
|
||||||
XGetWindowAttributes(d, toshoot, &attrs);
|
|
||||||
|
|
||||||
w->ximg = XShmCreateImage(d, attrs.visual, 32, ZPixmap, NULL, &w->shminfo, attrs.width, attrs.height);
|
|
||||||
stride = ((w->ximg->bytes_per_line + 15) & ~15);
|
|
||||||
w->shminfo.shmid = shmget(IPC_PRIVATE, stride * w->ximg->height, IPC_CREAT | 0777);
|
|
||||||
w->shminfo.shmaddr = w->ximg->data = shmat(w->shminfo.shmid, 0, 0);
|
|
||||||
w->shminfo.readOnly = False;
|
|
||||||
XShmAttach(d, &w->shminfo);
|
|
||||||
|
|
||||||
w->vcache = CHi_Image_New(2, 4, 8 * attrs.width, attrs.width, attrs.height, NULL);
|
|
||||||
} else {
|
|
||||||
stride = ((w->ximg->bytes_per_line + 15) & ~15);
|
|
||||||
}
|
|
||||||
|
|
||||||
XWindowAttributes toshootattrs;
|
|
||||||
XGetWindowAttributes(d, w->xcache, &toshootattrs);
|
|
||||||
|
|
||||||
XShmGetImage(d, w->xcache, w->ximg, 0, 0, AllPlanes);
|
|
||||||
|
|
||||||
// Turn u8 image to u16
|
|
||||||
#pragma omp parallel for
|
|
||||||
for(size_t y = 0; y < w->vcache->height; y++) {
|
|
||||||
for(size_t x = 0; x < w->vcache->width; x += 2) {
|
|
||||||
__m128i c = _mm_loadu_si128((__m128i*) ((uintptr_t) w->ximg->data + y * w->ximg->bytes_per_line + x * 4));
|
|
||||||
c = _mm_shuffle_epi8(c, _mm_set_epi8(7, -128, 6, -128, 5, -128, 4, -128, 3, -128, 2, -128, 1, -128, 0, -128));
|
|
||||||
c = apply_gamma_epi16(c, _mm_set_ps(1, 2.2f, 2.2f, 2.2f));
|
|
||||||
_mm_storeu_si128((__m128i*) ((uintptr_t) w->vcache->data16 + y * w->vcache->stride + x * 8), c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
n->sources[0].type = CUTIHI_VAL_SAMPLE;
|
|
||||||
n->sources[0].data.sample = w->vcache;
|
|
||||||
|
|
||||||
MTR_END("CHi", "window_perform");
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void window_destroy(CHiPubNode *pubn) {
|
|
||||||
CHiWindowNode *n = (void*) pubn;
|
|
||||||
|
|
||||||
if(n->vcache) {
|
|
||||||
XShmDetach(d, &n->shminfo);
|
|
||||||
shmdt(n->shminfo.shmaddr);
|
|
||||||
XDestroyImage(n->ximg);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(pubn);
|
|
||||||
}
|
|
||||||
|
|
||||||
CUTIVIS CHiPubNode *CHi_Window() {
|
|
||||||
if(!d) {
|
|
||||||
d = XOpenDisplay(NULL);
|
|
||||||
root = RootWindow(d, DefaultScreen(d));
|
|
||||||
}
|
|
||||||
|
|
||||||
CHiWindowNode *n = calloc(1, sizeof(*n));
|
|
||||||
n->pub.type = CUTIHI_T('CWin','dow ');
|
|
||||||
n->pub.Start = n->pub.Stop = NULL;
|
|
||||||
n->pub.Perform = window_perform;
|
|
||||||
n->pub.Destroy = window_destroy;
|
|
||||||
n->pub.sinkCount = 1;
|
|
||||||
n->pub.sinks = calloc(sizeof(*n->pub.sinks), 1);
|
|
||||||
n->pub.sourceCount = 1;
|
|
||||||
n->pub.sources = calloc(sizeof(*n->pub.sources), 1);
|
|
||||||
|
|
||||||
n->xcache = 0;
|
|
||||||
n->vcache = NULL;
|
|
||||||
|
|
||||||
return &n->pub;
|
|
||||||
}
|
|
||||||
|
|
||||||
// All of the following are ews
|
|
||||||
|
|
||||||
CUTIVIS size_t CHi_Window_GetSourceCount() {
|
|
||||||
Atom atom = XInternAtom(d, "_NET_CLIENT_LIST", 1);
|
|
||||||
Atom actualType;
|
|
||||||
int format;
|
|
||||||
unsigned long numItems, bytesAfter;
|
|
||||||
|
|
||||||
Window *list;
|
|
||||||
|
|
||||||
int status = XGetWindowProperty(d, root, atom, 0L, ~0L, 0, AnyPropertyType, &actualType, &format, &numItems, &bytesAfter, (unsigned char**) &list);
|
|
||||||
|
|
||||||
//XFree(list);
|
|
||||||
|
|
||||||
return status >= Success ? numItems : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
CUTIVIS const char *CHi_Window_GetSourceName(size_t idx) {
|
|
||||||
int found = 0;
|
|
||||||
Atom atom = XInternAtom(d, "_NET_CLIENT_LIST", 1);
|
|
||||||
Atom actualType;
|
|
||||||
int format;
|
|
||||||
unsigned long numItems, bytesAfter;
|
|
||||||
|
|
||||||
Window *list;
|
|
||||||
XTextProperty windowName;
|
|
||||||
|
|
||||||
int status = XGetWindowProperty(d, root, atom, 0L, ~0L, 0, AnyPropertyType, &actualType, &format, &numItems, &bytesAfter, (unsigned char**) &list);
|
|
||||||
|
|
||||||
if(status >= Success) {
|
|
||||||
//XFree(list);
|
|
||||||
|
|
||||||
status = XGetWMName(d, list[idx], &windowName);
|
|
||||||
if(status >= Success) {
|
|
||||||
found = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return found ? strdup(windowName.value ? windowName.value : "") : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
CUTIVIS uintptr_t CHi_Window_GetSourceData(size_t idx) {
|
|
||||||
Atom atom = XInternAtom(d, "_NET_CLIENT_LIST", 1);
|
|
||||||
Atom actualType;
|
|
||||||
int format;
|
|
||||||
unsigned long numItems, bytesAfter;
|
|
||||||
|
|
||||||
Window *list;
|
|
||||||
|
|
||||||
int status = XGetWindowProperty(d, root, atom, 0L, ~0L, 0, AnyPropertyType, &actualType, &format, &numItems, &bytesAfter, (unsigned char**) &list);
|
|
||||||
|
|
||||||
if(status >= Success) {
|
|
||||||
Window ret = list[idx];
|
|
||||||
//XFree(list);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
CUTIVIS size_t CHi_Window_GetNextSource(size_t i) {
|
|
||||||
return i + 1;
|
|
||||||
}
|
|
130
hi/window.cpp
Normal file
130
hi/window.cpp
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
#include"node.h"
|
||||||
|
|
||||||
|
#include<stdlib.h>
|
||||||
|
|
||||||
|
#include<ScreenCapture.h>
|
||||||
|
#include<mutex>
|
||||||
|
|
||||||
|
#include<tmmintrin.h>
|
||||||
|
#include<smmintrin.h>
|
||||||
|
|
||||||
|
#include<time.h>
|
||||||
|
|
||||||
|
#include<string.h>
|
||||||
|
|
||||||
|
#include"img.h"
|
||||||
|
|
||||||
|
#include"linearity.h"
|
||||||
|
|
||||||
|
#include"minitrace.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
CHiPubNode pub;
|
||||||
|
|
||||||
|
char* lastWindowString;
|
||||||
|
std::shared_ptr<SL::Screen_Capture::IScreenCaptureManager> config;
|
||||||
|
|
||||||
|
std::mutex mut;
|
||||||
|
std::vector<CHiImage*> images;
|
||||||
|
} CHiWindowNode;
|
||||||
|
|
||||||
|
static int window_perform(CHiPubNode *n) {
|
||||||
|
CHiWindowNode *w = (CHiWindowNode*) n;
|
||||||
|
|
||||||
|
MTR_BEGIN("CHi", "window_perform");
|
||||||
|
|
||||||
|
const char *expectedTitle = CHi_Crawl(&w->pub.sinks[0])->data.text;
|
||||||
|
|
||||||
|
if(w->lastWindowString == nullptr || strcmp(w->lastWindowString, expectedTitle)) {
|
||||||
|
if(w->lastWindowString) {
|
||||||
|
free(w->lastWindowString);
|
||||||
|
}
|
||||||
|
w->lastWindowString = strdup(expectedTitle);
|
||||||
|
|
||||||
|
w->config = SL::Screen_Capture::CreateCaptureConfiguration([=](){
|
||||||
|
for(SL::Screen_Capture::Window& window : SL::Screen_Capture::GetWindows()) {
|
||||||
|
if(!strcmp(window.Name, w->lastWindowString)) {
|
||||||
|
return std::vector<SL::Screen_Capture::Window>{window};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return std::vector<SL::Screen_Capture::Window>{};
|
||||||
|
})->onNewFrame([=](const SL::Screen_Capture::Image& img, const SL::Screen_Capture::Window& window){
|
||||||
|
CHiImage *new_image = CHi_Image_New(2, 4, (window.Size.x * 8 + 15) & ~15, window.Size.x, window.Size.y, nullptr);
|
||||||
|
memset(new_image->data8, 0, new_image->stride * new_image->height);
|
||||||
|
|
||||||
|
#pragma omp parallel for
|
||||||
|
for(size_t y = 0; y < new_image->height; y++) {
|
||||||
|
uint8_t buf[16] = {};
|
||||||
|
for(size_t x = 0; x < new_image->width; x += 2) {
|
||||||
|
memcpy(buf, &img.Data[y * new_image->width + x], 8);
|
||||||
|
|
||||||
|
__m128i c = _mm_loadu_si128((__m128i*) buf);
|
||||||
|
c = _mm_shuffle_epi8(c, _mm_set_epi8(7, -128, 6, -128, 5, -128, 4, -128, 3, -128, 2, -128, 1, -128, 0, -128));
|
||||||
|
c = apply_gamma_epi16(c, _mm_set_ps(1, 2.2f, 2.2f, 2.2f));
|
||||||
|
_mm_store_si128((__m128i*) ((uintptr_t) new_image->data8 + y * new_image->stride + x * 8), c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_lock<std::mutex> lock{w->mut};
|
||||||
|
while(w->images.size() > 0) {
|
||||||
|
CHi_Image_Free(w->images.front());
|
||||||
|
w->images.erase(w->images.begin());
|
||||||
|
}
|
||||||
|
w->images.push_back(new_image);
|
||||||
|
})->start_capturing();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_lock<std::mutex> lock{w->mut};
|
||||||
|
if(w->images.size() > 0) {
|
||||||
|
if(n->sources[0].data.sample) {
|
||||||
|
CHi_Image_Free(n->sources[0].data.sample);
|
||||||
|
}
|
||||||
|
|
||||||
|
n->sources[0].type = CUTIHI_VAL_SAMPLE;
|
||||||
|
n->sources[0].data.sample = w->images.front();
|
||||||
|
|
||||||
|
w->images.erase(w->images.begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
MTR_END("CHi", "window_perform");
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void window_destroy(CHiPubNode *pubn) {
|
||||||
|
CHiWindowNode *n = (CHiWindowNode*) pubn;
|
||||||
|
delete n;
|
||||||
|
}
|
||||||
|
|
||||||
|
CUTIVIS CHiPubNode *CHi_Window() {
|
||||||
|
auto *n = new CHiWindowNode();
|
||||||
|
n->pub.type = CUTIHI_T('CWin','dow ');
|
||||||
|
n->pub.Start = n->pub.Stop = NULL;
|
||||||
|
n->pub.Perform = window_perform;
|
||||||
|
n->pub.Destroy = window_destroy;
|
||||||
|
n->pub.sinkCount = 1;
|
||||||
|
n->pub.sinks = (CHiValue*) calloc(sizeof(*n->pub.sinks), 1);
|
||||||
|
n->pub.sourceCount = 1;
|
||||||
|
n->pub.sources = (CHiValue*) calloc(sizeof(*n->pub.sources), 1);
|
||||||
|
|
||||||
|
return &n->pub;
|
||||||
|
}
|
||||||
|
|
||||||
|
CUTIVIS size_t CHi_Window_GetList(void **buf) {
|
||||||
|
auto vec = SL::Screen_Capture::GetWindows();
|
||||||
|
|
||||||
|
*buf = calloc(vec.size(), sizeof(vec[0]));
|
||||||
|
memcpy(*buf, &vec[0], sizeof(vec[0]) * vec.size());
|
||||||
|
|
||||||
|
return vec.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
CUTIVIS const char *CHi_Window_GetName(void *buf, size_t i) {
|
||||||
|
return ((SL::Screen_Capture::Window*) buf)[i].Name;
|
||||||
|
}
|
||||||
|
CUTIVIS size_t CHi_Window_GetHandle(void *buf, size_t i) {
|
||||||
|
return ((SL::Screen_Capture::Window*) buf)[i].Handle;
|
||||||
|
}
|
||||||
|
CUTIVIS void CHi_Window_FreeList(void *buf) {
|
||||||
|
free(buf);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user