2019-09-28 11:34:46 -07:00
|
|
|
/*----------------------------------------------------------------------------*/
|
2020-06-26 17:12:55 -07:00
|
|
|
/* Copyright (c) 2019-2020 FIRST. All Rights Reserved. */
|
2019-09-28 11:34:46 -07:00
|
|
|
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
|
|
|
|
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
|
|
|
|
/* the project. */
|
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
#include "SimDeviceDataJNI.h"
|
|
|
|
|
|
|
|
|
|
#include <jni.h>
|
|
|
|
|
|
|
|
|
|
#include <functional>
|
|
|
|
|
#include <string>
|
|
|
|
|
#include <utility>
|
|
|
|
|
|
|
|
|
|
#include <wpi/UidVector.h>
|
|
|
|
|
#include <wpi/jni_util.h>
|
|
|
|
|
|
|
|
|
|
#include "SimulatorJNI.h"
|
2020-06-27 22:11:24 -07:00
|
|
|
#include "edu_wpi_first_hal_simulation_SimDeviceDataJNI.h"
|
|
|
|
|
#include "hal/simulation/SimDeviceData.h"
|
2019-09-28 11:34:46 -07:00
|
|
|
|
2020-06-26 17:12:55 -07:00
|
|
|
using namespace hal;
|
2019-09-28 11:34:46 -07:00
|
|
|
using namespace wpi::java;
|
|
|
|
|
|
|
|
|
|
static JClass simDeviceInfoCls;
|
|
|
|
|
static JClass simValueInfoCls;
|
|
|
|
|
static JClass simDeviceCallbackCls;
|
|
|
|
|
static JClass simValueCallbackCls;
|
|
|
|
|
static jmethodID simDeviceCallbackCallback;
|
|
|
|
|
static jmethodID simValueCallbackCallback;
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
|
|
struct DeviceInfo {
|
|
|
|
|
DeviceInfo(const char* name_, HAL_SimDeviceHandle handle_)
|
|
|
|
|
: name{name_}, handle{handle_} {}
|
|
|
|
|
std::string name;
|
|
|
|
|
HAL_SimValueHandle handle;
|
|
|
|
|
|
|
|
|
|
jobject MakeJava(JNIEnv* env) const;
|
|
|
|
|
void CallJava(JNIEnv* env, jobject callobj) const;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct ValueInfo {
|
|
|
|
|
ValueInfo(const char* name_, HAL_SimValueHandle handle_, bool readonly_,
|
|
|
|
|
const HAL_Value& value_)
|
|
|
|
|
: name{name_}, handle{handle_}, readonly{readonly_}, value{value_} {}
|
|
|
|
|
std::string name;
|
|
|
|
|
HAL_SimValueHandle handle;
|
|
|
|
|
bool readonly;
|
|
|
|
|
HAL_Value value;
|
|
|
|
|
|
|
|
|
|
jobject MakeJava(JNIEnv* env) const;
|
|
|
|
|
void CallJava(JNIEnv* env, jobject callobj) const;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
std::pair<jlong, jdouble> ToValue12() const;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
jobject DeviceInfo::MakeJava(JNIEnv* env) const {
|
|
|
|
|
static jmethodID func =
|
|
|
|
|
env->GetMethodID(simDeviceInfoCls, "<init>", "(Ljava/lang/String;I)V");
|
|
|
|
|
return env->NewObject(simDeviceInfoCls, func, MakeJString(env, name),
|
|
|
|
|
(jint)handle);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DeviceInfo::CallJava(JNIEnv* env, jobject callobj) const {
|
|
|
|
|
env->CallVoidMethod(callobj, simDeviceCallbackCallback,
|
|
|
|
|
MakeJString(env, name), (jint)handle);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::pair<jlong, jdouble> ValueInfo::ToValue12() const {
|
|
|
|
|
jlong value1 = 0;
|
|
|
|
|
jdouble value2 = 0.0;
|
|
|
|
|
switch (value.type) {
|
|
|
|
|
case HAL_BOOLEAN:
|
|
|
|
|
value1 = value.data.v_boolean;
|
|
|
|
|
break;
|
|
|
|
|
case HAL_DOUBLE:
|
|
|
|
|
value2 = value.data.v_double;
|
|
|
|
|
break;
|
|
|
|
|
case HAL_ENUM:
|
|
|
|
|
value1 = value.data.v_enum;
|
|
|
|
|
break;
|
|
|
|
|
case HAL_INT:
|
|
|
|
|
value1 = value.data.v_int;
|
|
|
|
|
break;
|
|
|
|
|
case HAL_LONG:
|
|
|
|
|
value1 = value.data.v_long;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return std::pair(value1, value2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
jobject ValueInfo::MakeJava(JNIEnv* env) const {
|
|
|
|
|
static jmethodID func =
|
|
|
|
|
env->GetMethodID(simValueInfoCls, "<init>", "(Ljava/lang/String;IZIJD)V");
|
|
|
|
|
auto [value1, value2] = ToValue12();
|
|
|
|
|
return env->NewObject(simValueInfoCls, func, MakeJString(env, name),
|
|
|
|
|
(jint)handle, (jboolean)readonly, (jint)value.type,
|
|
|
|
|
value1, value2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ValueInfo::CallJava(JNIEnv* env, jobject callobj) const {
|
|
|
|
|
auto [value1, value2] = ToValue12();
|
|
|
|
|
env->CallVoidMethod(callobj, simValueCallbackCallback, MakeJString(env, name),
|
|
|
|
|
(jint)handle, (jboolean)readonly, (jint)value.type,
|
|
|
|
|
value1, value2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
|
|
class CallbackStore {
|
|
|
|
|
public:
|
|
|
|
|
explicit CallbackStore(JNIEnv* env, jobject obj) : m_call{env, obj} {}
|
|
|
|
|
~CallbackStore() {
|
|
|
|
|
if (m_cancelCallback) m_cancelCallback();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SetCancel(std::function<void()> cancelCallback) {
|
|
|
|
|
m_cancelCallback = std::move(cancelCallback);
|
|
|
|
|
}
|
|
|
|
|
void Free(JNIEnv* env) { m_call.free(env); }
|
|
|
|
|
jobject Get() const { return m_call; }
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
wpi::java::JGlobal<jobject> m_call;
|
|
|
|
|
std::function<void()> m_cancelCallback;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class CallbackThreadJNI : public wpi::SafeThread {
|
|
|
|
|
public:
|
|
|
|
|
void Main();
|
|
|
|
|
|
|
|
|
|
using DeviceCalls =
|
|
|
|
|
std::vector<std::pair<std::weak_ptr<CallbackStore>, DeviceInfo>>;
|
|
|
|
|
DeviceCalls m_deviceCalls;
|
|
|
|
|
using ValueCalls =
|
|
|
|
|
std::vector<std::pair<std::weak_ptr<CallbackStore>, ValueInfo>>;
|
|
|
|
|
ValueCalls m_valueCalls;
|
|
|
|
|
|
|
|
|
|
wpi::UidVector<std::shared_ptr<CallbackStore>, 4> m_callbacks;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class CallbackJNI {
|
|
|
|
|
public:
|
|
|
|
|
static CallbackJNI& GetInstance() {
|
|
|
|
|
static CallbackJNI inst;
|
|
|
|
|
return inst;
|
|
|
|
|
}
|
|
|
|
|
void SendDevice(int32_t callback, DeviceInfo info);
|
|
|
|
|
void SendValue(int32_t callback, ValueInfo info);
|
|
|
|
|
|
|
|
|
|
std::pair<int32_t, std::shared_ptr<CallbackStore>> AllocateCallback(
|
|
|
|
|
JNIEnv* env, jobject obj);
|
|
|
|
|
|
|
|
|
|
void FreeCallback(JNIEnv* env, int32_t uid);
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
CallbackJNI() { m_owner.Start(); }
|
|
|
|
|
|
|
|
|
|
wpi::SafeThreadOwner<CallbackThreadJNI> m_owner;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
void CallbackThreadJNI::Main() {
|
|
|
|
|
JNIEnv* env;
|
|
|
|
|
JavaVMAttachArgs args;
|
|
|
|
|
args.version = JNI_VERSION_1_2;
|
|
|
|
|
args.name = const_cast<char*>("SimDeviceCallback");
|
|
|
|
|
args.group = nullptr;
|
|
|
|
|
jint rs = sim::GetJVM()->AttachCurrentThreadAsDaemon(
|
|
|
|
|
reinterpret_cast<void**>(&env), &args);
|
|
|
|
|
if (rs != JNI_OK) return;
|
|
|
|
|
|
|
|
|
|
DeviceCalls deviceCalls;
|
|
|
|
|
ValueCalls valueCalls;
|
|
|
|
|
|
|
|
|
|
std::unique_lock lock(m_mutex);
|
|
|
|
|
while (m_active) {
|
|
|
|
|
m_cond.wait(lock, [&] { return !m_active; });
|
|
|
|
|
if (!m_active) break;
|
|
|
|
|
|
|
|
|
|
deviceCalls.swap(m_deviceCalls);
|
|
|
|
|
valueCalls.swap(m_valueCalls);
|
|
|
|
|
|
|
|
|
|
lock.unlock(); // don't hold mutex during callback execution
|
|
|
|
|
|
|
|
|
|
for (auto&& call : deviceCalls) {
|
|
|
|
|
if (auto store = call.first.lock()) {
|
|
|
|
|
if (jobject callobj = store->Get()) {
|
|
|
|
|
call.second.CallJava(env, callobj);
|
|
|
|
|
if (env->ExceptionCheck()) {
|
|
|
|
|
env->ExceptionDescribe();
|
|
|
|
|
env->ExceptionClear();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (auto&& call : valueCalls) {
|
|
|
|
|
if (auto store = call.first.lock()) {
|
|
|
|
|
if (jobject callobj = store->Get()) {
|
|
|
|
|
call.second.CallJava(env, callobj);
|
|
|
|
|
if (env->ExceptionCheck()) {
|
|
|
|
|
env->ExceptionDescribe();
|
|
|
|
|
env->ExceptionClear();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
deviceCalls.clear();
|
|
|
|
|
valueCalls.clear();
|
|
|
|
|
|
|
|
|
|
lock.lock();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// free global references
|
|
|
|
|
for (auto&& callback : m_callbacks) callback->Free(env);
|
|
|
|
|
|
|
|
|
|
sim::GetJVM()->DetachCurrentThread();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CallbackJNI::SendDevice(int32_t callback, DeviceInfo info) {
|
|
|
|
|
auto thr = m_owner.GetThread();
|
|
|
|
|
if (!thr) return;
|
|
|
|
|
thr->m_deviceCalls.emplace_back(thr->m_callbacks[callback], std::move(info));
|
|
|
|
|
thr->m_cond.notify_one();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CallbackJNI::SendValue(int32_t callback, ValueInfo info) {
|
|
|
|
|
auto thr = m_owner.GetThread();
|
|
|
|
|
if (!thr) return;
|
|
|
|
|
thr->m_valueCalls.emplace_back(thr->m_callbacks[callback], std::move(info));
|
|
|
|
|
thr->m_cond.notify_one();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::pair<int32_t, std::shared_ptr<CallbackStore>>
|
|
|
|
|
CallbackJNI::AllocateCallback(JNIEnv* env, jobject obj) {
|
|
|
|
|
auto thr = m_owner.GetThread();
|
|
|
|
|
if (!thr) return std::pair(0, nullptr);
|
|
|
|
|
auto store = std::make_shared<CallbackStore>(env, obj);
|
|
|
|
|
return std::pair(thr->m_callbacks.emplace_back(store) + 1, store);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CallbackJNI::FreeCallback(JNIEnv* env, int32_t uid) {
|
|
|
|
|
auto thr = m_owner.GetThread();
|
|
|
|
|
if (!thr) return;
|
|
|
|
|
if (uid <= 0 || static_cast<uint32_t>(uid) >= thr->m_callbacks.size()) return;
|
|
|
|
|
--uid;
|
|
|
|
|
auto store = std::move(thr->m_callbacks[uid]);
|
|
|
|
|
thr->m_callbacks.erase(uid);
|
|
|
|
|
store->Free(env);
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-26 17:12:55 -07:00
|
|
|
namespace hal {
|
2019-09-28 11:34:46 -07:00
|
|
|
namespace sim {
|
|
|
|
|
|
|
|
|
|
bool InitializeSimDeviceDataJNI(JNIEnv* env) {
|
|
|
|
|
simDeviceInfoCls = JClass(
|
2020-06-27 22:11:24 -07:00
|
|
|
env, "edu/wpi/first/hal/simulation/SimDeviceDataJNI$SimDeviceInfo");
|
2019-09-28 11:34:46 -07:00
|
|
|
if (!simDeviceInfoCls) return false;
|
|
|
|
|
|
2020-06-27 22:11:24 -07:00
|
|
|
simValueInfoCls =
|
|
|
|
|
JClass(env, "edu/wpi/first/hal/simulation/SimDeviceDataJNI$SimValueInfo");
|
2019-09-28 11:34:46 -07:00
|
|
|
if (!simValueInfoCls) return false;
|
|
|
|
|
|
2020-06-27 22:11:24 -07:00
|
|
|
simDeviceCallbackCls =
|
|
|
|
|
JClass(env, "edu/wpi/first/hal/simulation/SimDeviceCallback");
|
2019-09-28 11:34:46 -07:00
|
|
|
if (!simDeviceCallbackCls) return false;
|
|
|
|
|
|
|
|
|
|
simDeviceCallbackCallback = env->GetMethodID(simDeviceCallbackCls, "callback",
|
|
|
|
|
"(Ljava/lang/String;I)V");
|
|
|
|
|
if (!simDeviceCallbackCallback) return false;
|
|
|
|
|
|
2020-06-27 22:11:24 -07:00
|
|
|
simValueCallbackCls =
|
|
|
|
|
JClass(env, "edu/wpi/first/hal/simulation/SimValueCallback");
|
2019-09-28 11:34:46 -07:00
|
|
|
if (!simValueCallbackCls) return false;
|
|
|
|
|
|
|
|
|
|
simValueCallbackCallback = env->GetMethodID(
|
|
|
|
|
simValueCallbackCls, "callbackNative", "(Ljava/lang/String;IZIJD)V");
|
|
|
|
|
if (!simValueCallbackCallback) return false;
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FreeSimDeviceDataJNI(JNIEnv* env) {
|
|
|
|
|
simDeviceInfoCls.free(env);
|
|
|
|
|
simValueInfoCls.free(env);
|
|
|
|
|
simDeviceCallbackCls.free(env);
|
|
|
|
|
simValueCallbackCls.free(env);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace sim
|
2020-06-26 17:12:55 -07:00
|
|
|
} // namespace hal
|
2019-09-28 11:34:46 -07:00
|
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
|
|
2020-07-04 01:09:49 -07:00
|
|
|
/*
|
|
|
|
|
* Class: edu_wpi_first_hal_simulation_SimDeviceDataJNI
|
|
|
|
|
* Method: setSimDeviceEnabled
|
|
|
|
|
* Signature: (Ljava/lang/String;Z)V
|
|
|
|
|
*/
|
|
|
|
|
JNIEXPORT void JNICALL
|
|
|
|
|
Java_edu_wpi_first_hal_simulation_SimDeviceDataJNI_setSimDeviceEnabled
|
|
|
|
|
(JNIEnv* env, jclass, jstring prefix, jboolean enabled)
|
|
|
|
|
{
|
|
|
|
|
HALSIM_SetSimDeviceEnabled(JStringRef{env, prefix}.c_str(), enabled);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Class: edu_wpi_first_hal_simulation_SimDeviceDataJNI
|
|
|
|
|
* Method: isSimDeviceEnabled
|
|
|
|
|
* Signature: (Ljava/lang/String;)Z
|
|
|
|
|
*/
|
|
|
|
|
JNIEXPORT jboolean JNICALL
|
|
|
|
|
Java_edu_wpi_first_hal_simulation_SimDeviceDataJNI_isSimDeviceEnabled
|
|
|
|
|
(JNIEnv* env, jclass, jstring name)
|
|
|
|
|
{
|
|
|
|
|
return HALSIM_IsSimDeviceEnabled(JStringRef{env, name}.c_str());
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-28 11:34:46 -07:00
|
|
|
/*
|
2020-06-27 22:11:24 -07:00
|
|
|
* Class: edu_wpi_first_hal_simulation_SimDeviceDataJNI
|
2019-09-28 11:34:46 -07:00
|
|
|
* Method: registerSimDeviceCreatedCallback
|
|
|
|
|
* Signature: (Ljava/lang/String;Ljava/lang/Object;Z)I
|
|
|
|
|
*/
|
|
|
|
|
JNIEXPORT jint JNICALL
|
2020-06-27 22:11:24 -07:00
|
|
|
Java_edu_wpi_first_hal_simulation_SimDeviceDataJNI_registerSimDeviceCreatedCallback
|
2019-09-28 11:34:46 -07:00
|
|
|
(JNIEnv* env, jclass, jstring prefix, jobject callback,
|
|
|
|
|
jboolean initialNotify)
|
|
|
|
|
{
|
|
|
|
|
auto [uid, store] =
|
|
|
|
|
CallbackJNI::GetInstance().AllocateCallback(env, callback);
|
|
|
|
|
int32_t cuid = HALSIM_RegisterSimDeviceCreatedCallback(
|
|
|
|
|
JStringRef{env, prefix}.c_str(),
|
|
|
|
|
reinterpret_cast<void*>(static_cast<intptr_t>(uid)),
|
|
|
|
|
[](const char* name, void* param, HAL_SimDeviceHandle handle) {
|
|
|
|
|
int32_t uid = reinterpret_cast<intptr_t>(param);
|
|
|
|
|
CallbackJNI::GetInstance().SendDevice(uid, DeviceInfo{name, handle});
|
|
|
|
|
},
|
|
|
|
|
initialNotify);
|
|
|
|
|
store->SetCancel([cuid] { HALSIM_CancelSimDeviceCreatedCallback(cuid); });
|
|
|
|
|
return uid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
2020-06-27 22:11:24 -07:00
|
|
|
* Class: edu_wpi_first_hal_simulation_SimDeviceDataJNI
|
2019-09-28 11:34:46 -07:00
|
|
|
* Method: cancelSimDeviceCreatedCallback
|
|
|
|
|
* Signature: (I)V
|
|
|
|
|
*/
|
|
|
|
|
JNIEXPORT void JNICALL
|
2020-06-27 22:11:24 -07:00
|
|
|
Java_edu_wpi_first_hal_simulation_SimDeviceDataJNI_cancelSimDeviceCreatedCallback
|
2019-09-28 11:34:46 -07:00
|
|
|
(JNIEnv* env, jclass, jint uid)
|
|
|
|
|
{
|
|
|
|
|
CallbackJNI::GetInstance().FreeCallback(env, uid);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
2020-06-27 22:11:24 -07:00
|
|
|
* Class: edu_wpi_first_hal_simulation_SimDeviceDataJNI
|
2019-09-28 11:34:46 -07:00
|
|
|
* Method: registerSimDeviceFreedCallback
|
|
|
|
|
* Signature: (Ljava/lang/String;Ljava/lang/Object;)I
|
|
|
|
|
*/
|
|
|
|
|
JNIEXPORT jint JNICALL
|
2020-06-27 22:11:24 -07:00
|
|
|
Java_edu_wpi_first_hal_simulation_SimDeviceDataJNI_registerSimDeviceFreedCallback
|
2019-09-28 11:34:46 -07:00
|
|
|
(JNIEnv* env, jclass, jstring prefix, jobject callback)
|
|
|
|
|
{
|
|
|
|
|
auto [uid, store] =
|
|
|
|
|
CallbackJNI::GetInstance().AllocateCallback(env, callback);
|
|
|
|
|
int32_t cuid = HALSIM_RegisterSimDeviceFreedCallback(
|
|
|
|
|
JStringRef{env, prefix}.c_str(),
|
|
|
|
|
reinterpret_cast<void*>(static_cast<intptr_t>(uid)),
|
|
|
|
|
[](const char* name, void* param, HAL_SimDeviceHandle handle) {
|
|
|
|
|
int32_t uid = reinterpret_cast<intptr_t>(param);
|
|
|
|
|
CallbackJNI::GetInstance().SendDevice(uid, DeviceInfo{name, handle});
|
|
|
|
|
});
|
|
|
|
|
store->SetCancel([cuid] { HALSIM_CancelSimDeviceFreedCallback(cuid); });
|
|
|
|
|
return uid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
2020-06-27 22:11:24 -07:00
|
|
|
* Class: edu_wpi_first_hal_simulation_SimDeviceDataJNI
|
2019-09-28 11:34:46 -07:00
|
|
|
* Method: cancelSimDeviceFreedCallback
|
|
|
|
|
* Signature: (I)V
|
|
|
|
|
*/
|
|
|
|
|
JNIEXPORT void JNICALL
|
2020-06-27 22:11:24 -07:00
|
|
|
Java_edu_wpi_first_hal_simulation_SimDeviceDataJNI_cancelSimDeviceFreedCallback
|
2019-09-28 11:34:46 -07:00
|
|
|
(JNIEnv* env, jclass, jint uid)
|
|
|
|
|
{
|
|
|
|
|
CallbackJNI::GetInstance().FreeCallback(env, uid);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
2020-06-27 22:11:24 -07:00
|
|
|
* Class: edu_wpi_first_hal_simulation_SimDeviceDataJNI
|
2019-09-28 11:34:46 -07:00
|
|
|
* Method: getSimDeviceHandle
|
|
|
|
|
* Signature: (Ljava/lang/String;)I
|
|
|
|
|
*/
|
|
|
|
|
JNIEXPORT jint JNICALL
|
2020-06-27 22:11:24 -07:00
|
|
|
Java_edu_wpi_first_hal_simulation_SimDeviceDataJNI_getSimDeviceHandle
|
2019-09-28 11:34:46 -07:00
|
|
|
(JNIEnv* env, jclass, jstring name)
|
|
|
|
|
{
|
|
|
|
|
return HALSIM_GetSimDeviceHandle(JStringRef{env, name}.c_str());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
2020-06-27 22:11:24 -07:00
|
|
|
* Class: edu_wpi_first_hal_simulation_SimDeviceDataJNI
|
2019-09-28 11:34:46 -07:00
|
|
|
* Method: getSimValueDeviceHandle
|
|
|
|
|
* Signature: (I)I
|
|
|
|
|
*/
|
|
|
|
|
JNIEXPORT jint JNICALL
|
2020-06-27 22:11:24 -07:00
|
|
|
Java_edu_wpi_first_hal_simulation_SimDeviceDataJNI_getSimValueDeviceHandle
|
2019-09-28 11:34:46 -07:00
|
|
|
(JNIEnv*, jclass, jint handle)
|
|
|
|
|
{
|
|
|
|
|
return HALSIM_GetSimValueDeviceHandle(handle);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
2020-06-27 22:11:24 -07:00
|
|
|
* Class: edu_wpi_first_hal_simulation_SimDeviceDataJNI
|
2019-09-28 11:34:46 -07:00
|
|
|
* Method: enumerateSimDevices
|
|
|
|
|
* Signature: (Ljava/lang/String;)[Ljava/lang/Object;
|
|
|
|
|
*/
|
|
|
|
|
JNIEXPORT jobjectArray JNICALL
|
2020-06-27 22:11:24 -07:00
|
|
|
Java_edu_wpi_first_hal_simulation_SimDeviceDataJNI_enumerateSimDevices
|
2019-09-28 11:34:46 -07:00
|
|
|
(JNIEnv* env, jclass, jstring prefix)
|
|
|
|
|
{
|
|
|
|
|
// get values
|
|
|
|
|
std::vector<DeviceInfo> arr;
|
|
|
|
|
HALSIM_EnumerateSimDevices(
|
|
|
|
|
JStringRef{env, prefix}.c_str(), &arr,
|
|
|
|
|
[](const char* name, void* param, HAL_SimDeviceHandle handle) {
|
|
|
|
|
auto arr = static_cast<std::vector<DeviceInfo>*>(param);
|
|
|
|
|
arr->emplace_back(name, handle);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// convert to java
|
|
|
|
|
size_t numElems = arr.size();
|
|
|
|
|
jobjectArray jarr =
|
|
|
|
|
env->NewObjectArray(arr.size(), simDeviceInfoCls, nullptr);
|
|
|
|
|
if (!jarr) return nullptr;
|
|
|
|
|
for (size_t i = 0; i < numElems; ++i) {
|
|
|
|
|
JLocal<jobject> elem{env, arr[i].MakeJava(env)};
|
|
|
|
|
env->SetObjectArrayElement(jarr, i, elem.obj());
|
|
|
|
|
}
|
|
|
|
|
return jarr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
2020-06-27 22:11:24 -07:00
|
|
|
* Class: edu_wpi_first_hal_simulation_SimDeviceDataJNI
|
2019-09-28 11:34:46 -07:00
|
|
|
* Method: registerSimValueCreatedCallback
|
|
|
|
|
* Signature: (ILjava/lang/Object;Z)I
|
|
|
|
|
*/
|
|
|
|
|
JNIEXPORT jint JNICALL
|
2020-06-27 22:11:24 -07:00
|
|
|
Java_edu_wpi_first_hal_simulation_SimDeviceDataJNI_registerSimValueCreatedCallback
|
2019-09-28 11:34:46 -07:00
|
|
|
(JNIEnv* env, jclass, jint device, jobject callback, jboolean initialNotify)
|
|
|
|
|
{
|
|
|
|
|
auto [uid, store] =
|
|
|
|
|
CallbackJNI::GetInstance().AllocateCallback(env, callback);
|
|
|
|
|
int32_t cuid = HALSIM_RegisterSimValueCreatedCallback(
|
|
|
|
|
device, reinterpret_cast<void*>(static_cast<intptr_t>(uid)),
|
|
|
|
|
[](const char* name, void* param, HAL_SimValueHandle handle,
|
|
|
|
|
HAL_Bool readonly, const HAL_Value* value) {
|
|
|
|
|
int32_t uid = reinterpret_cast<intptr_t>(param);
|
|
|
|
|
CallbackJNI::GetInstance().SendValue(
|
|
|
|
|
uid, ValueInfo{name, handle, static_cast<bool>(readonly), *value});
|
|
|
|
|
},
|
|
|
|
|
initialNotify);
|
|
|
|
|
store->SetCancel([cuid] { HALSIM_CancelSimValueCreatedCallback(cuid); });
|
|
|
|
|
return uid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
2020-06-27 22:11:24 -07:00
|
|
|
* Class: edu_wpi_first_hal_simulation_SimDeviceDataJNI
|
2019-09-28 11:34:46 -07:00
|
|
|
* Method: cancelSimValueCreatedCallback
|
|
|
|
|
* Signature: (I)V
|
|
|
|
|
*/
|
|
|
|
|
JNIEXPORT void JNICALL
|
2020-06-27 22:11:24 -07:00
|
|
|
Java_edu_wpi_first_hal_simulation_SimDeviceDataJNI_cancelSimValueCreatedCallback
|
2019-09-28 11:34:46 -07:00
|
|
|
(JNIEnv* env, jclass, jint uid)
|
|
|
|
|
{
|
|
|
|
|
CallbackJNI::GetInstance().FreeCallback(env, uid);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
2020-06-27 22:11:24 -07:00
|
|
|
* Class: edu_wpi_first_hal_simulation_SimDeviceDataJNI
|
2019-09-28 11:34:46 -07:00
|
|
|
* Method: registerSimValueChangedCallback
|
|
|
|
|
* Signature: (ILjava/lang/Object;Z)I
|
|
|
|
|
*/
|
|
|
|
|
JNIEXPORT jint JNICALL
|
2020-06-27 22:11:24 -07:00
|
|
|
Java_edu_wpi_first_hal_simulation_SimDeviceDataJNI_registerSimValueChangedCallback
|
2019-09-28 11:34:46 -07:00
|
|
|
(JNIEnv* env, jclass, jint handle, jobject callback, jboolean initialNotify)
|
|
|
|
|
{
|
|
|
|
|
auto [uid, store] =
|
|
|
|
|
CallbackJNI::GetInstance().AllocateCallback(env, callback);
|
|
|
|
|
int32_t cuid = HALSIM_RegisterSimValueChangedCallback(
|
|
|
|
|
handle, reinterpret_cast<void*>(static_cast<intptr_t>(uid)),
|
|
|
|
|
[](const char* name, void* param, HAL_SimValueHandle handle,
|
|
|
|
|
HAL_Bool readonly, const HAL_Value* value) {
|
|
|
|
|
int32_t uid = reinterpret_cast<intptr_t>(param);
|
|
|
|
|
CallbackJNI::GetInstance().SendValue(
|
|
|
|
|
uid, ValueInfo{name, handle, static_cast<bool>(readonly), *value});
|
|
|
|
|
},
|
|
|
|
|
initialNotify);
|
|
|
|
|
store->SetCancel([cuid] { HALSIM_CancelSimValueChangedCallback(cuid); });
|
|
|
|
|
return uid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
2020-06-27 22:11:24 -07:00
|
|
|
* Class: edu_wpi_first_hal_simulation_SimDeviceDataJNI
|
2019-09-28 11:34:46 -07:00
|
|
|
* Method: cancelSimValueChangedCallback
|
|
|
|
|
* Signature: (I)V
|
|
|
|
|
*/
|
|
|
|
|
JNIEXPORT void JNICALL
|
2020-06-27 22:11:24 -07:00
|
|
|
Java_edu_wpi_first_hal_simulation_SimDeviceDataJNI_cancelSimValueChangedCallback
|
2019-09-28 11:34:46 -07:00
|
|
|
(JNIEnv* env, jclass, jint uid)
|
|
|
|
|
{
|
|
|
|
|
CallbackJNI::GetInstance().FreeCallback(env, uid);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
2020-06-27 22:11:24 -07:00
|
|
|
* Class: edu_wpi_first_hal_simulation_SimDeviceDataJNI
|
2019-09-28 11:34:46 -07:00
|
|
|
* Method: getSimValueHandle
|
|
|
|
|
* Signature: (ILjava/lang/String;)I
|
|
|
|
|
*/
|
|
|
|
|
JNIEXPORT jint JNICALL
|
2020-06-27 22:11:24 -07:00
|
|
|
Java_edu_wpi_first_hal_simulation_SimDeviceDataJNI_getSimValueHandle
|
2019-09-28 11:34:46 -07:00
|
|
|
(JNIEnv* env, jclass, jint device, jstring name)
|
|
|
|
|
{
|
|
|
|
|
return HALSIM_GetSimValueHandle(device, JStringRef{env, name}.c_str());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
2020-06-27 22:11:24 -07:00
|
|
|
* Class: edu_wpi_first_hal_simulation_SimDeviceDataJNI
|
2019-09-28 11:34:46 -07:00
|
|
|
* Method: enumerateSimValues
|
|
|
|
|
* Signature: (I)[Ljava/lang/Object;
|
|
|
|
|
*/
|
|
|
|
|
JNIEXPORT jobjectArray JNICALL
|
2020-06-27 22:11:24 -07:00
|
|
|
Java_edu_wpi_first_hal_simulation_SimDeviceDataJNI_enumerateSimValues
|
2019-09-28 11:34:46 -07:00
|
|
|
(JNIEnv* env, jclass, jint device)
|
|
|
|
|
{
|
|
|
|
|
// get values
|
|
|
|
|
std::vector<ValueInfo> arr;
|
|
|
|
|
HALSIM_EnumerateSimValues(
|
|
|
|
|
device, &arr,
|
|
|
|
|
[](const char* name, void* param, HAL_SimValueHandle handle,
|
|
|
|
|
HAL_Bool readonly, const HAL_Value* value) {
|
|
|
|
|
auto arr = static_cast<std::vector<ValueInfo>*>(param);
|
|
|
|
|
arr->emplace_back(name, handle, readonly, *value);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// convert to java
|
|
|
|
|
size_t numElems = arr.size();
|
|
|
|
|
jobjectArray jarr = env->NewObjectArray(arr.size(), simValueInfoCls, nullptr);
|
|
|
|
|
if (!jarr) return nullptr;
|
|
|
|
|
for (size_t i = 0; i < numElems; ++i) {
|
|
|
|
|
JLocal<jobject> elem{env, arr[i].MakeJava(env)};
|
|
|
|
|
env->SetObjectArrayElement(jarr, i, elem.obj());
|
|
|
|
|
}
|
|
|
|
|
return jarr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
2020-06-27 22:11:24 -07:00
|
|
|
* Class: edu_wpi_first_hal_simulation_SimDeviceDataJNI
|
2019-09-28 11:34:46 -07:00
|
|
|
* Method: getSimValueEnumOptions
|
|
|
|
|
* Signature: (I)[Ljava/lang/Object;
|
|
|
|
|
*/
|
|
|
|
|
JNIEXPORT jobjectArray JNICALL
|
2020-06-27 22:11:24 -07:00
|
|
|
Java_edu_wpi_first_hal_simulation_SimDeviceDataJNI_getSimValueEnumOptions
|
2019-09-28 11:34:46 -07:00
|
|
|
(JNIEnv* env, jclass, jint handle)
|
|
|
|
|
{
|
|
|
|
|
static JClass stringCls{env, "java/lang/String"};
|
|
|
|
|
if (!stringCls) return nullptr;
|
|
|
|
|
int32_t numElems = 0;
|
|
|
|
|
const char** elems = HALSIM_GetSimValueEnumOptions(handle, &numElems);
|
|
|
|
|
jobjectArray jarr = env->NewObjectArray(numElems, stringCls, nullptr);
|
|
|
|
|
if (!jarr) return nullptr;
|
|
|
|
|
for (int32_t i = 0; i < numElems; ++i) {
|
|
|
|
|
JLocal<jstring> elem{env, MakeJString(env, elems[i])};
|
|
|
|
|
env->SetObjectArrayElement(jarr, i, elem.obj());
|
|
|
|
|
}
|
|
|
|
|
return jarr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
2020-06-27 22:11:24 -07:00
|
|
|
* Class: edu_wpi_first_hal_simulation_SimDeviceDataJNI
|
2019-09-28 11:34:46 -07:00
|
|
|
* Method: resetSimDeviceData
|
|
|
|
|
* Signature: ()V
|
|
|
|
|
*/
|
|
|
|
|
JNIEXPORT void JNICALL
|
2020-06-27 22:11:24 -07:00
|
|
|
Java_edu_wpi_first_hal_simulation_SimDeviceDataJNI_resetSimDeviceData
|
2019-09-28 11:34:46 -07:00
|
|
|
(JNIEnv*, jclass)
|
|
|
|
|
{
|
|
|
|
|
HALSIM_ResetSimDeviceData();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // extern "C"
|