mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-10 08:38:20 +00:00
[common] moved linux agnostic code into the common library
This commit is contained in:
parent
0c6ff6822d
commit
1c1d2a0568
@ -20,6 +20,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "interface/capture.h"
|
||||
#include "interface/platform.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/event.h"
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
@ -37,7 +38,7 @@ struct xcb
|
||||
uint32_t seg;
|
||||
int shmID;
|
||||
void * data;
|
||||
osEventHandle * frameEvent;
|
||||
LGEvent * frameEvent;
|
||||
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
@ -67,7 +68,7 @@ static bool xcb_create()
|
||||
this = (struct xcb *)calloc(sizeof(struct xcb), 1);
|
||||
this->shmID = -1;
|
||||
this->data = (void *)-1;
|
||||
this->frameEvent = os_createEvent(true);
|
||||
this->frameEvent = lgCreateEvent(true, 20);
|
||||
|
||||
if (!this->frameEvent)
|
||||
{
|
||||
@ -84,7 +85,7 @@ static bool xcb_init()
|
||||
assert(this);
|
||||
assert(!this->initialized);
|
||||
|
||||
os_resetEvent(this->frameEvent);
|
||||
lgResetEvent(this->frameEvent);
|
||||
|
||||
this->xcb = xcb_connect(NULL, NULL);
|
||||
if (!this->xcb || xcb_connection_has_error(this->xcb))
|
||||
@ -158,7 +159,7 @@ static bool xcb_deinit()
|
||||
|
||||
static void xcb_free()
|
||||
{
|
||||
os_freeEvent(this->frameEvent);
|
||||
lgFreeEvent(this->frameEvent);
|
||||
free(this);
|
||||
this = NULL;
|
||||
}
|
||||
@ -187,20 +188,29 @@ static CaptureResult xcb_capture()
|
||||
0);
|
||||
|
||||
this->hasFrame = true;
|
||||
os_signalEvent(this->frameEvent);
|
||||
lgSignalEvent(this->frameEvent);
|
||||
}
|
||||
|
||||
return CAPTURE_RESULT_OK;
|
||||
}
|
||||
|
||||
static CaptureResult xcb_getFrame(CaptureFrame * frame)
|
||||
static CaptureResult xcb_waitFrame(CaptureFrame * frame)
|
||||
{
|
||||
lgWaitEvent(this->frameEvent, TIMEOUT_INFINITE);
|
||||
|
||||
frame->width = this->width;
|
||||
frame->height = this->height;
|
||||
frame->pitch = this->width * 4;
|
||||
frame->stride = this->width;
|
||||
frame->format = CAPTURE_FMT_BGRA;
|
||||
|
||||
return CAPTURE_RESULT_OK;
|
||||
}
|
||||
|
||||
static CaptureResult xcb_getFrame(FrameBuffer frame)
|
||||
{
|
||||
assert(this);
|
||||
assert(this->initialized);
|
||||
assert(frame);
|
||||
assert(frame->data);
|
||||
|
||||
os_waitEvent(this->frameEvent, TIMEOUT_INFINITE);
|
||||
|
||||
xcb_shm_get_image_reply_t * img;
|
||||
img = xcb_shm_get_image_reply(this->xcb, this->imgC, NULL);
|
||||
@ -210,12 +220,7 @@ static CaptureResult xcb_getFrame(CaptureFrame * frame)
|
||||
return CAPTURE_RESULT_ERROR;
|
||||
}
|
||||
|
||||
frame->width = this->width;
|
||||
frame->height = this->height;
|
||||
frame->pitch = this->width * 4;
|
||||
frame->stride = this->width;
|
||||
frame->format = CAPTURE_FMT_BGRA;
|
||||
memcpy(frame->data, this->data, this->width * this->height * 4);
|
||||
framebuffer_write(frame, this->data, this->width * this->height * 4);
|
||||
free(img);
|
||||
|
||||
this->hasFrame = false;
|
||||
@ -237,6 +242,7 @@ struct CaptureInterface Capture_XCB =
|
||||
.free = xcb_free,
|
||||
.getMaxFrameSize = xcb_getMaxFrameSize,
|
||||
.capture = xcb_capture,
|
||||
.waitFrame = xcb_waitFrame,
|
||||
.getFrame = xcb_getFrame,
|
||||
.getPointer = xcb_getPointer
|
||||
};
|
@ -20,6 +20,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "interface/platform.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/option.h"
|
||||
#include "common/thread.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <getopt.h>
|
||||
@ -44,15 +45,6 @@ struct app
|
||||
|
||||
static struct app app;
|
||||
|
||||
struct osThreadHandle
|
||||
{
|
||||
const char * name;
|
||||
osThreadFunction function;
|
||||
void * opaque;
|
||||
pthread_t handle;
|
||||
int resultCode;
|
||||
};
|
||||
|
||||
void sigHandler(int signo)
|
||||
{
|
||||
DEBUG_INFO("SIGINT");
|
||||
@ -269,185 +261,3 @@ void os_shmemUnmap()
|
||||
munmap(app.shmMap, app.shmSize);
|
||||
app.shmMap = MAP_FAILED;
|
||||
}
|
||||
|
||||
static void * threadWrapper(void * opaque)
|
||||
{
|
||||
osThreadHandle * handle = (osThreadHandle *)opaque;
|
||||
handle->resultCode = handle->function(handle->opaque);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool os_createThread(const char * name, osThreadFunction function, void * opaque, osThreadHandle ** handle)
|
||||
{
|
||||
*handle = (osThreadHandle*)malloc(sizeof(osThreadHandle));
|
||||
(*handle)->name = name;
|
||||
(*handle)->function = function;
|
||||
(*handle)->opaque = opaque;
|
||||
|
||||
if (pthread_create(&(*handle)->handle, NULL, threadWrapper, *handle) != 0)
|
||||
{
|
||||
DEBUG_ERROR("pthread_create failed for thread: %s", name);
|
||||
free(*handle);
|
||||
*handle = NULL;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool os_joinThread(osThreadHandle * handle, int * resultCode)
|
||||
{
|
||||
if (pthread_join(handle->handle, NULL) != 0)
|
||||
{
|
||||
DEBUG_ERROR("pthread_join failed for thread: %s", handle->name);
|
||||
free(handle);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (resultCode)
|
||||
*resultCode = handle->resultCode;
|
||||
|
||||
free(handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
struct osEventHandle
|
||||
{
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
bool flag;
|
||||
bool autoReset;
|
||||
};
|
||||
|
||||
osEventHandle * os_createEvent(bool autoReset)
|
||||
{
|
||||
osEventHandle * handle = (osEventHandle *)calloc(sizeof(osEventHandle), 1);
|
||||
if (!handle)
|
||||
{
|
||||
DEBUG_ERROR("Failed to allocate memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pthread_mutex_init(&handle->mutex, NULL) != 0)
|
||||
{
|
||||
DEBUG_ERROR("Failed to create the mutex");
|
||||
free(handle);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pthread_cond_init(&handle->cond, NULL) != 0)
|
||||
{
|
||||
pthread_mutex_destroy(&handle->mutex);
|
||||
free(handle);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
handle->autoReset = autoReset;
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
void os_freeEvent(osEventHandle * handle)
|
||||
{
|
||||
assert(handle);
|
||||
|
||||
pthread_cond_destroy (&handle->cond );
|
||||
pthread_mutex_destroy(&handle->mutex);
|
||||
free(handle);
|
||||
}
|
||||
|
||||
bool os_waitEvent(osEventHandle * handle, unsigned int timeout)
|
||||
{
|
||||
assert(handle);
|
||||
|
||||
if (pthread_mutex_lock(&handle->mutex) != 0)
|
||||
{
|
||||
DEBUG_ERROR("Failed to lock the mutex");
|
||||
return false;
|
||||
}
|
||||
|
||||
while(!handle->flag)
|
||||
{
|
||||
if (timeout == TIMEOUT_INFINITE)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (handle->autoReset)
|
||||
handle->flag = false;
|
||||
|
||||
if (pthread_mutex_unlock(&handle->mutex) != 0)
|
||||
{
|
||||
DEBUG_ERROR("Failed to unlock the mutex");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool os_signalEvent(osEventHandle * handle)
|
||||
{
|
||||
assert(handle);
|
||||
|
||||
if (pthread_mutex_lock(&handle->mutex) != 0)
|
||||
{
|
||||
DEBUG_ERROR("Failed to lock the mutex");
|
||||
return false;
|
||||
}
|
||||
|
||||
handle->flag = true;
|
||||
|
||||
if (pthread_mutex_unlock(&handle->mutex) != 0)
|
||||
{
|
||||
DEBUG_ERROR("Failed to unlock the mutex");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pthread_cond_signal(&handle->cond) != 0)
|
||||
{
|
||||
DEBUG_ERROR("Failed to signal the condition");
|
||||
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;
|
||||
}
|
@ -8,4 +8,10 @@ include_directories(
|
||||
add_library(lg_common_platform_code STATIC
|
||||
crash.c
|
||||
sysinfo.c
|
||||
thread.c
|
||||
event.c
|
||||
)
|
||||
|
||||
if(ENABLE_BACKTRACE)
|
||||
target_link_libraries(lg_common_platform_code bfd)
|
||||
endif()
|
||||
|
169
common/src/platform/linux/event.c
Normal file
169
common/src/platform/linux/event.c
Normal file
@ -0,0 +1,169 @@
|
||||
/*
|
||||
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||
Copyright (C) 2017-2019 Geoffrey McRae <geoff@hostfission.com>
|
||||
https://looking-glass.hostfission.com
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "common/event.h"
|
||||
|
||||
#include "common/debug.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
struct LGEvent
|
||||
{
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
bool flag;
|
||||
bool autoReset;
|
||||
};
|
||||
|
||||
LGEvent * lgCreateEvent(bool autoReset, unsigned int msSpinTime)
|
||||
{
|
||||
LGEvent * handle = (LGEvent *)calloc(sizeof(LGEvent), 1);
|
||||
if (!handle)
|
||||
{
|
||||
DEBUG_ERROR("Failed to allocate memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pthread_mutex_init(&handle->mutex, NULL) != 0)
|
||||
{
|
||||
DEBUG_ERROR("Failed to create the mutex");
|
||||
free(handle);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pthread_cond_init(&handle->cond, NULL) != 0)
|
||||
{
|
||||
pthread_mutex_destroy(&handle->mutex);
|
||||
free(handle);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
handle->autoReset = autoReset;
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
void lgFreeEvent(LGEvent * handle)
|
||||
{
|
||||
assert(handle);
|
||||
|
||||
pthread_cond_destroy (&handle->cond );
|
||||
pthread_mutex_destroy(&handle->mutex);
|
||||
free(handle);
|
||||
}
|
||||
|
||||
bool lgWaitEvent(LGEvent * handle, unsigned int timeout)
|
||||
{
|
||||
assert(handle);
|
||||
|
||||
if (pthread_mutex_lock(&handle->mutex) != 0)
|
||||
{
|
||||
DEBUG_ERROR("Failed to lock the mutex");
|
||||
return false;
|
||||
}
|
||||
|
||||
while(!handle->flag)
|
||||
{
|
||||
if (timeout == TIMEOUT_INFINITE)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (handle->autoReset)
|
||||
handle->flag = false;
|
||||
|
||||
if (pthread_mutex_unlock(&handle->mutex) != 0)
|
||||
{
|
||||
DEBUG_ERROR("Failed to unlock the mutex");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool lgSignalEvent(LGEvent * handle)
|
||||
{
|
||||
assert(handle);
|
||||
|
||||
if (pthread_mutex_lock(&handle->mutex) != 0)
|
||||
{
|
||||
DEBUG_ERROR("Failed to lock the mutex");
|
||||
return false;
|
||||
}
|
||||
|
||||
handle->flag = true;
|
||||
|
||||
if (pthread_mutex_unlock(&handle->mutex) != 0)
|
||||
{
|
||||
DEBUG_ERROR("Failed to unlock the mutex");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pthread_cond_signal(&handle->cond) != 0)
|
||||
{
|
||||
DEBUG_ERROR("Failed to signal the condition");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool lgResetEvent(LGEvent * 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;
|
||||
}
|
74
common/src/platform/linux/thread.c
Normal file
74
common/src/platform/linux/thread.c
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
Looking Glass - KVM FrameRelay (KVMFR) Client
|
||||
Copyright (C) 2017-2020 Geoffrey McRae <geoff@hostfission.com>
|
||||
https://looking-glass.hostfission.com
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "common/thread.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "common/debug.h"
|
||||
|
||||
struct LGThread
|
||||
{
|
||||
const char * name;
|
||||
LGThreadFunction function;
|
||||
void * opaque;
|
||||
pthread_t handle;
|
||||
int resultCode;
|
||||
};
|
||||
|
||||
static void * threadWrapper(void * opaque)
|
||||
{
|
||||
LGThread * handle = (LGThread *)opaque;
|
||||
handle->resultCode = handle->function(handle->opaque);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool lgCreateThread(const char * name, LGThreadFunction function, void * opaque, LGThread ** handle)
|
||||
{
|
||||
*handle = (LGThread*)malloc(sizeof(LGThread));
|
||||
(*handle)->name = name;
|
||||
(*handle)->function = function;
|
||||
(*handle)->opaque = opaque;
|
||||
|
||||
if (pthread_create(&(*handle)->handle, NULL, threadWrapper, *handle) != 0)
|
||||
{
|
||||
DEBUG_ERROR("pthread_create failed for thread: %s", name);
|
||||
free(*handle);
|
||||
*handle = NULL;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool lgJoinThread(LGThread * handle, int * resultCode)
|
||||
{
|
||||
if (pthread_join(handle->handle, NULL) != 0)
|
||||
{
|
||||
DEBUG_ERROR("pthread_join failed for thread: %s", handle->name);
|
||||
free(handle);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (resultCode)
|
||||
*resultCode = handle->resultCode;
|
||||
|
||||
free(handle);
|
||||
return true;
|
||||
}
|
Loading…
Reference in New Issue
Block a user