diff options
Diffstat (limited to 'x-plane-plugin')
-rw-r--r-- | x-plane-plugin/plugin.c | 185 | ||||
-rw-r--r-- | x-plane-plugin/version-script.txt | 10 |
2 files changed, 195 insertions, 0 deletions
diff --git a/x-plane-plugin/plugin.c b/x-plane-plugin/plugin.c new file mode 100644 index 00000000..fc1a5186 --- /dev/null +++ b/x-plane-plugin/plugin.c @@ -0,0 +1,185 @@ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <sys/file.h> +#include <sys/mman.h> +#include <limits.h> +#include <unistd.h> + +#include <XPLMPlugin.h> +#include <XPLMDisplay.h> +#include <XPLMDataAccess.h> +#include <XPLMCamera.h> +#include <XPLMProcessing.h> + +// using Wine name to ease things +#define WINE_SHM_NAME "facetracknoir-wine-shm" +#define WINE_MTX_NAME "facetracknoir-wine-mtx" + +typedef struct PortableLockedShm { + void* mem; + int fd, size; +} PortableLockedShm; + +typedef struct WineSHM { + float rx, ry, rz, tx, ty, tz; + char stop; +} WineSHM; + +static PortableLockedShm* lck_posix = NULL; +static WineSHM* shm_posix = NULL; +static void *view_x, *view_y, *view_z, *view_heading, *view_pitch; +static float offset_x, offset_y, offset_z; + +PortableLockedShm* PortableLockedShm_init(const char *shmName, const char *mutexName, int mapSize) +{ + PortableLockedShm* self = malloc(sizeof(PortableLockedShm)); + char shm_filename[NAME_MAX]; + shm_filename[0] = '/'; + strncpy(shm_filename+1, shmName, NAME_MAX-2); + shm_filename[NAME_MAX-1] = '\0'; + sprintf(shm_filename + strlen(shm_filename), "%ld\n", (long) getuid()); + //(void) shm_unlink(shm_filename); + + self->fd = shm_open(shm_filename, O_RDWR | O_CREAT, 0600); + if (ftruncate(self->fd, mapSize) == 0) + self->mem = mmap(NULL, mapSize, PROT_READ|PROT_WRITE, MAP_SHARED, self->fd, (off_t)0); + else + self->mem = (void*) -1; + return self; +} + +void PortableLockedShm_free(PortableLockedShm* self) +{ + //(void) shm_unlink(shm_filename); + (void) munmap(self->mem, self->size); + (void) close(self->fd); + free(self); +} + +void PortableLockedShm_lock(PortableLockedShm* self) +{ + flock(self->fd, LOCK_SH); +} + +void PortableLockedShm_unlock(PortableLockedShm* self) +{ + flock(self->fd, LOCK_UN); +} + +static void reinit_offset() { + offset_x = XPLMGetDataf(view_x); + offset_y = XPLMGetDataf(view_y); + offset_z = XPLMGetDataf(view_z); +} + +int write_head_position( + XPLMDrawingPhase inPhase, + int inIsBefore, + void * inRefcon) +{ + if (lck_posix != NULL && shm_posix != NULL) { + PortableLockedShm_lock(lck_posix); + XPLMSetDataf(view_x, shm_posix->tx * 1e-2 + offset_x); + XPLMSetDataf(view_y, shm_posix->ty * 1e-2 + offset_y); + XPLMSetDataf(view_z, shm_posix->tz * 1e-2 + offset_z); + XPLMSetDataf(view_heading, shm_posix->rx * 57.295781); + XPLMSetDataf(view_pitch, shm_posix->ry * 57.295781); + PortableLockedShm_unlock(lck_posix); + } + return 1; +} + +PLUGIN_API int XPluginStart ( char * outName, char * outSignature, char * outDescription ) { + view_x = XPLMFindDataRef("sim/aircraft/view/acf_peX"); + view_y = XPLMFindDataRef("sim/aircraft/view/acf_peY"); + view_z = XPLMFindDataRef("sim/aircraft/view/acf_peZ"); + view_heading = XPLMFindDataRef("sim/graphics/view/pilots_head_psi"); + view_pitch = XPLMFindDataRef("sim/graphics/view/pilots_head_the"); + if (view_x && view_y && view_z && view_heading && view_pitch) { + lck_posix = PortableLockedShm_init(WINE_SHM_NAME, WINE_MTX_NAME, sizeof(WineSHM)); + if (lck_posix->mem == (void*)-1) { + fprintf(stderr, "FTNOIR failed to init SHM #1!\n"); + return 0; + } + if (lck_posix->mem == NULL) { + fprintf(stderr, "FTNOIR failed to init SHM #2!\n"); + return 0; + } + shm_posix = (WineSHM*) lck_posix->mem; + memset(shm_posix, 0, sizeof(WineSHM)); + strcpy(outName, "FaceTrackNoIR"); + strcpy(outSignature, "FaceTrackNoIR - FreeTrack lives!"); + strcpy(outDescription, "Face tracking view control"); + fprintf(stderr, "FTNOIR init complete\n"); + return 1; + } + return 0; +} + +#if 0 +static int camera_callback(XPLMCameraPosition_t* outCameraPosition, int inIsLosingControl, void* inRefCon) { + if (!inIsLosingControl && XPLMGetCycleNumber() > 0) { + //XPLMReadCameraPosition(outCameraPosition); + PortableLockedShm_lock(lck_posix); + outCameraPosition->heading = shm_posix->rx * 57.295781; + outCameraPosition->pitch = shm_posix->ry * 57.295781; + outCameraPosition->roll = shm_posix->rz * 57.295781; + outCameraPosition->x = XPLMGetDataf(view_x); + outCameraPosition->y = XPLMGetDataf(view_y); + outCameraPosition->z = XPLMGetDataf(view_z); + PortableLockedShm_unlock(lck_posix); + return 1; + } + return 0; +} +static float flight_loop ( + float inElapsedSinceLastCall, + float inElapsedTimeSinceLastFlightLoop, + int inCounter, + void * inRefcon) +{ + XPLMControlCamera(xplm_ControlCameraForever, camera_callback, NULL); + // don't want it called anymore + return 0; +} +#endif + +PLUGIN_API void XPluginStop ( void ) { +#if 0 + // crashes due to race + if (lck_posix) + PortableLockedShm_free(lck_posix); + lck_posix = NULL; + shm_posix = NULL; +#endif +} + +PLUGIN_API void XPluginEnable ( void ) { + reinit_offset(); + XPLMRegisterDrawCallback(write_head_position, xplm_Phase_LastScene, 1, NULL); +#if 0 + XPLMRegisterFlightLoopCallback(flight_loop, -1, NULL); +#endif +} + +PLUGIN_API void XPluginDisable ( void ) { + XPLMUnregisterDrawCallback(write_head_position, xplm_Phase_LastScene, 1, NULL); + XPLMSetDataf(view_x, offset_x); + XPLMSetDataf(view_y, offset_y); + XPLMSetDataf(view_z, offset_z); +#if 0 + XPLMUnregisterFlightLoopCallback(flight_loop, NULL); + if (XPLMIsCameraBeingControlled(NULL)) + XPLMDontControlCamera(); +#endif +} + +PLUGIN_API void XPluginReceiveMessage( + XPLMPluginID inFromWho, + int inMessage, + void * inParam) +{ + if (inMessage == XPLM_MSG_AIRPORT_LOADED) + reinit_offset(); +} diff --git a/x-plane-plugin/version-script.txt b/x-plane-plugin/version-script.txt new file mode 100644 index 00000000..cfb84ec8 --- /dev/null +++ b/x-plane-plugin/version-script.txt @@ -0,0 +1,10 @@ +{ + global: + XPluginStart; + XPluginStop; + XPluginEnable; + XPluginDisable; + XPluginReceiveMessage; + local: + *; +}; |