mirror of
https://github.com/jojo61/vdr-plugin-softhdcuvid.git
synced 2023-10-10 13:37:41 +02:00
fixed detach crash hopefully
This commit is contained in:
parent
9a14e748c9
commit
cca1022528
@ -1594,10 +1594,10 @@ bool cOglThread::InitOpenGL(void) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if 1
|
|
||||||
if (!GlxInitopengl())
|
if (!GlxInitopengl())
|
||||||
return false;
|
return false;
|
||||||
#endif
|
|
||||||
VertexBuffers[vbText]->EnableBlending();
|
VertexBuffers[vbText]->EnableBlending();
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
return true;
|
return true;
|
||||||
@ -1650,7 +1650,7 @@ void cOglThread::DeleteVertexBuffers(void) {
|
|||||||
void cOglThread::Cleanup(void) {
|
void cOglThread::Cleanup(void) {
|
||||||
esyslog("[softhddev]OglThread cleanup\n");
|
esyslog("[softhddev]OglThread cleanup\n");
|
||||||
DeleteVertexBuffers();
|
DeleteVertexBuffers();
|
||||||
delete cOglOsd::oFb;
|
// delete cOglOsd::oFb;
|
||||||
cOglOsd::oFb = NULL;
|
cOglOsd::oFb = NULL;
|
||||||
DeleteShaders();
|
DeleteShaders();
|
||||||
// glVDPAUFiniNV();
|
// glVDPAUFiniNV();
|
||||||
|
252
softhdcuvid.cpp
252
softhdcuvid.cpp
@ -3595,163 +3595,163 @@ cString cPluginSoftHdDevice::SVDRPCommand(const char *command,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!strcasecmp(command, "SUSP")) {
|
if (!strcasecmp(command, "SUSP")) {
|
||||||
if (cSoftHdControl::Player) { // already suspended
|
if (cSoftHdControl::Player) { // already suspended
|
||||||
return "SoftHdDevice already suspended";
|
return "SoftHdDevice already suspended";
|
||||||
}
|
}
|
||||||
if (SuspendMode != NOT_SUSPENDED) {
|
if (SuspendMode != NOT_SUSPENDED) {
|
||||||
return "SoftHdDevice already detached";
|
return "SoftHdDevice already detached";
|
||||||
}
|
}
|
||||||
cControl::Launch(new cSoftHdControl);
|
|
||||||
cControl::Attach();
|
|
||||||
Suspend(ConfigSuspendClose, ConfigSuspendClose, ConfigSuspendX11);
|
|
||||||
SuspendMode = SUSPEND_NORMAL;
|
|
||||||
#ifdef USE_OPENGLOSD
|
#ifdef USE_OPENGLOSD
|
||||||
dsyslog("[softhddev]stopping Ogl Thread svdrp STAT");
|
dsyslog("[softhddev]stopping Ogl Thread svdrp STAT");
|
||||||
cSoftOsdProvider::StopOpenGlThread();
|
cSoftOsdProvider::StopOpenGlThread();
|
||||||
#endif
|
#endif
|
||||||
return "SoftHdDevice is suspended";
|
cControl::Launch(new cSoftHdControl);
|
||||||
|
cControl::Attach();
|
||||||
|
Suspend(ConfigSuspendClose, ConfigSuspendClose, ConfigSuspendX11);
|
||||||
|
SuspendMode = SUSPEND_NORMAL;
|
||||||
|
return "SoftHdDevice is suspended";
|
||||||
}
|
}
|
||||||
if (!strcasecmp(command, "RESU")) {
|
if (!strcasecmp(command, "RESU")) {
|
||||||
if (SuspendMode == NOT_SUSPENDED) {
|
if (SuspendMode == NOT_SUSPENDED) {
|
||||||
return "SoftHdDevice already resumed";
|
return "SoftHdDevice already resumed";
|
||||||
}
|
}
|
||||||
if (SuspendMode != SUSPEND_NORMAL) {
|
if (SuspendMode != SUSPEND_NORMAL) {
|
||||||
return "can't resume SoftHdDevice";
|
return "can't resume SoftHdDevice";
|
||||||
}
|
}
|
||||||
if (ShutdownHandler.GetUserInactiveTime()) {
|
if (ShutdownHandler.GetUserInactiveTime()) {
|
||||||
ShutdownHandler.SetUserInactiveTimeout();
|
ShutdownHandler.SetUserInactiveTimeout();
|
||||||
}
|
}
|
||||||
if (cSoftHdControl::Player) { // suspended
|
if (cSoftHdControl::Player) { // suspended
|
||||||
cControl::Shutdown(); // not need, if not suspended
|
cControl::Shutdown(); // not need, if not suspended
|
||||||
}
|
}
|
||||||
Resume();
|
Resume();
|
||||||
SuspendMode = NOT_SUSPENDED;
|
SuspendMode = NOT_SUSPENDED;
|
||||||
return "SoftHdDevice is resumed";
|
return "SoftHdDevice is resumed";
|
||||||
}
|
}
|
||||||
if (!strcasecmp(command, "DETA")) {
|
if (!strcasecmp(command, "DETA")) {
|
||||||
if (SuspendMode == SUSPEND_DETACHED) {
|
if (SuspendMode == SUSPEND_DETACHED) {
|
||||||
return "SoftHdDevice already detached";
|
return "SoftHdDevice already detached";
|
||||||
}
|
}
|
||||||
if (cSoftHdControl::Player) { // already suspended
|
if (cSoftHdControl::Player) { // already suspended
|
||||||
return "can't suspend SoftHdDevice already suspended";
|
return "can't suspend SoftHdDevice already suspended";
|
||||||
}
|
}
|
||||||
cControl::Launch(new cSoftHdControl);
|
|
||||||
cControl::Attach();
|
|
||||||
Suspend(1, 1, 0);
|
|
||||||
SuspendMode = SUSPEND_DETACHED;
|
|
||||||
#ifdef USE_OPENGLOSD
|
#ifdef USE_OPENGLOSD
|
||||||
dsyslog("[softhddev]stopping Ogl Thread svdrp DETA");
|
dsyslog("[softhddev]stopping Ogl Thread svdrp DETA");
|
||||||
cSoftOsdProvider::StopOpenGlThread();
|
cSoftOsdProvider::StopOpenGlThread();
|
||||||
#endif
|
#endif
|
||||||
return "SoftHdDevice is detached";
|
cControl::Launch(new cSoftHdControl);
|
||||||
|
cControl::Attach();
|
||||||
|
Suspend(1, 1, 0);
|
||||||
|
SuspendMode = SUSPEND_DETACHED;
|
||||||
|
return "SoftHdDevice is detached";
|
||||||
}
|
}
|
||||||
if (!strcasecmp(command, "ATTA")) {
|
if (!strcasecmp(command, "ATTA")) {
|
||||||
char *tmp;
|
char *tmp;
|
||||||
char *t;
|
char *t;
|
||||||
char *s;
|
char *s;
|
||||||
char *o;
|
char *o;
|
||||||
|
|
||||||
if (SuspendMode != SUSPEND_DETACHED) {
|
if (SuspendMode != SUSPEND_DETACHED) {
|
||||||
return "can't attach SoftHdDevice not detached";
|
return "can't attach SoftHdDevice not detached";
|
||||||
}
|
|
||||||
if (!(tmp = strdup(option))) {
|
|
||||||
return "out of memory";
|
|
||||||
}
|
|
||||||
t = tmp;
|
|
||||||
while ((s = strsep(&t, " \t\n\r"))) {
|
|
||||||
if (!strcmp(s, "-d")) {
|
|
||||||
if (!(o = strsep(&t, " \t\n\r"))) {
|
|
||||||
free(tmp);
|
|
||||||
return "missing option argument";
|
|
||||||
}
|
}
|
||||||
free(ConfigX11Display);
|
if (!(tmp = strdup(option))) {
|
||||||
ConfigX11Display = strdup(o);
|
return "out of memory";
|
||||||
X11DisplayName = ConfigX11Display;
|
|
||||||
} else if (!strncmp(s, "-d", 2)) {
|
|
||||||
free(ConfigX11Display);
|
|
||||||
ConfigX11Display = strdup(s + 2);
|
|
||||||
X11DisplayName = ConfigX11Display;
|
|
||||||
|
|
||||||
} else if (!strcmp(s, "-a")) {
|
|
||||||
if (!(o = strsep(&t, " \t\n\r"))) {
|
|
||||||
free(tmp);
|
|
||||||
return "missing option argument";
|
|
||||||
}
|
}
|
||||||
free(ConfigAudioDevice);
|
t = tmp;
|
||||||
ConfigAudioDevice = strdup(o);
|
while ((s = strsep(&t, " \t\n\r"))) {
|
||||||
AudioSetDevice(ConfigAudioDevice);
|
if (!strcmp(s, "-d")) {
|
||||||
} else if (!strncmp(s, "-a", 2)) {
|
if (!(o = strsep(&t, " \t\n\r"))) {
|
||||||
free(ConfigAudioDevice);
|
free(tmp);
|
||||||
ConfigAudioDevice = strdup(s + 2);
|
return "missing option argument";
|
||||||
AudioSetDevice(ConfigAudioDevice);
|
}
|
||||||
|
free(ConfigX11Display);
|
||||||
|
ConfigX11Display = strdup(o);
|
||||||
|
X11DisplayName = ConfigX11Display;
|
||||||
|
} else if (!strncmp(s, "-d", 2)) {
|
||||||
|
free(ConfigX11Display);
|
||||||
|
ConfigX11Display = strdup(s + 2);
|
||||||
|
X11DisplayName = ConfigX11Display;
|
||||||
|
|
||||||
} else if (!strcmp(s, "-p")) {
|
} else if (!strcmp(s, "-a")) {
|
||||||
if (!(o = strsep(&t, " \t\n\r"))) {
|
if (!(o = strsep(&t, " \t\n\r"))) {
|
||||||
free(tmp);
|
free(tmp);
|
||||||
return "missing option argument";
|
return "missing option argument";
|
||||||
|
}
|
||||||
|
free(ConfigAudioDevice);
|
||||||
|
ConfigAudioDevice = strdup(o);
|
||||||
|
AudioSetDevice(ConfigAudioDevice);
|
||||||
|
} else if (!strncmp(s, "-a", 2)) {
|
||||||
|
free(ConfigAudioDevice);
|
||||||
|
ConfigAudioDevice = strdup(s + 2);
|
||||||
|
AudioSetDevice(ConfigAudioDevice);
|
||||||
|
|
||||||
|
} else if (!strcmp(s, "-p")) {
|
||||||
|
if (!(o = strsep(&t, " \t\n\r"))) {
|
||||||
|
free(tmp);
|
||||||
|
return "missing option argument";
|
||||||
|
}
|
||||||
|
free(ConfigPassthroughDevice);
|
||||||
|
ConfigPassthroughDevice = strdup(o);
|
||||||
|
AudioSetPassthroughDevice(ConfigPassthroughDevice);
|
||||||
|
} else if (!strncmp(s, "-p", 2)) {
|
||||||
|
free(ConfigPassthroughDevice);
|
||||||
|
ConfigPassthroughDevice = strdup(s + 2);
|
||||||
|
AudioSetPassthroughDevice(ConfigPassthroughDevice);
|
||||||
|
|
||||||
|
} else if (*s) {
|
||||||
|
free(tmp);
|
||||||
|
return "unsupported option";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
free(ConfigPassthroughDevice);
|
|
||||||
ConfigPassthroughDevice = strdup(o);
|
|
||||||
AudioSetPassthroughDevice(ConfigPassthroughDevice);
|
|
||||||
} else if (!strncmp(s, "-p", 2)) {
|
|
||||||
free(ConfigPassthroughDevice);
|
|
||||||
ConfigPassthroughDevice = strdup(s + 2);
|
|
||||||
AudioSetPassthroughDevice(ConfigPassthroughDevice);
|
|
||||||
|
|
||||||
} else if (*s) {
|
|
||||||
free(tmp);
|
free(tmp);
|
||||||
return "unsupported option";
|
if (ShutdownHandler.GetUserInactiveTime()) {
|
||||||
}
|
ShutdownHandler.SetUserInactiveTimeout();
|
||||||
}
|
}
|
||||||
free(tmp);
|
if (cSoftHdControl::Player) { // suspended
|
||||||
if (ShutdownHandler.GetUserInactiveTime()) {
|
cControl::Shutdown(); // not need, if not suspended
|
||||||
ShutdownHandler.SetUserInactiveTimeout();
|
}
|
||||||
}
|
Resume();
|
||||||
if (cSoftHdControl::Player) { // suspended
|
SuspendMode = NOT_SUSPENDED;
|
||||||
cControl::Shutdown(); // not need, if not suspended
|
return "SoftHdDevice is attached";
|
||||||
}
|
|
||||||
Resume();
|
|
||||||
SuspendMode = NOT_SUSPENDED;
|
|
||||||
return "SoftHdDevice is attached";
|
|
||||||
}
|
}
|
||||||
if (!strcasecmp(command, "HOTK")) {
|
if (!strcasecmp(command, "HOTK")) {
|
||||||
int hotk;
|
int hotk;
|
||||||
|
|
||||||
hotk = strtol(option, NULL, 0);
|
hotk = strtol(option, NULL, 0);
|
||||||
HandleHotkey(hotk);
|
HandleHotkey(hotk);
|
||||||
return "hot-key executed";
|
return "hot-key executed";
|
||||||
}
|
}
|
||||||
if (!strcasecmp(command, "PRIM")) {
|
if (!strcasecmp(command, "PRIM")) {
|
||||||
int primary;
|
int primary;
|
||||||
|
|
||||||
primary = strtol(option, NULL, 0);
|
primary = strtol(option, NULL, 0);
|
||||||
if (!primary && MyDevice) {
|
if (!primary && MyDevice) {
|
||||||
primary = MyDevice->DeviceNumber() + 1;
|
primary = MyDevice->DeviceNumber() + 1;
|
||||||
}
|
}
|
||||||
dsyslog("[softhddev] switching primary device to %d\n", primary);
|
dsyslog("[softhddev] switching primary device to %d\n", primary);
|
||||||
DoMakePrimary = primary;
|
DoMakePrimary = primary;
|
||||||
return "switching primary device requested";
|
return "switching primary device requested";
|
||||||
}
|
}
|
||||||
if (!strcasecmp(command, "3DOF")) {
|
if (!strcasecmp(command, "3DOF")) {
|
||||||
VideoSetOsd3DMode(0);
|
VideoSetOsd3DMode(0);
|
||||||
return "3d off";
|
return "3d off";
|
||||||
}
|
}
|
||||||
if (!strcasecmp(command, "3DSB")) {
|
if (!strcasecmp(command, "3DSB")) {
|
||||||
VideoSetOsd3DMode(1);
|
VideoSetOsd3DMode(1);
|
||||||
return "3d sbs";
|
return "3d sbs";
|
||||||
}
|
}
|
||||||
if (!strcasecmp(command, "3DTB")) {
|
if (!strcasecmp(command, "3DTB")) {
|
||||||
VideoSetOsd3DMode(2);
|
VideoSetOsd3DMode(2);
|
||||||
return "3d tb";
|
return "3d tb";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcasecmp(command, "RAIS")) {
|
if (!strcasecmp(command, "RAIS")) {
|
||||||
if (!ConfigStartX11Server) {
|
if (!ConfigStartX11Server) {
|
||||||
VideoRaiseWindow();
|
VideoRaiseWindow();
|
||||||
} else {
|
} else {
|
||||||
return "Raise not possible";
|
return "Raise not possible";
|
||||||
}
|
}
|
||||||
return "Window raised";
|
return "Window raised";
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
36
video.c
36
video.c
@ -633,8 +633,8 @@ static void VideoUpdateOutput(AVRational input_aspect_ratio, int input_width,
|
|||||||
normal:
|
normal:
|
||||||
*output_x = video_x;
|
*output_x = video_x;
|
||||||
*output_y = video_y;
|
*output_y = video_y;
|
||||||
*output_width = (video_height * display_aspect_ratio.num + display_aspect_ratio.den ) / display_aspect_ratio.den;
|
*output_width = (video_height * display_aspect_ratio.num + display_aspect_ratio.den -1 ) / display_aspect_ratio.den;
|
||||||
*output_height = (video_width * display_aspect_ratio.den + display_aspect_ratio.num ) / display_aspect_ratio.num;
|
*output_height = (video_width * display_aspect_ratio.den + display_aspect_ratio.num -1 ) / display_aspect_ratio.num;
|
||||||
// JOJO hier stimmt was nicht
|
// JOJO hier stimmt was nicht
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
*output_width = video_width;
|
*output_width = video_width;
|
||||||
@ -866,6 +866,7 @@ static void GlxUploadOsdTexture(int x, int y, int width, int height,
|
|||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
glDisable(GL_TEXTURE_2D);
|
glDisable(GL_TEXTURE_2D);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@ -887,11 +888,11 @@ static void GlxOsdInit(int width, int height)
|
|||||||
|
|
||||||
Debug(3, "video/glx: osd init context %p <-> %p\n", glXGetCurrentContext(), GlxContext);
|
Debug(3, "video/glx: osd init context %p <-> %p\n", glXGetCurrentContext(), GlxContext);
|
||||||
|
|
||||||
|
#ifndef USE_OPENGLOSD
|
||||||
//
|
//
|
||||||
// create a RGBA texture.
|
// create a RGBA texture.
|
||||||
//
|
//
|
||||||
glEnable(GL_TEXTURE_2D); // create 2d texture(s)
|
glEnable(GL_TEXTURE_2D); // create 2d texture(s)
|
||||||
|
|
||||||
glGenTextures(2, OsdGlTextures);
|
glGenTextures(2, OsdGlTextures);
|
||||||
for (i = 0; i < 2; ++i) {
|
for (i = 0; i < 2; ++i) {
|
||||||
glBindTexture(GL_TEXTURE_2D, OsdGlTextures[i]);
|
glBindTexture(GL_TEXTURE_2D, OsdGlTextures[i]);
|
||||||
@ -901,11 +902,12 @@ static void GlxOsdInit(int width, int height)
|
|||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
glDisable(GL_TEXTURE_2D);
|
glDisable(GL_TEXTURE_2D);
|
||||||
|
#else
|
||||||
|
OsdGlTextures[0] = 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@ -914,6 +916,7 @@ static void GlxOsdInit(int width, int height)
|
|||||||
static void GlxOsdExit(void)
|
static void GlxOsdExit(void)
|
||||||
{
|
{
|
||||||
if (OsdGlTextures[0]) {
|
if (OsdGlTextures[0]) {
|
||||||
|
glXMakeCurrent(XlibDisplay, VideoWindow, GlxContext );
|
||||||
glDeleteTextures(2, OsdGlTextures);
|
glDeleteTextures(2, OsdGlTextures);
|
||||||
OsdGlTextures[0] = 0;
|
OsdGlTextures[0] = 0;
|
||||||
OsdGlTextures[1] = 0;
|
OsdGlTextures[1] = 0;
|
||||||
@ -4878,18 +4881,14 @@ static void VideoCreateWindow(xcb_window_t parent, xcb_visualid_t visual,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// FIXME: size hints
|
// FIXME: size hints
|
||||||
|
#if 0
|
||||||
// register interest in the delete window message
|
// register interest in the delete window message
|
||||||
if ((reply =
|
if ((reply =
|
||||||
xcb_intern_atom_reply(Connection, xcb_intern_atom(Connection, 0,
|
xcb_intern_atom_reply(Connection, xcb_intern_atom(Connection, 0, sizeof("WM_DELETE_WINDOW") - 1, "WM_DELETE_WINDOW"),NULL))) {
|
||||||
sizeof("WM_DELETE_WINDOW") - 1, "WM_DELETE_WINDOW"),
|
|
||||||
NULL))) {
|
|
||||||
WmDeleteWindowAtom = reply->atom;
|
WmDeleteWindowAtom = reply->atom;
|
||||||
free(reply);
|
free(reply);
|
||||||
if ((reply =
|
if ((reply =
|
||||||
xcb_intern_atom_reply(Connection, xcb_intern_atom(Connection,
|
xcb_intern_atom_reply(Connection, xcb_intern_atom(Connection,0, sizeof("WM_PROTOCOLS") - 1, "WM_PROTOCOLS"),NULL))) {
|
||||||
0, sizeof("WM_PROTOCOLS") - 1, "WM_PROTOCOLS"),
|
|
||||||
NULL))) {
|
|
||||||
#ifdef XCB_ICCCM_NUM_WM_SIZE_HINTS_ELEMENTS
|
#ifdef XCB_ICCCM_NUM_WM_SIZE_HINTS_ELEMENTS
|
||||||
xcb_icccm_set_wm_protocols(Connection, VideoWindow, reply->atom, 1,&WmDeleteWindowAtom);
|
xcb_icccm_set_wm_protocols(Connection, VideoWindow, reply->atom, 1,&WmDeleteWindowAtom);
|
||||||
#endif
|
#endif
|
||||||
@ -4899,6 +4898,7 @@ static void VideoCreateWindow(xcb_window_t parent, xcb_visualid_t visual,
|
|||||||
free(reply);
|
free(reply);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
//
|
//
|
||||||
// prepare fullscreen.
|
// prepare fullscreen.
|
||||||
//
|
//
|
||||||
@ -5439,7 +5439,11 @@ void VideoInit(const char *display_name)
|
|||||||
Debug(3, "video: x11 already setup\n");
|
Debug(3, "video: x11 already setup\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#ifdef USE_GLX
|
||||||
|
if (!XInitThreads()) {
|
||||||
|
Error(_("video: Can't initialize X11 thread support on '%s'\n"),display_name);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
// Open the connection to the X server.
|
// Open the connection to the X server.
|
||||||
// use the DISPLAY environment variable as the default display name
|
// use the DISPLAY environment variable as the default display name
|
||||||
if (!display_name && !(display_name = getenv("DISPLAY"))) {
|
if (!display_name && !(display_name = getenv("DISPLAY"))) {
|
||||||
@ -5451,11 +5455,7 @@ void VideoInit(const char *display_name)
|
|||||||
// FIXME: we need to retry connection
|
// FIXME: we need to retry connection
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#ifdef USE_GLX
|
|
||||||
if (!XInitThreads()) {
|
|
||||||
Error(_("video: Can't initialize X11 thread support on '%s'\n"),display_name);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
// Register error handler
|
// Register error handler
|
||||||
XSetIOErrorHandler(VideoIOErrorHandler);
|
XSetIOErrorHandler(VideoIOErrorHandler);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user