// native_bridge/src/SharedMemoryIPC.cpp #include "SharedMemoryIPC.h" #include #include // ── Platform shared-memory helpers (used by main.cpp on Windows and by the // self-check test on POSIX). The DAW (Rust) creates the mapping; the bridge // opens it. Layout must match the Rust struct (see src-tauri/src/shm.rs). #ifdef _WIN32 #include struct ShmHandle { HANDLE map = nullptr; void* view = nullptr; }; ShmHandle* shm_open(const char* name, size_t size) { ShmHandle* h = new ShmHandle(); h->map = OpenFileMappingA(FILE_MAP_ALL_ACCESS, FALSE, name); if (!h->map) { delete h; return nullptr; } h->view = MapViewOfFile(h->map, FILE_MAP_ALL_ACCESS, 0, 0, size); if (!h->view) { CloseHandle(h->map); delete h; return nullptr; } return h; } // Creates the mapping (used by tests/self-check; the DAW normally owns it). ShmHandle* shm_create(const char* name, size_t size) { ShmHandle* h = new ShmHandle(); int wlen = MultiByteToWideChar(CP_UTF8, 0, name, -1, nullptr, 0); std::wstring wname(wlen, L'\0'); MultiByteToWideChar(CP_UTF8, 0, name, -1, &wname[0], wlen); h->map = CreateFileMappingW(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, size, wname.c_str()); if (!h->map) { delete h; return nullptr; } h->view = MapViewOfFile(h->map, FILE_MAP_ALL_ACCESS, 0, 0, size); if (!h->view) { CloseHandle(h->map); delete h; return nullptr; } return h; } void shm_close(ShmHandle* h) { if (!h) return; if (h->view) UnmapViewOfFile(h->view); if (h->map) CloseHandle(h->map); delete h; } #else #include #include #include #include struct ShmHandle { int fd = -1; void* view = nullptr; std::string name; }; ShmHandle* shm_open(const char* name) { size_t sz = sizeof(SharedAudioBufferIPC); int fd = ::shm_open(name, O_CREAT | O_RDWR, 0666); if (fd < 0) return nullptr; if (ftruncate(fd, (off_t)sz) != 0) { ::close(fd); return nullptr; } void* view = mmap(nullptr, sz, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (view == MAP_FAILED) { ::close(fd); return nullptr; } ShmHandle* h = new ShmHandle(); h->fd = fd; h->view = view; h->name = name; return h; } void shm_close(ShmHandle* h) { if (!h) return; if (h->view) munmap(h->view, sizeof(SharedAudioBufferIPC)); if (h->fd >= 0) ::close(h->fd); shm_unlink(h->name.c_str()); delete h; } #endif ShmHandle* shm_open_default() { return shm_open("SonicForge_DAW_IPC"); } SharedAudioBufferIPC* shm_ptr(ShmHandle* h) { return h ? static_cast(h->view) : nullptr; } SandboxHostIPC* shm_sandbox_ptr(ShmHandle* h) { return h ? static_cast(h->view) : nullptr; } bool shm_write_midi(ShmHandle* h, uint8_t cmd, uint8_t channel, uint8_t pitch, uint8_t velocity, uint32_t sampleOffset, uint8_t data2, uint8_t data3) { SharedAudioBufferIPC* ipc = shm_ptr(h); if (!ipc) return false; // Ring overwrite guard: keep at most queue capacity pending events. if (ipc->midiQueueCount >= 64) return false; uint32_t i = ipc->midiQueueCount++; SharedAudioBufferIPC::MidiEventIPC& e = ipc->midiQueue[i]; e.command = cmd; e.channel = channel; e.pitch = pitch; e.velocity = velocity; e.data2 = data2; e.data3 = data3; e.sampleOffset = sampleOffset; return true; } bool shm_write_control(ShmHandle* h, uint32_t type, uint32_t arg0, uint32_t arg1, uint32_t channel, const char* path) { SharedAudioBufferIPC* ipc = shm_ptr(h); if (!ipc) return false; if (ipc->controlQueueCount >= 8) return false; uint32_t i = ipc->controlQueueCount++; SharedAudioBufferIPC::ControlEventIPC& c = ipc->controlQueue[i]; c.type = type; c.arg0 = arg0; c.channel = channel; std::memset(c.arg2, 0, sizeof(c.arg2)); if (path && type == 2 /*LOAD*/) { c.arg1 = (uint32_t)std::strlen(path); // path length in arg1 if (c.arg1 < sizeof(c.arg2)) std::memcpy(c.arg2, path, c.arg1); } else { c.arg1 = arg1; // TRANSPORT playhead / OPEN_GUI hwnd etc. } return true; }