aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api_example.c33
-rw-r--r--include/libsurvive/survive.h34
-rw-r--r--include/libsurvive/survive_api.h30
-rw-r--r--include/libsurvive/survive_types.h19
-rw-r--r--src/survive_api.c167
-rwxr-xr-xsrc/survive_cal.c1
-rw-r--r--src/survive_reproject.c2
-rw-r--r--winbuild/libsurvive.sln23
-rw-r--r--winbuild/libsurvive/libsurvive.vcxproj2
-rw-r--r--winbuild/libsurvive/libsurvive.vcxproj.filters6
10 files changed, 289 insertions, 28 deletions
diff --git a/api_example.c b/api_example.c
new file mode 100644
index 0000000..f2d9bd6
--- /dev/null
+++ b/api_example.c
@@ -0,0 +1,33 @@
+#include <stdio.h>
+#include <string.h>
+#include <survive_api.h>
+#include <os_generic.h>
+
+int main(int argc, char **argv) {
+ SurviveAsyncContext *actx = survive_asyc_init(argc, argv);
+ if (actx == 0) // implies -help or similiar
+ return 0;
+
+ survive_async_start_thread(actx);
+
+ while (survive_async_is_running(actx)) {
+ OGUSleep(30000);
+
+ SurvivePose pose;
+
+ for (const SurviveAsyncObject* it = survive_async_get_first_tracked(actx); it != 0; it = survive_async_get_next_tracked(actx, it)) {
+ uint32_t timecode = survive_async_object_get_latest_pose(it, &pose);
+ printf("%s (%u): %f %f %f %f %f %f %f\n", survive_async_object_name(it), timecode,
+ pose.Pos[0], pose.Pos[1], pose.Pos[2], pose.Rot[0], pose.Rot[1], pose.Rot[2], pose.Rot[3]);
+ }
+
+ OGUSleep(30000);
+ for (const SurviveAsyncObject* it = survive_async_get_next_updated(actx); it != 0; it = survive_async_get_next_updated(actx)) {
+ printf("%s changed since last checked\n", survive_async_object_name(it));
+ }
+
+ }
+
+ survive_async_close(actx);
+ return 0;
+}
diff --git a/include/libsurvive/survive.h b/include/libsurvive/survive.h
index 65343b7..52dcc0d 100644
--- a/include/libsurvive/survive.h
+++ b/include/libsurvive/survive.h
@@ -10,19 +10,13 @@
extern "C" {
#endif
-#ifdef _WIN32
-#define SURVIVE_EXPORT __declspec(dllexport)
-#else
-#define SURVIVE_EXPORT __attribute__((visibility("default")))
-#endif
-
/**
* This struct encodes what the last effective angles seen on a sensor were, and when they occured.
*/
typedef struct {
FLT angles[SENSORS_PER_OBJECT][NUM_LIGHTHOUSES][2]; // 2 Axes (Angles in LH space)
- uint32_t timecode[SENSORS_PER_OBJECT][NUM_LIGHTHOUSES][2]; // Timecode per axis in ticks
- uint32_t lengths[SENSORS_PER_OBJECT][NUM_LIGHTHOUSES][2]; // Timecode per axis in ticks
+ survive_timecode timecode[SENSORS_PER_OBJECT][NUM_LIGHTHOUSES][2]; // Timecode per axis in ticks
+ survive_timecode lengths[SENSORS_PER_OBJECT][NUM_LIGHTHOUSES][2]; // Timecode per axis in ticks
FLT accel[3];
FLT gyro[3];
@@ -43,15 +37,15 @@ void SurviveSensorActivations_add_imu(SurviveSensorActivations *self, struct Pos
* Returns true iff both angles for the given sensor and lighthouse were seen at most `tolerance` ticks before the given
* `timecode_now`.
*/
-bool SurviveSensorActivations_isPairValid(const SurviveSensorActivations *self, uint32_t tolerance,
- uint32_t timecode_now, uint32_t sensor_idx, int lh);
+bool SurviveSensorActivations_isPairValid(const SurviveSensorActivations *self, survive_timecode tolerance,
+ survive_timecode timecode_now, uint32_t sensor_idx, int lh);
/**
* Default tolerance that gives a somewhat accuate representation of current state.
*
* Don't rely on this to be a given value.
*/
-extern uint32_t SurviveSensorActivations_default_tolerance;
+extern survive_timecode SurviveSensorActivations_default_tolerance;
// DANGER: This structure may be redefined. Note that it is logically split into 64-bit chunks
// for optimization on 32- and 64-bit systems.
@@ -75,7 +69,7 @@ struct SurviveObject {
// Pose Information, also "poser" field.
FLT PoseConfidence; // 0..1
SurvivePose OutPose; // Final pose? (some day, one can dream!)
- uint32_t OutPose_timecode;
+ survive_timecode OutPose_timecode;
SurvivePose FromLHPose[NUM_LIGHTHOUSES]; // Filled out by poser, contains computed position from each lighthouse.
void *PoserData; // Initialized to zero, configured by poser, can be anything the poser wants.
PoserCB PoserFn;
@@ -101,11 +95,11 @@ struct SurviveObject {
int8_t oldcode;
int8_t sync_set_number; // 0 = master, 1 = slave, -1 = fault.
int8_t did_handle_ootx; // If unset, will send lightcap data for sync pulses next time a sensor is hit.
- uint32_t last_sync_time[NUM_LIGHTHOUSES];
- uint32_t last_sync_length[NUM_LIGHTHOUSES];
- uint32_t recent_sync_time;
+ survive_timecode last_sync_time[NUM_LIGHTHOUSES];
+ survive_timecode last_sync_length[NUM_LIGHTHOUSES];
+ survive_timecode recent_sync_time;
- uint32_t last_lighttime; // May be a 24- or 32- bit number depending on what device.
+ survive_timecode last_lighttime; // May be a 24- or 32- bit number depending on what device.
FLT *acc_bias; // size is FLT*3. contains x,y,z
FLT *acc_scale; // size is FLT*3. contains x,y,z
@@ -305,14 +299,14 @@ SURVIVE_EXPORT int survive_haptic(SurviveObject *so, uint8_t reserved, uint16_t
// Call these from your callback if overridden.
// Accept higher-level data.
SURVIVE_EXPORT void survive_default_light_process(SurviveObject *so, int sensor_id, int acode, int timeinsweep,
- uint32_t timecode, uint32_t length, uint32_t lh);
-SURVIVE_EXPORT void survive_default_imu_process(SurviveObject *so, int mode, FLT *accelgyro, uint32_t timecode, int id);
-SURVIVE_EXPORT void survive_default_angle_process(SurviveObject *so, int sensor_id, int acode, uint32_t timecode,
+ survive_timecode timecode, survive_timecode length, uint32_t lh);
+SURVIVE_EXPORT void survive_default_imu_process(SurviveObject *so, int mode, FLT *accelgyro, survive_timecode timecode, int id);
+SURVIVE_EXPORT void survive_default_angle_process(SurviveObject *so, int sensor_id, int acode, survive_timecode timecode,
FLT length, FLT angle, uint32_t lh);
SURVIVE_EXPORT void survive_default_button_process(SurviveObject *so, uint8_t eventType, uint8_t buttonId,
uint8_t axis1Id, uint16_t axis1Val, uint8_t axis2Id,
uint16_t axis2Val);
-SURVIVE_EXPORT void survive_default_raw_pose_process(SurviveObject *so, uint32_t timecode, SurvivePose *pose);
+SURVIVE_EXPORT void survive_default_raw_pose_process(SurviveObject *so, survive_timecode timecode, SurvivePose *pose);
SURVIVE_EXPORT void survive_default_lighthouse_pose_process(SurviveContext *ctx, uint8_t lighthouse,
SurvivePose *lh_pose, SurvivePose *obj_pose);
SURVIVE_EXPORT int survive_default_htc_config_process(SurviveObject *so, char *ct0conf, int len);
diff --git a/include/libsurvive/survive_api.h b/include/libsurvive/survive_api.h
new file mode 100644
index 0000000..30e30ac
--- /dev/null
+++ b/include/libsurvive/survive_api.h
@@ -0,0 +1,30 @@
+#include "survive_types.h"
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ struct SurviveAsyncContext;
+ typedef struct SurviveAsyncContext SurviveAsyncContext;
+
+ SURVIVE_EXPORT SurviveAsyncContext *survive_asyc_init(int argc, char *const *argv);
+ SURVIVE_EXPORT void survive_async_close(SurviveAsyncContext* actx);
+
+ SURVIVE_EXPORT void survive_async_start_thread(SurviveAsyncContext* actx);
+ SURVIVE_EXPORT int survive_async_stop_thread(SurviveAsyncContext* actx);
+ SURVIVE_EXPORT bool survive_async_is_running(SurviveAsyncContext* actx);
+
+ struct SurviveAsyncObject;
+ typedef struct SurviveAsyncObject SurviveAsyncObject;
+
+ SURVIVE_EXPORT const SurviveAsyncObject* survive_async_get_first_tracked(SurviveAsyncContext* actx);
+ SURVIVE_EXPORT const SurviveAsyncObject* survive_async_get_next_tracked(SurviveAsyncContext* actx, const SurviveAsyncObject* curr);
+ SURVIVE_EXPORT const SurviveAsyncObject* survive_async_get_next_updated(SurviveAsyncContext* actx);
+
+ SURVIVE_EXPORT survive_timecode survive_async_object_get_latest_pose(const SurviveAsyncObject* sao, SurvivePose* pose);
+ SURVIVE_EXPORT const char* survive_async_object_name(SurviveAsyncObject* sao);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/libsurvive/survive_types.h b/include/libsurvive/survive_types.h
index 367c391..b9d145f 100644
--- a/include/libsurvive/survive_types.h
+++ b/include/libsurvive/survive_types.h
@@ -4,6 +4,12 @@
#include "linmath.h"
#include "stdint.h"
+#ifdef _WIN32
+#define SURVIVE_EXPORT __declspec(dllexport)
+#else
+#define SURVIVE_EXPORT __attribute__((visibility("default")))
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -38,6 +44,8 @@ typedef LinmathPose SurvivePose;
#define BUTTON_EVENT_BUTTON_UP 2
#define BUTTON_EVENT_AXIS_CHANGED 3
+typedef uint32_t survive_timecode;
+
typedef struct SurviveObject SurviveObject;
typedef struct SurviveContext SurviveContext;
typedef struct BaseStationData BaseStationData;
@@ -45,13 +53,12 @@ typedef struct SurviveCalData SurviveCalData; //XXX Warning: This may be remov
typedef int (*htc_config_func)(SurviveObject *so, char *ct0conf, int len);
typedef void (*text_feedback_func)( SurviveContext * ctx, const char * fault );
-typedef void (*light_process_func)( SurviveObject * so, int sensor_id, int acode, int timeinsweep, uint32_t timecode, uint32_t length, uint32_t lighthouse);
-typedef void (*imu_process_func)( SurviveObject * so, int mask, FLT * accelgyro, uint32_t timecode, int id );
-typedef void (*angle_process_func)( SurviveObject * so, int sensor_id, int acode, uint32_t timecode, FLT length, FLT angle, uint32_t lh);
+typedef void (*light_process_func)( SurviveObject * so, int sensor_id, int acode, int timeinsweep, survive_timecode timecode, survive_timecode length, uint32_t lighthouse);
+typedef void (*imu_process_func)( SurviveObject * so, int mask, FLT * accelgyro, survive_timecode timecode, int id );
+typedef void (*angle_process_func)( SurviveObject * so, int sensor_id, int acode, survive_timecode timecode, FLT length, FLT angle, uint32_t lh);
typedef void(*button_process_func)(SurviveObject * so, uint8_t eventType, uint8_t buttonId, uint8_t axis1Id, uint16_t axis1Val, uint8_t axis2Id, uint16_t axis2Val);
-typedef void (*pose_func)(SurviveObject *so, uint32_t timecode, SurvivePose *pose);
-typedef void (*lighthouse_pose_func)(SurviveContext *ctx, uint8_t lighthouse, SurvivePose *lighthouse_pose,
- SurvivePose *object_pose);
+typedef void (*pose_func)(SurviveObject *so, survive_timecode timecode, SurvivePose *pose);
+typedef void (*lighthouse_pose_func)(SurviveContext *ctx, uint8_t lighthouse, SurvivePose *lighthouse_pose, SurvivePose *object_pose);
// For lightcap, etc. Don't change this structure at all. Regular vive is dependent on it being exactly as-is.
// When you write drivers, you can use this to send survive lightcap data.
diff --git a/src/survive_api.c b/src/survive_api.c
new file mode 100644
index 0000000..9883c9f
--- /dev/null
+++ b/src/survive_api.c
@@ -0,0 +1,167 @@
+#include "survive_api.h"
+#include "os_generic.h"
+#include "survive.h"
+#include "stdio.h"
+
+struct SurviveAsyncObject {
+ struct SurviveAsyncContext* actx;
+
+ enum SurviveAsyncObject_type {
+ SurviveAsyncObject_LIGHTHOUSE,
+ SurviveAsyncObject_OBJECT
+ } type;
+
+ union {
+ int lighthosue;
+ struct SurviveObject* so;
+ } data;
+
+ char name[32];
+ bool has_update;
+};
+
+struct SurviveAsyncContext {
+ SurviveContext* ctx;
+
+ bool running;
+ og_thread_t thread;
+ og_mutex_t poll_mutex;
+
+ size_t object_ct;
+ struct SurviveAsyncObject objects[];
+};
+
+static void pose_fn(SurviveObject *so, uint32_t timecode, SurvivePose *pose) {
+ survive_default_raw_pose_process(so, timecode, pose);
+
+ struct SurviveAsyncContext* actx = so->ctx->user_ptr;
+ int idx = so->user_ptr;
+ actx->objects[idx].has_update = true;
+}
+static void lh_fn(SurviveContext *ctx, uint8_t lighthouse, SurvivePose *lighthouse_pose,
+ SurvivePose *object_pose) {
+ survive_default_lighthouse_pose_process(ctx, lighthouse, lighthouse_pose, object_pose);
+
+ struct SurviveAsyncContext* actx = ctx->user_ptr;
+ actx->objects[lighthouse].has_update = true;
+}
+
+struct SurviveAsyncContext *survive_asyc_init(int argc, char *const *argv) {
+ SurviveContext* ctx = survive_init(argc, argv);
+ if (ctx == 0)
+ return 0;
+
+ survive_startup(ctx);
+
+ int object_ct = ctx->activeLighthouses + ctx->objs_ct;
+ struct SurviveAsyncContext * actx = calloc(1, sizeof(struct SurviveAsyncContext) + sizeof(struct SurviveAsyncObject) * object_ct );
+ actx->object_ct = object_ct;
+ actx->ctx = ctx;
+ actx->poll_mutex = OGCreateMutex();
+ ctx->user_ptr = actx;
+ int i = 0;
+ for (i = 0; i < ctx->activeLighthouses; i++) {
+ struct SurviveAsyncObject* obj = &actx->objects[i];
+ obj->data.lighthosue = i;
+ obj->type = SurviveAsyncObject_LIGHTHOUSE;
+ obj->actx = actx;
+ obj->has_update = ctx->bsd[i].PositionSet;
+ snprintf(obj->name, 32, "LH%d", i);
+ }
+ for (; i < object_ct; i++) {
+ struct SurviveAsyncObject* obj = &actx->objects[i];
+ int so_idx = i - ctx->activeLighthouses;
+ obj->data.so = ctx->objs[so_idx];
+ obj->type = SurviveAsyncObject_OBJECT;
+ obj->actx = actx;
+ obj->data.so->user_ptr = (void*)i;
+ snprintf(obj->name, 32, "%s", obj->data.so->codename);
+ }
+
+ survive_install_pose_fn(ctx, pose_fn);
+ survive_install_lighthouse_pose_fn(ctx, lh_fn);
+ return actx;
+}
+
+void survive_async_close(struct SurviveAsyncContext* actx) {
+ if (actx->running) {
+ survive_async_stop_thread(actx);
+ }
+
+ survive_close(actx->ctx);
+}
+
+static inline void* __async_thread(void* _actx) {
+ struct SurviveAsyncContext* actx = _actx;
+ int error = 0;
+ while (actx->running && error == 0) {
+ OGLockMutex(actx->poll_mutex);
+ error = survive_poll(actx->ctx);
+ OGUnlockMutex(actx->poll_mutex);
+ }
+ actx->running = false;
+ return (void*)error;
+}
+bool survive_async_is_running(struct SurviveAsyncContext* actx) {
+ return actx->running;
+}
+void survive_async_start_thread(struct SurviveAsyncContext* actx) {
+ actx->running = true;
+ actx->thread = OGCreateThread(__async_thread, actx);
+}
+int survive_async_stop_thread(struct SurviveAsyncContext* actx) {
+ actx->running = false;
+ int error = (int)OGJoinThread(actx->thread);
+ if (error != 0) {
+ SurviveContext* ctx = actx->ctx;
+ SV_INFO("Warning: Loope exited with error %d", error);
+ }
+ return error;
+}
+
+const struct SurviveAsyncObject* survive_async_get_next_tracked(struct SurviveAsyncContext* actx, const struct SurviveAsyncObject* curr) {
+ const struct SurviveAsyncObject* next = curr + 1;
+ if (next >= actx->objects + actx->object_ct)
+ return 0;
+ return next;
+}
+
+const struct SurviveAsyncObject* survive_async_get_first_tracked(struct SurviveAsyncContext* actx) {
+ return actx->objects;
+}
+
+const struct SurviveAsyncObject* survive_async_get_next_updated(struct SurviveAsyncContext* actx) {
+ for (int i = 0; i < actx->object_ct; i++) {
+ if (actx->objects[i].has_update) {
+ actx->objects[i].has_update = false;
+ return &actx->objects[i];
+ }
+ }
+ return 0;
+}
+
+uint32_t survive_async_object_get_latest_pose(const struct SurviveAsyncObject* sao, SurvivePose* pose) {
+ uint32_t timecode = 0;
+ OGLockMutex(sao->actx->poll_mutex);
+
+ switch (sao->type) {
+ case SurviveAsyncObject_LIGHTHOUSE: {
+ if(pose)
+ *pose = sao->actx->ctx->bsd[sao->data.lighthosue].Pose;
+ break;
+ }
+ case SurviveAsyncObject_OBJECT:
+ if(pose)
+ *pose = sao->data.so->OutPose;
+ timecode = sao->data.so->OutPose_timecode;
+ break;
+ }
+
+ OGUnlockMutex(sao->actx->poll_mutex);
+ return timecode;
+}
+
+const char * survive_async_object_name(const SurviveAsyncObject * sao)
+{
+ return sao->name;
+}
diff --git a/src/survive_cal.c b/src/survive_cal.c
index 3015b68..36e0a31 100755
--- a/src/survive_cal.c
+++ b/src/survive_cal.c
@@ -188,7 +188,6 @@ void survive_cal_install( struct SurviveContext * ctx )
}
}
- const char * DriverName;
cd->ConfigPoserFn = GetDriverByConfig(ctx, "Poser", "configposer", "SBA", 0);
ootx_packet_clbk = ootx_packet_clbk_d;
diff --git a/src/survive_reproject.c b/src/survive_reproject.c
index d6ba70b..8d8f0ed 100644
--- a/src/survive_reproject.c
+++ b/src/survive_reproject.c
@@ -99,5 +99,5 @@ void survive_apply_bsd_calibration(SurviveContext *ctx, int lh, const FLT *in, F
void survive_reproject_from_pose_with_config(const SurviveContext *ctx, struct survive_calibration_config *config,
int lighthouse, const SurvivePose *pose, FLT *point3d, FLT *out) {
- return survive_reproject_from_pose_with_bsd(&ctx->bsd[lighthouse], config, pose, point3d, out);
+ survive_reproject_from_pose_with_bsd(&ctx->bsd[lighthouse], config, pose, point3d, out);
}
diff --git a/winbuild/libsurvive.sln b/winbuild/libsurvive.sln
index b525975..1872a5a 100644
--- a/winbuild/libsurvive.sln
+++ b/winbuild/libsurvive.sln
@@ -11,6 +11,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "data_recorder", "data_recor
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test\test.vcxproj", "{EF083B79-F1D7-408A-9902-502B9A0639E0}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "simple_pose_test", "simple_pose_test\simple_pose_test.vcxproj", "{308708B5-DDC9-49EE-BF31-C83E187AFE15}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "api_example", "api_example\api_example.vcxproj", "{545316AE-4E07-49DD-A2B8-7A2DE9676EFF}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@@ -51,8 +55,27 @@ Global
{EF083B79-F1D7-408A-9902-502B9A0639E0}.Release|x64.Build.0 = Release|x64
{EF083B79-F1D7-408A-9902-502B9A0639E0}.Release|x86.ActiveCfg = Release|Win32
{EF083B79-F1D7-408A-9902-502B9A0639E0}.Release|x86.Build.0 = Release|Win32
+ {308708B5-DDC9-49EE-BF31-C83E187AFE15}.Debug|x64.ActiveCfg = Debug|x64
+ {308708B5-DDC9-49EE-BF31-C83E187AFE15}.Debug|x64.Build.0 = Debug|x64
+ {308708B5-DDC9-49EE-BF31-C83E187AFE15}.Debug|x86.ActiveCfg = Debug|Win32
+ {308708B5-DDC9-49EE-BF31-C83E187AFE15}.Debug|x86.Build.0 = Debug|Win32
+ {308708B5-DDC9-49EE-BF31-C83E187AFE15}.Release|x64.ActiveCfg = Release|x64
+ {308708B5-DDC9-49EE-BF31-C83E187AFE15}.Release|x64.Build.0 = Release|x64
+ {308708B5-DDC9-49EE-BF31-C83E187AFE15}.Release|x86.ActiveCfg = Release|Win32
+ {308708B5-DDC9-49EE-BF31-C83E187AFE15}.Release|x86.Build.0 = Release|Win32
+ {545316AE-4E07-49DD-A2B8-7A2DE9676EFF}.Debug|x64.ActiveCfg = Debug|x64
+ {545316AE-4E07-49DD-A2B8-7A2DE9676EFF}.Debug|x64.Build.0 = Debug|x64
+ {545316AE-4E07-49DD-A2B8-7A2DE9676EFF}.Debug|x86.ActiveCfg = Debug|Win32
+ {545316AE-4E07-49DD-A2B8-7A2DE9676EFF}.Debug|x86.Build.0 = Debug|Win32
+ {545316AE-4E07-49DD-A2B8-7A2DE9676EFF}.Release|x64.ActiveCfg = Release|x64
+ {545316AE-4E07-49DD-A2B8-7A2DE9676EFF}.Release|x64.Build.0 = Release|x64
+ {545316AE-4E07-49DD-A2B8-7A2DE9676EFF}.Release|x86.ActiveCfg = Release|Win32
+ {545316AE-4E07-49DD-A2B8-7A2DE9676EFF}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {EA7B8D68-188A-4190-B011-8A7F4EC52C38}
+ EndGlobalSection
EndGlobal
diff --git a/winbuild/libsurvive/libsurvive.vcxproj b/winbuild/libsurvive/libsurvive.vcxproj
index 4b76c99..85e9f5a 100644
--- a/winbuild/libsurvive/libsurvive.vcxproj
+++ b/winbuild/libsurvive/libsurvive.vcxproj
@@ -178,6 +178,7 @@
<ClCompile Include="..\..\src\poser_sba.c" />
<ClCompile Include="..\..\src\poser_turveytori.c" />
<ClCompile Include="..\..\src\survive.c" />
+ <ClCompile Include="..\..\src\survive_api.c" />
<ClCompile Include="..\..\src\survive_cal.c" />
<ClCompile Include="..\..\src\survive_charlesbiguator.c" />
<ClCompile Include="..\..\src\survive_config.c" />
@@ -197,6 +198,7 @@
<ItemGroup>
<ClInclude Include="..\..\include\libsurvive\poser.h" />
<ClInclude Include="..\..\include\libsurvive\survive.h" />
+ <ClInclude Include="..\..\include\libsurvive\survive_api.h" />
<ClInclude Include="..\..\include\libsurvive\survive_types.h" />
<ClInclude Include="..\..\redist\crc32.h" />
<ClInclude Include="..\..\redist\jsmn.h" />
diff --git a/winbuild/libsurvive/libsurvive.vcxproj.filters b/winbuild/libsurvive/libsurvive.vcxproj.filters
index 1f98c68..61cec4c 100644
--- a/winbuild/libsurvive/libsurvive.vcxproj.filters
+++ b/winbuild/libsurvive/libsurvive.vcxproj.filters
@@ -135,6 +135,9 @@
<ClCompile Include="..\..\redist\sba\sba_chkjac.c">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="..\..\src\survive_api.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\ootx_decoder.h">
@@ -188,6 +191,9 @@
<ClInclude Include="..\..\redist\sba\sba.h">
<Filter>Source Files</Filter>
</ClInclude>
+ <ClInclude Include="..\..\include\libsurvive\survive_api.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />