#include <PvSystem.h>
#include <PvDevice.h>
#include <PvDeviceGEV.h>
#include <PvDeviceU3V.h>
#include <PvStream.h>
#include <PvStreamGEV.h>
#include <PvStreamU3V.h>
#include <PvBuffer.h>
#include <PvImage.h>
#include <PvGenParameterArray.h>
#include <PvGenEnum.h>
#include <PvGenInteger.h>
#include <PvGenFloat.h>
#include <PvGenString.h>
#include <PvGenCommand.h>
#include <vector>
#include <string>
#include <cstring>
#include <cstdint>
#include <stdexcept>
struct JaiSystem {
PvSystem pvSystem;
std::vector<std::string> connectionIds;
std::vector<std::string> serialNumbers;
};
struct JaiDevice {
PvDevice* pvDevice = nullptr;
std::string connectionId;
};
struct JaiStream {
PvStream* pvStream = nullptr;
};
struct JaiBuffer {
PvBuffer* pvBuffer = nullptr;
bool owned = true; };
static void safe_copy(const char* src, char* dst, int len) {
if (!src || len <= 0) { if (dst && len > 0) dst[0] = '\0'; return; }
std::strncpy(dst, src, (size_t)(len - 1));
dst[len - 1] = '\0';
}
extern "C" {
JaiSystem* jai_system_new() {
try { return new JaiSystem(); }
catch (...) { return nullptr; }
}
void jai_system_free(JaiSystem* s) { delete s; }
int jai_system_find(JaiSystem* s) {
if (!s) return -1;
try {
s->connectionIds.clear();
s->serialNumbers.clear();
PvResult r = s->pvSystem.Find();
if (!r.IsOK()) return -1;
for (uint32_t i = 0; i < s->pvSystem.GetInterfaceCount(); i++) {
const PvInterface* iface = s->pvSystem.GetInterface(i);
if (!iface) continue;
for (uint32_t j = 0; j < iface->GetDeviceCount(); j++) {
const PvDeviceInfo* di = iface->GetDeviceInfo(j);
if (!di) continue;
s->connectionIds.push_back(di->GetConnectionID().GetAscii());
s->serialNumbers.push_back(di->GetSerialNumber().GetAscii());
}
}
return (int)s->connectionIds.size();
} catch (...) { return -1; }
}
int jai_system_get_device_id(JaiSystem* s, int idx, char* buf, int len) {
if (!s || idx < 0 || (size_t)idx >= s->connectionIds.size()) return -1;
safe_copy(s->connectionIds[(size_t)idx].c_str(), buf, len);
return 0;
}
int jai_system_get_device_serial(JaiSystem* s, int idx, char* buf, int len) {
if (!s || idx < 0 || (size_t)idx >= s->serialNumbers.size()) return -1;
safe_copy(s->serialNumbers[(size_t)idx].c_str(), buf, len);
return 0;
}
JaiDevice* jai_device_connect(const char* connection_id) {
if (!connection_id) return nullptr;
try {
PvResult r;
PvDevice* dev = PvDevice::CreateAndConnect(PvString(connection_id), &r);
if (!r.IsOK() || !dev) return nullptr;
JaiDevice* d = new JaiDevice();
d->pvDevice = dev;
d->connectionId = connection_id;
return d;
} catch (...) { return nullptr; }
}
void jai_device_free(JaiDevice* d) {
if (!d) return;
try {
if (d->pvDevice) {
d->pvDevice->Disconnect();
PvDevice::Free(d->pvDevice);
d->pvDevice = nullptr;
}
} catch (...) {}
delete d;
}
int jai_device_get_int(JaiDevice* d, const char* name, int64_t* out) {
if (!d || !d->pvDevice || !name || !out) return -1;
try {
PvGenParameterArray* p = d->pvDevice->GetParameters();
int64_t v = 0;
PvResult r = p->GetIntegerValue(PvString(name), v);
if (!r.IsOK()) return -1;
*out = v;
return 0;
} catch (...) { return -1; }
}
int jai_device_set_int(JaiDevice* d, const char* name, int64_t value) {
if (!d || !d->pvDevice || !name) return -1;
try {
PvGenParameterArray* p = d->pvDevice->GetParameters();
return p->SetIntegerValue(PvString(name), value).IsOK() ? 0 : -1;
} catch (...) { return -1; }
}
int jai_device_get_float(JaiDevice* d, const char* name, double* out) {
if (!d || !d->pvDevice || !name || !out) return -1;
try {
PvGenParameterArray* p = d->pvDevice->GetParameters();
double v = 0.0;
PvResult r = p->GetFloatValue(PvString(name), v);
if (!r.IsOK()) return -1;
*out = v;
return 0;
} catch (...) { return -1; }
}
int jai_device_set_float(JaiDevice* d, const char* name, double value) {
if (!d || !d->pvDevice || !name) return -1;
try {
PvGenParameterArray* p = d->pvDevice->GetParameters();
return p->SetFloatValue(PvString(name), value).IsOK() ? 0 : -1;
} catch (...) { return -1; }
}
int jai_device_get_string(JaiDevice* d, const char* name, char* buf, int len) {
if (!d || !d->pvDevice || !name || !buf) return -1;
try {
PvGenParameterArray* p = d->pvDevice->GetParameters();
PvString v;
PvResult r = p->GetStringValue(PvString(name), v);
if (!r.IsOK()) return -1;
safe_copy(v.GetAscii(), buf, len);
return 0;
} catch (...) { return -1; }
}
int jai_device_get_enum(JaiDevice* d, const char* name, char* buf, int len) {
if (!d || !d->pvDevice || !name || !buf) return -1;
try {
PvGenParameterArray* p = d->pvDevice->GetParameters();
PvString v;
PvResult r = p->GetEnumValue(PvString(name), v);
if (!r.IsOK()) return -1;
safe_copy(v.GetAscii(), buf, len);
return 0;
} catch (...) { return -1; }
}
int jai_device_set_enum(JaiDevice* d, const char* name, const char* value) {
if (!d || !d->pvDevice || !name || !value) return -1;
try {
PvGenParameterArray* p = d->pvDevice->GetParameters();
return p->SetEnumValue(PvString(name), PvString(value)).IsOK() ? 0 : -1;
} catch (...) { return -1; }
}
int jai_device_execute(JaiDevice* d, const char* name) {
if (!d || !d->pvDevice || !name) return -1;
try {
PvGenParameterArray* p = d->pvDevice->GetParameters();
return p->ExecuteCommand(PvString(name)).IsOK() ? 0 : -1;
} catch (...) { return -1; }
}
uint64_t jai_device_payload_size(JaiDevice* d) {
if (!d || !d->pvDevice) return 0;
try { return (uint64_t)d->pvDevice->GetPayloadSize(); }
catch (...) { return 0; }
}
int jai_device_stream_enable(JaiDevice* d) {
if (!d || !d->pvDevice) return -1;
try { return d->pvDevice->StreamEnable().IsOK() ? 0 : -1; }
catch (...) { return -1; }
}
int jai_device_stream_disable(JaiDevice* d) {
if (!d || !d->pvDevice) return -1;
try { return d->pvDevice->StreamDisable().IsOK() ? 0 : -1; }
catch (...) { return -1; }
}
int jai_device_get_connection_id(JaiDevice* d, char* buf, int len) {
if (!d || !buf) return -1;
safe_copy(d->connectionId.c_str(), buf, len);
return 0;
}
JaiStream* jai_stream_open(const char* connection_id) {
if (!connection_id) return nullptr;
try {
PvResult r;
PvStream* s = PvStream::CreateAndOpen(PvString(connection_id), &r);
if (!r.IsOK() || !s) return nullptr;
JaiStream* js = new JaiStream();
js->pvStream = s;
return js;
} catch (...) { return nullptr; }
}
void jai_stream_free(JaiStream* s) {
if (!s) return;
try {
if (s->pvStream) {
s->pvStream->Close();
PvStream::Free(s->pvStream);
s->pvStream = nullptr;
}
} catch (...) {}
delete s;
}
int jai_stream_queue(JaiStream* s, JaiBuffer* buf) {
if (!s || !s->pvStream || !buf || !buf->pvBuffer) return -1;
try { return s->pvStream->QueueBuffer(buf->pvBuffer).IsOK() ? 0 : -1; }
catch (...) { return -1; }
}
JaiBuffer* jai_stream_retrieve(JaiStream* s, uint32_t timeout_ms) {
if (!s || !s->pvStream) return nullptr;
try {
PvBuffer* pvBuf = nullptr;
PvResult opResult;
PvResult r = s->pvStream->RetrieveBuffer(&pvBuf, &opResult, timeout_ms);
if (!r.IsOK() || !opResult.IsOK() || !pvBuf) return nullptr;
JaiBuffer* jb = new JaiBuffer();
jb->pvBuffer = pvBuf;
jb->owned = false;
return jb;
} catch (...) { return nullptr; }
}
int jai_stream_requeue(JaiStream* s, JaiBuffer* buf) {
if (!s || !s->pvStream || !buf || !buf->pvBuffer) return -1;
try { return s->pvStream->QueueBuffer(buf->pvBuffer).IsOK() ? 0 : -1; }
catch (...) { return -1; }
}
int jai_stream_abort(JaiStream* s) {
if (!s || !s->pvStream) return -1;
try { return s->pvStream->AbortQueuedBuffers().IsOK() ? 0 : -1; }
catch (...) { return -1; }
}
JaiBuffer* jai_buffer_alloc(uint64_t size) {
try {
JaiBuffer* jb = new JaiBuffer();
jb->pvBuffer = new PvBuffer();
jb->pvBuffer->Alloc((uint32_t)size);
jb->owned = true;
return jb;
} catch (...) { return nullptr; }
}
void jai_buffer_free(JaiBuffer* buf) {
if (!buf) return;
if (buf->owned && buf->pvBuffer) {
delete buf->pvBuffer;
buf->pvBuffer = nullptr;
} else {
}
delete buf;
}
uint32_t jai_buffer_width(JaiBuffer* buf) {
if (!buf || !buf->pvBuffer) return 0;
try {
PvImage* img = buf->pvBuffer->GetImage();
return img ? img->GetWidth() : 0;
} catch (...) { return 0; }
}
uint32_t jai_buffer_height(JaiBuffer* buf) {
if (!buf || !buf->pvBuffer) return 0;
try {
PvImage* img = buf->pvBuffer->GetImage();
return img ? img->GetHeight() : 0;
} catch (...) { return 0; }
}
uint32_t jai_buffer_bits_per_pixel(JaiBuffer* buf) {
if (!buf || !buf->pvBuffer) return 8;
try {
PvImage* img = buf->pvBuffer->GetImage();
return img ? img->GetBitsPerPixel() : 8;
} catch (...) { return 8; }
}
uint32_t jai_buffer_bits_per_component(JaiBuffer* buf) {
if (!buf || !buf->pvBuffer) return 8;
try {
PvImage* img = buf->pvBuffer->GetImage();
if (!img) return 8;
uint32_t bpc = 8;
PvImage::GetBitsPerComponent(img->GetPixelType(), bpc);
return bpc;
} catch (...) { return 8; }
}
int jai_buffer_is_color(JaiBuffer* buf) {
if (!buf || !buf->pvBuffer) return 0;
try {
PvImage* img = buf->pvBuffer->GetImage();
if (!img) return 0;
return PvImage::IsPixelColor(img->GetPixelType()) ? 1 : 0;
} catch (...) { return 0; }
}
const uint8_t* jai_buffer_data(JaiBuffer* buf) {
if (!buf || !buf->pvBuffer) return nullptr;
try {
PvImage* img = buf->pvBuffer->GetImage();
if (!img) return nullptr;
return reinterpret_cast<const uint8_t*>(img->GetDataPointer());
} catch (...) { return nullptr; }
}
uint64_t jai_buffer_data_size(JaiBuffer* buf) {
if (!buf || !buf->pvBuffer) return 0;
try {
PvImage* img = buf->pvBuffer->GetImage();
if (!img) return 0;
uint32_t w = img->GetWidth();
uint32_t h = img->GetHeight();
uint32_t bpp = img->GetBitsPerPixel();
uint32_t padding = img->GetPaddingX();
uint32_t stride = (w * bpp + 7) / 8 + padding;
return (uint64_t)stride * h;
} catch (...) { return 0; }
}
}