|
- #pragma once
- #ifdef LAUNCHPAD
- #include <memory.h>
- #include <windows.h>
- #include "driver_include.hpp"
-
- #pragma pack(push,1)
- struct __attribute__((aligned(1), packed)) _launchpadMessage
- {
- uint8_t status;
- uint8_t cmd;
- uint8_t key;
- uint8_t currentScene;
- uint8_t lpNumber;
- uint8_t shiftDown;
- short param0;
- short param1;
-
- #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
- void FromMessage(LaunchpadMessage *src)
- {
- status = (uint8_t)src->status;
- cmd = (uint8_t)src->cmd;
- key = (uint8_t)src->key;
- currentScene = (uint8_t)src->currentScene;
- lpNumber = (uint8_t)src->lpNumber;
- shiftDown = (uint8_t)(src->shiftDown ? 1 : 0);
- param0 = src->param0;
- param1 = src->param1;
- }
-
- LaunchpadMessage Reconstruct()
- {
- LaunchpadMessage rv;
- rv.status = (LaunchpadKeyStatus)status;
- rv.cmd = (LaunchpadCommand)cmd;
- rv.key = (LaunchpadKey)key;
- rv.currentScene = (LaunchpadScene)currentScene;
- rv.lpNumber = lpNumber;
- rv.shiftDown = shiftDown != 0;
- rv.param0 = param0;
- rv.param1 = param1;
-
- return rv;
- }
- };
- #pragma pack(pop)
-
- class communicator
- {
- private:
- class circBuffer
- {
- private:
- uint8_t * mapAccess;
- int rdPtr;
- int WR_PTR_POS;
- int P0;
- int PN;
-
- public:
- static int bufferOverhead() { return sizeof(uint32_t); } // n. di bytes EXTRA richiesti per la gestione del buffer circolare
-
- void Clear()
- {
- rdPtr = wrPtr_get();
- }
-
- circBuffer(int bufferSize, void *acc, int offset)
- {
- WR_PTR_POS = offset;
- P0 = WR_PTR_POS + bufferOverhead(); // posizione 0 memoria effettiva (dove salvare e leggere i dati, dopo i primi 8 bytes riservati ai puntatori rd/wr)
- PN = P0 + bufferSize - bufferOverhead();
- mapAccess = (uint8_t*)acc;
- Clear();
- }
-
- ~circBuffer()
- {
- mapAccess = NULL;
- }
-
- void WriteChunk(LaunchpadMessage *_msg)
- {
- #ifdef DEBUG
- info("send message %i; tx size is %i", _msg->cmd, sizeof(_launchpadMessage));
- #endif
- _launchpadMessage msg;
- msg.FromMessage(_msg);
-
- uint8_t *ptr = (uint8_t *)&msg;
- int cur_wrPtr = wrPtr_get();
- for(int k = 0; k < (int)sizeof(_launchpadMessage); k++)
- cur_wrPtr = Put(*ptr++, cur_wrPtr);
- wrPtr_set(cur_wrPtr); // finalizza IN SOLIDO il chunk appena letto
- }
-
- LaunchpadMessage ReadChunk()
- {
- if(data_available())
- {
- _launchpadMessage msg;
- uint8_t *p = (uint8_t *)&msg;
- for(int k = 0; k < (int)sizeof(_launchpadMessage); k++)
- *p++ = Get();
-
- return msg.Reconstruct();
- }
-
- LaunchpadMessage rv;
- rv.status = LaunchpadKeyStatus::keyNone;
- return rv;
- }
-
- private:
- int wrPtr_get()
- {
- return *((uint32_t *)(mapAccess + WR_PTR_POS));
- }
- void wrPtr_set(uint32_t v)
- {
- uint32_t *ptr = (uint32_t *)(mapAccess + WR_PTR_POS);
- *ptr = v;
- }
- bool data_available() { return rdPtr != wrPtr_get(); }
-
- int incPtr(int ptr)
- {
- if(++ptr >= PN)
- ptr = P0;
-
- return ptr;
- }
-
- int Put(uint8_t b, int ptr)
- {
- mapAccess[ptr] = b;
- return incPtr(ptr);
- }
-
- uint8_t Get()
- {
- int trdPtr = rdPtr;
- uint8_t rv = mapAccess[trdPtr];
- rdPtr = incPtr(trdPtr);
- return rv;
- }
- };
-
- public:
- communicator()
- {
- hMapFile = NULL;
- syncMutex = NULL;
- pmemory = NULL;
- pCommonMemory = NULL;
- rdBuffer = wrBuffer = NULL;
- }
-
- ~communicator()
- {
- deinit();
- }
-
- void clear()
- {
- if(pmemory != NULL)
- {
- rdBuffer->Clear();
- wrBuffer->Clear();
- }
- }
-
- bool Connected() { return pmemory != NULL; }
-
- bool Open()
- {
- if(pmemory == NULL)
- {
- try
- {
- init();
- } catch(_exception ex)
- {
- deinit();
- }
- }
-
- return pmemory != NULL;
- }
-
- void Write(LaunchpadMessage msg)
- {
- if(checkServer())
- {
- if(WaitForSingleObject(syncMutex, 500) == WAIT_OBJECT_0)
- {
- wrBuffer->WriteChunk(&msg);
- ReleaseMutex(syncMutex);
- }
- }
- }
-
- LaunchpadMessage Read()
- {
- if(checkServer())
- return rdBuffer->ReadChunk();
-
- LaunchpadMessage rv;
- rv.status = LaunchpadKeyStatus::keyNone;
- return rv;
- }
-
- private:
- void *pmemory;
- uint32_t *pCommonMemory;
- circBuffer *rdBuffer;
- circBuffer *wrBuffer;
- HANDLE hMapFile;
- HANDLE syncMutex;
-
- void init()
- {
- const int BUFFER_SIZE = 100;
- const int SERVERUP_POS = 0; // (Int32) : indica se il server e' up o down
- const int START_OF_BUFFER = SERVERUP_POS + sizeof(uint32_t); // prima locazione di memoria utile per il buffer circolare
-
- int b_l = BUFFER_SIZE * sizeof(_launchpadMessage) + circBuffer::bufferOverhead();
- #ifdef DEBUG
- info("Open file mapping");
- #endif
- hMapFile = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE, TRUE, "launchpad_mem");
- if(hMapFile != NULL)
- {
- #ifdef DEBUG
- info("file mapping opened");
- #endif
- void *p = MapViewOfFile(hMapFile, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 2 * b_l + sizeof(uint32_t)/*flag SERVER_POS*/);
- #ifdef DEBUG
- info("MapViewOfFile success");
- #endif
- syncMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "launchpad_mtx");
- #ifdef DEBUG
- if(syncMutex != NULL) info("mutex OK"); else info("*** no mutexxxxxxx!!!!!! ****");
- #endif
-
-
- wrBuffer = new circBuffer(b_l, p, START_OF_BUFFER);
- rdBuffer = new circBuffer(b_l, p, START_OF_BUFFER + b_l);
- #ifdef DEBUG
- info("circBuffer created");
- #endif
-
- pmemory = p;
- pCommonMemory = (uint32_t *)p;
- #ifdef DEBUG
- info("Opened OK");
- #endif
- }
- }
-
- bool checkServer()
- {
- bool rv = false;
- if(pCommonMemory != NULL)
- {
- uint32_t server = *pCommonMemory;
- if(server == 0)
- {
- #ifdef DEBUG
- info("*** connection lost ***");
- #endif
- deinit();
- } else
- rv = true;
- }
-
- return rv;
- }
-
- void deinit()
- {
- void *p = pmemory;
- pmemory = NULL;
- pCommonMemory = NULL;
-
- if(p != NULL)
- UnmapViewOfFile(p);
-
- if(hMapFile != NULL)
- CloseHandle(hMapFile);
- hMapFile = NULL;
-
- if(rdBuffer != NULL)
- {
- delete rdBuffer;
- rdBuffer = NULL;
- }
- if(wrBuffer != NULL)
- {
- delete wrBuffer;
- wrBuffer = NULL;
- }
- if(syncMutex != NULL)
- {
- CloseHandle(syncMutex);
- syncMutex = NULL;
- }
- }
- };
- #endif
|