diff --git a/c-host/linux/capture/xcb.c b/c-host/linux/capture/xcb.c index 866e2ad0..c65535f1 100644 --- a/c-host/linux/capture/xcb.c +++ b/c-host/linux/capture/xcb.c @@ -19,6 +19,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA #include "capture/interface.h" #include "debug.h" +#include "app.h" #include #include #include @@ -36,6 +37,7 @@ struct xcb uint32_t seg; int shmID; void * data; + osEventHandle * frameEvent; unsigned int width; unsigned int height; @@ -62,9 +64,18 @@ static const char * xcb_getName() static bool xcb_create() { assert(!this); - this = (struct xcb *)calloc(sizeof(struct xcb), 1); - this->shmID = -1; - this->data = (void *)-1; + this = (struct xcb *)calloc(sizeof(struct xcb), 1); + this->shmID = -1; + this->data = (void *)-1; + this->frameEvent = os_createEvent(true); + + if (!this->frameEvent) + { + DEBUG_ERROR("Failed to create the frame event"); + free(this); + return false; + } + return true; } @@ -73,6 +84,8 @@ static bool xcb_init() assert(this); assert(!this->initialized); + os_resetEvent(this->frameEvent); + this->xcb = xcb_connect(NULL, NULL); if (!this->xcb || xcb_connection_has_error(this->xcb)) { @@ -145,6 +158,7 @@ static bool xcb_deinit() static void xcb_free() { + os_freeEvent(this->frameEvent); free(this); this = NULL; } @@ -174,6 +188,7 @@ static CaptureResult xcb_capture(bool * hasFrameUpdate, bool * hasPointerUpdate) *hasFrameUpdate = true; this->hasFrame = true; + os_signalEvent(this->frameEvent); } return CAPTURE_RESULT_OK; @@ -186,11 +201,7 @@ static bool xcb_getFrame(CaptureFrame * frame) assert(frame); assert(frame->data); - if (!this->hasFrame) - { - DEBUG_ERROR("No frame to get"); - return false; - } + os_waitEvent(this->frameEvent, TIMEOUT_INFINITE); xcb_shm_get_image_reply_t * img; img = xcb_shm_get_image_reply(this->xcb, this->imgC, NULL); @@ -206,8 +217,8 @@ static bool xcb_getFrame(CaptureFrame * frame) frame->stride = this->width; frame->format = CAPTURE_FMT_BGRA; memcpy(frame->data, this->data, this->width * this->height * 4); - free(img); + this->hasFrame = false; return true; } diff --git a/c-host/linux/platform.c b/c-host/linux/platform.c index 38608b31..3ca5deb7 100644 --- a/c-host/linux/platform.c +++ b/c-host/linux/platform.c @@ -29,6 +29,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA #include #include #include +#include struct app { @@ -251,9 +252,10 @@ struct osEventHandle pthread_mutex_t mutex; pthread_cond_t cond; bool flag; + bool autoReset; }; -osEventHandle * os_createEvent() +osEventHandle * os_createEvent(bool autoReset) { osEventHandle * handle = (osEventHandle *)calloc(sizeof(osEventHandle), 1); if (!handle) @@ -276,6 +278,8 @@ osEventHandle * os_createEvent() return NULL; } + handle->autoReset = autoReset; + return handle; } @@ -288,7 +292,7 @@ void os_freeEvent(osEventHandle * handle) free(handle); } -bool os_waitEvent(osEventHandle * handle) +bool os_waitEvent(osEventHandle * handle, unsigned int timeout) { assert(handle); @@ -300,14 +304,33 @@ bool os_waitEvent(osEventHandle * handle) while(!handle->flag) { - if (pthread_cond_wait(&handle->cond, &handle->mutex) != 0) + if (timeout == TIMEOUT_INFINITE) { - DEBUG_ERROR("Wait to wait on the condition"); - return false; + if (pthread_cond_wait(&handle->cond, &handle->mutex) != 0) + { + DEBUG_ERROR("Wait to wait on the condition"); + return false; + } + } + else + { + struct timespec ts; + ts.tv_sec = timeout / 1000; + ts.tv_nsec = (timeout % 1000) * 1000000; + switch(pthread_cond_timedwait(&handle->cond, &handle->mutex, &ts)) + { + case ETIMEDOUT: + return false; + + default: + DEBUG_ERROR("Timed wait failed"); + return false; + } } } - handle->flag = false; + if (handle->autoReset) + handle->flag = false; if (pthread_mutex_unlock(&handle->mutex) != 0) { @@ -342,5 +365,26 @@ bool os_signalEvent(osEventHandle * handle) return false; } + return true; +} + +bool os_resetEvent(osEventHandle * handle) +{ + assert(handle); + + if (pthread_mutex_lock(&handle->mutex) != 0) + { + DEBUG_ERROR("Failed to lock the mutex"); + return false; + } + + handle->flag = false; + + if (pthread_mutex_unlock(&handle->mutex) != 0) + { + DEBUG_ERROR("Failed to unlock the mutex"); + return false; + } + return true; } \ No newline at end of file