hamlib 0.2.7 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +77 -6
- package/binding.gyp +8 -2
- package/docs/build-hamlib-from-source.md +640 -0
- package/docs/prebuilt-bundling.md +347 -0
- package/index.d.ts +126 -6
- package/lib/index.js +162 -1
- package/package.json +5 -2
- package/prebuilds/darwin-arm64/libhamlib.4.dylib +0 -0
- package/prebuilds/darwin-arm64/node.napi.node +0 -0
- package/prebuilds/darwin-x64/libhamlib.4.dylib +0 -0
- package/prebuilds/darwin-x64/node.napi.node +0 -0
- package/prebuilds/linux-arm64/libhamlib.so +0 -0
- package/prebuilds/linux-arm64/libhamlib.so.4 +0 -0
- package/prebuilds/linux-arm64/libhamlib.so.4.0.7 +0 -0
- package/prebuilds/linux-arm64/node.napi.node +0 -0
- package/prebuilds/linux-x64/libhamlib.so +0 -0
- package/prebuilds/linux-x64/libhamlib.so.4 +0 -0
- package/prebuilds/linux-x64/libhamlib.so.4.0.7 +0 -0
- package/prebuilds/linux-x64/node.napi.node +0 -0
- package/prebuilds/win32-x64/hamlib_shim.dll +0 -0
- package/prebuilds/win32-x64/node.napi.node +0 -0
- package/src/hamlib.cpp +291 -10
- package/src/hamlib.h +14 -0
- package/src/shim/hamlib_shim.c +135 -0
- package/src/shim/hamlib_shim.h +54 -0
package/src/hamlib.cpp
CHANGED
|
@@ -4,6 +4,9 @@
|
|
|
4
4
|
#include <vector>
|
|
5
5
|
#include <memory>
|
|
6
6
|
#include <algorithm>
|
|
7
|
+
#include <chrono>
|
|
8
|
+
#include <cstdio>
|
|
9
|
+
#include <exception>
|
|
7
10
|
|
|
8
11
|
// 安全宏 - 检查RIG指针有效性,防止空指针解引用和已销毁对象访问
|
|
9
12
|
#define CHECK_RIG_VALID() \
|
|
@@ -45,10 +48,13 @@ public:
|
|
|
45
48
|
} else {
|
|
46
49
|
shim_rig_set_freq_callback(hamlib_instance_->my_rig, NodeHamLib::freq_change_cb, hamlib_instance_);
|
|
47
50
|
auto ppt_cb = +[](void* handle, int vfo, int ptt, void* arg) -> int {
|
|
48
|
-
|
|
51
|
+
(void)handle;
|
|
52
|
+
(void)vfo;
|
|
53
|
+
(void)ptt;
|
|
54
|
+
(void)arg;
|
|
49
55
|
return 0;
|
|
50
56
|
};
|
|
51
|
-
|
|
57
|
+
shim_rig_set_ptt_callback(hamlib_instance_->my_rig, ppt_cb, NULL);
|
|
52
58
|
shim_rig_set_trn(hamlib_instance_->my_rig, SHIM_RIG_TRN_POLL);
|
|
53
59
|
hamlib_instance_->rig_is_open = true;
|
|
54
60
|
}
|
|
@@ -280,7 +286,11 @@ public:
|
|
|
280
286
|
void Execute() override {
|
|
281
287
|
CHECK_RIG_VALID();
|
|
282
288
|
|
|
283
|
-
|
|
289
|
+
if (shim_rig_level_is_float(level_type_)) {
|
|
290
|
+
result_code_ = shim_rig_set_level_f(hamlib_instance_->my_rig, SHIM_RIG_VFO_CURR, level_type_, value_);
|
|
291
|
+
} else {
|
|
292
|
+
result_code_ = shim_rig_set_level_i(hamlib_instance_->my_rig, SHIM_RIG_VFO_CURR, level_type_, static_cast<int>(value_));
|
|
293
|
+
}
|
|
284
294
|
if (result_code_ != SHIM_RIG_OK) {
|
|
285
295
|
error_message_ = shim_rigerror(result_code_);
|
|
286
296
|
}
|
|
@@ -2170,7 +2180,7 @@ private:
|
|
|
2170
2180
|
|
|
2171
2181
|
// Helper function to parse VFO parameter from JavaScript
|
|
2172
2182
|
int parseVfoParameter(const Napi::CallbackInfo& info, int index, int defaultVfo = SHIM_RIG_VFO_CURR) {
|
|
2173
|
-
if (info.Length() > index && info[index].IsString()) {
|
|
2183
|
+
if (info.Length() > static_cast<size_t>(index) && info[index].IsString()) {
|
|
2174
2184
|
std::string vfoStr = info[index].As<Napi::String>().Utf8Value();
|
|
2175
2185
|
if (vfoStr == "VFO-A") {
|
|
2176
2186
|
return SHIM_RIG_VFO_A;
|
|
@@ -2268,6 +2278,8 @@ NodeHamLib::NodeHamLib(const Napi::CallbackInfo & info): ObjectWrap(info) {
|
|
|
2268
2278
|
|
|
2269
2279
|
// 析构函数 - 确保资源正确清理
|
|
2270
2280
|
NodeHamLib::~NodeHamLib() {
|
|
2281
|
+
StopSpectrumStreamInternal();
|
|
2282
|
+
|
|
2271
2283
|
// 如果rig指针存在,执行清理
|
|
2272
2284
|
if (my_rig) {
|
|
2273
2285
|
// 如果rig是打开状态,先关闭
|
|
@@ -2281,10 +2293,70 @@ NodeHamLib::~NodeHamLib() {
|
|
|
2281
2293
|
}
|
|
2282
2294
|
}
|
|
2283
2295
|
|
|
2296
|
+
int NodeHamLib::spectrum_line_cb(void* handle, const shim_spectrum_line_t* line, void* arg) {
|
|
2297
|
+
(void)handle;
|
|
2298
|
+
NodeHamLib* instance = static_cast<NodeHamLib*>(arg);
|
|
2299
|
+
if (!instance || !line) {
|
|
2300
|
+
return 0;
|
|
2301
|
+
}
|
|
2302
|
+
instance->EmitSpectrumLine(*line);
|
|
2303
|
+
return 0;
|
|
2304
|
+
}
|
|
2305
|
+
|
|
2306
|
+
void NodeHamLib::EmitSpectrumLine(const shim_spectrum_line_t& line) {
|
|
2307
|
+
if (!spectrum_tsfn_) {
|
|
2308
|
+
return;
|
|
2309
|
+
}
|
|
2310
|
+
|
|
2311
|
+
auto* line_copy = new shim_spectrum_line_t(line);
|
|
2312
|
+
napi_status status = spectrum_tsfn_.BlockingCall(
|
|
2313
|
+
line_copy,
|
|
2314
|
+
[](Napi::Env env, Napi::Function callback, shim_spectrum_line_t* data) {
|
|
2315
|
+
Napi::Object lineObject = Napi::Object::New(env);
|
|
2316
|
+
lineObject.Set("scopeId", Napi::Number::New(env, data->id));
|
|
2317
|
+
lineObject.Set("dataLevelMin", Napi::Number::New(env, data->data_level_min));
|
|
2318
|
+
lineObject.Set("dataLevelMax", Napi::Number::New(env, data->data_level_max));
|
|
2319
|
+
lineObject.Set("signalStrengthMin", Napi::Number::New(env, data->signal_strength_min));
|
|
2320
|
+
lineObject.Set("signalStrengthMax", Napi::Number::New(env, data->signal_strength_max));
|
|
2321
|
+
lineObject.Set("mode", Napi::Number::New(env, data->spectrum_mode));
|
|
2322
|
+
lineObject.Set("centerFreq", Napi::Number::New(env, data->center_freq));
|
|
2323
|
+
lineObject.Set("spanHz", Napi::Number::New(env, data->span_freq));
|
|
2324
|
+
lineObject.Set("lowEdgeFreq", Napi::Number::New(env, data->low_edge_freq));
|
|
2325
|
+
lineObject.Set("highEdgeFreq", Napi::Number::New(env, data->high_edge_freq));
|
|
2326
|
+
lineObject.Set("dataLength", Napi::Number::New(env, data->data_length));
|
|
2327
|
+
lineObject.Set("timestamp", Napi::Number::New(env, static_cast<double>(std::chrono::duration_cast<std::chrono::milliseconds>(
|
|
2328
|
+
std::chrono::system_clock::now().time_since_epoch()).count())));
|
|
2329
|
+
lineObject.Set("data", Napi::Buffer<unsigned char>::Copy(env, data->data, static_cast<size_t>(data->data_length)));
|
|
2330
|
+
callback.Call({ lineObject });
|
|
2331
|
+
delete data;
|
|
2332
|
+
});
|
|
2333
|
+
|
|
2334
|
+
if (status != napi_ok) {
|
|
2335
|
+
delete line_copy;
|
|
2336
|
+
return;
|
|
2337
|
+
}
|
|
2338
|
+
}
|
|
2339
|
+
|
|
2340
|
+
void NodeHamLib::StopSpectrumStreamInternal() {
|
|
2341
|
+
std::lock_guard<std::mutex> lock(spectrum_mutex_);
|
|
2342
|
+
if (spectrum_stream_running_) {
|
|
2343
|
+
shim_rig_set_spectrum_callback(my_rig, nullptr, nullptr);
|
|
2344
|
+
spectrum_stream_running_ = false;
|
|
2345
|
+
}
|
|
2346
|
+
if (spectrum_tsfn_) {
|
|
2347
|
+
spectrum_tsfn_.Release();
|
|
2348
|
+
spectrum_tsfn_ = Napi::ThreadSafeFunction();
|
|
2349
|
+
}
|
|
2350
|
+
}
|
|
2351
|
+
|
|
2284
2352
|
int NodeHamLib::freq_change_cb(void *handle, int vfo, double freq, void* arg) {
|
|
2353
|
+
(void)handle;
|
|
2354
|
+
(void)vfo;
|
|
2355
|
+
(void)freq;
|
|
2285
2356
|
auto instance = static_cast<NodeHamLib*>(arg);
|
|
2286
|
-
|
|
2287
|
-
|
|
2357
|
+
if (!instance) {
|
|
2358
|
+
return 0;
|
|
2359
|
+
}
|
|
2288
2360
|
//Napi::Function emit = instance->m_currentInfo[0].Get("emit").As<Napi::Function>();
|
|
2289
2361
|
// Napi::Function emit = instance->m_currentInfo[0]->This().As<Napi::Object>().Get("emit").As<Napi::Function>();
|
|
2290
2362
|
//emit.Call(instance->m_currentInfo->This(), { Napi::String::New(env, "frequency_change"), Napi::Number::New(env, freq) });
|
|
@@ -2293,7 +2365,6 @@ int NodeHamLib::freq_change_cb(void *handle, int vfo, double freq, void* arg) {
|
|
|
2293
2365
|
//auto fn = global.Get("process").As<Napi::Object>().Get("emit").As<Napi::Function>();
|
|
2294
2366
|
//fn.Call({Napi::Number::New(env, freq)});
|
|
2295
2367
|
return 0;
|
|
2296
|
-
return 0;
|
|
2297
2368
|
}
|
|
2298
2369
|
|
|
2299
2370
|
Napi::Value NodeHamLib::Open(const Napi::CallbackInfo & info) {
|
|
@@ -2565,6 +2636,8 @@ Napi::Value NodeHamLib::Close(const Napi::CallbackInfo & info) {
|
|
|
2565
2636
|
.ThrowAsJavaScriptException();
|
|
2566
2637
|
return env.Null();
|
|
2567
2638
|
}
|
|
2639
|
+
|
|
2640
|
+
StopSpectrumStreamInternal();
|
|
2568
2641
|
|
|
2569
2642
|
CloseAsyncWorker* worker = new CloseAsyncWorker(env, this);
|
|
2570
2643
|
worker->Queue();
|
|
@@ -2574,6 +2647,8 @@ Napi::Value NodeHamLib::Close(const Napi::CallbackInfo & info) {
|
|
|
2574
2647
|
|
|
2575
2648
|
Napi::Value NodeHamLib::Destroy(const Napi::CallbackInfo & info) {
|
|
2576
2649
|
Napi::Env env = info.Env();
|
|
2650
|
+
|
|
2651
|
+
StopSpectrumStreamInternal();
|
|
2577
2652
|
|
|
2578
2653
|
DestroyAsyncWorker* worker = new DestroyAsyncWorker(env, this);
|
|
2579
2654
|
worker->Queue();
|
|
@@ -2912,16 +2987,54 @@ Napi::Value NodeHamLib::SetLevel(const Napi::CallbackInfo & info) {
|
|
|
2912
2987
|
levelType = SHIM_RIG_LEVEL_VOXDELAY;
|
|
2913
2988
|
} else if (levelTypeStr == "ANTIVOX") {
|
|
2914
2989
|
levelType = SHIM_RIG_LEVEL_ANTIVOX;
|
|
2990
|
+
} else if (levelTypeStr == "SPECTRUM_MODE") {
|
|
2991
|
+
levelType = SHIM_RIG_LEVEL_SPECTRUM_MODE;
|
|
2992
|
+
} else if (levelTypeStr == "SPECTRUM_SPAN") {
|
|
2993
|
+
levelType = SHIM_RIG_LEVEL_SPECTRUM_SPAN;
|
|
2994
|
+
} else if (levelTypeStr == "SPECTRUM_EDGE_LOW") {
|
|
2995
|
+
levelType = SHIM_RIG_LEVEL_SPECTRUM_EDGE_LOW;
|
|
2996
|
+
} else if (levelTypeStr == "SPECTRUM_EDGE_HIGH") {
|
|
2997
|
+
levelType = SHIM_RIG_LEVEL_SPECTRUM_EDGE_HIGH;
|
|
2998
|
+
} else if (levelTypeStr == "SPECTRUM_SPEED") {
|
|
2999
|
+
levelType = SHIM_RIG_LEVEL_SPECTRUM_SPEED;
|
|
3000
|
+
} else if (levelTypeStr == "SPECTRUM_REF") {
|
|
3001
|
+
levelType = SHIM_RIG_LEVEL_SPECTRUM_REF;
|
|
3002
|
+
} else if (levelTypeStr == "SPECTRUM_AVG") {
|
|
3003
|
+
levelType = SHIM_RIG_LEVEL_SPECTRUM_AVG;
|
|
3004
|
+
} else if (levelTypeStr == "SPECTRUM_ATT") {
|
|
3005
|
+
levelType = SHIM_RIG_LEVEL_SPECTRUM_ATT;
|
|
2915
3006
|
} else {
|
|
2916
3007
|
Napi::TypeError::New(env, "Invalid level type").ThrowAsJavaScriptException();
|
|
2917
3008
|
return env.Null();
|
|
2918
3009
|
}
|
|
2919
3010
|
|
|
2920
|
-
|
|
3011
|
+
const bool isSpectrumLevel =
|
|
3012
|
+
levelType == SHIM_RIG_LEVEL_SPECTRUM_MODE
|
|
3013
|
+
|| levelType == SHIM_RIG_LEVEL_SPECTRUM_SPAN
|
|
3014
|
+
|| levelType == SHIM_RIG_LEVEL_SPECTRUM_EDGE_LOW
|
|
3015
|
+
|| levelType == SHIM_RIG_LEVEL_SPECTRUM_EDGE_HIGH
|
|
3016
|
+
|| levelType == SHIM_RIG_LEVEL_SPECTRUM_SPEED
|
|
3017
|
+
|| levelType == SHIM_RIG_LEVEL_SPECTRUM_REF
|
|
3018
|
+
|| levelType == SHIM_RIG_LEVEL_SPECTRUM_AVG
|
|
3019
|
+
|| levelType == SHIM_RIG_LEVEL_SPECTRUM_ATT;
|
|
3020
|
+
|
|
3021
|
+
if (isSpectrumLevel) {
|
|
3022
|
+
Napi::Promise::Deferred deferred = Napi::Promise::Deferred::New(env);
|
|
3023
|
+
int result = shim_rig_level_is_float(levelType)
|
|
3024
|
+
? shim_rig_set_level_f(my_rig, SHIM_RIG_VFO_CURR, levelType, static_cast<float>(levelValue))
|
|
3025
|
+
: shim_rig_set_level_i(my_rig, SHIM_RIG_VFO_CURR, levelType, static_cast<int>(levelValue));
|
|
3026
|
+
|
|
3027
|
+
if (result != SHIM_RIG_OK) {
|
|
3028
|
+
deferred.Reject(Napi::Error::New(env, shim_rigerror(result)).Value());
|
|
3029
|
+
} else {
|
|
3030
|
+
deferred.Resolve(Napi::Number::New(env, result));
|
|
3031
|
+
}
|
|
3032
|
+
return deferred.Promise();
|
|
3033
|
+
}
|
|
2921
3034
|
|
|
3035
|
+
float val = static_cast<float>(levelValue);
|
|
2922
3036
|
SetLevelAsyncWorker* worker = new SetLevelAsyncWorker(env, this, levelType, val);
|
|
2923
3037
|
worker->Queue();
|
|
2924
|
-
|
|
2925
3038
|
return worker->GetPromise();
|
|
2926
3039
|
}
|
|
2927
3040
|
|
|
@@ -2972,6 +3085,50 @@ Napi::Value NodeHamLib::GetLevel(const Napi::CallbackInfo & info) {
|
|
|
2972
3085
|
levelType = SHIM_RIG_LEVEL_ID_METER;
|
|
2973
3086
|
} else if (levelTypeStr == "TEMP_METER") {
|
|
2974
3087
|
levelType = SHIM_RIG_LEVEL_TEMP_METER;
|
|
3088
|
+
} else if (levelTypeStr == "NR") {
|
|
3089
|
+
levelType = SHIM_RIG_LEVEL_NR;
|
|
3090
|
+
} else if (levelTypeStr == "AF") {
|
|
3091
|
+
levelType = SHIM_RIG_LEVEL_AF;
|
|
3092
|
+
} else if (levelTypeStr == "RF") {
|
|
3093
|
+
levelType = SHIM_RIG_LEVEL_RF;
|
|
3094
|
+
} else if (levelTypeStr == "SQL") {
|
|
3095
|
+
levelType = SHIM_RIG_LEVEL_SQL;
|
|
3096
|
+
} else if (levelTypeStr == "RFPOWER") {
|
|
3097
|
+
levelType = SHIM_RIG_LEVEL_RFPOWER;
|
|
3098
|
+
} else if (levelTypeStr == "MICGAIN") {
|
|
3099
|
+
levelType = SHIM_RIG_LEVEL_MICGAIN;
|
|
3100
|
+
} else if (levelTypeStr == "VOXDELAY") {
|
|
3101
|
+
levelType = SHIM_RIG_LEVEL_VOXDELAY;
|
|
3102
|
+
} else if (levelTypeStr == "PBT_IN") {
|
|
3103
|
+
levelType = SHIM_RIG_LEVEL_PBT_IN;
|
|
3104
|
+
} else if (levelTypeStr == "PBT_OUT") {
|
|
3105
|
+
levelType = SHIM_RIG_LEVEL_PBT_OUT;
|
|
3106
|
+
} else if (levelTypeStr == "CWPITCH") {
|
|
3107
|
+
levelType = SHIM_RIG_LEVEL_CWPITCH;
|
|
3108
|
+
} else if (levelTypeStr == "COMP") {
|
|
3109
|
+
levelType = SHIM_RIG_LEVEL_COMP;
|
|
3110
|
+
} else if (levelTypeStr == "AGC") {
|
|
3111
|
+
levelType = SHIM_RIG_LEVEL_AGC;
|
|
3112
|
+
} else if (levelTypeStr == "VOXGAIN") {
|
|
3113
|
+
levelType = SHIM_RIG_LEVEL_VOXGAIN;
|
|
3114
|
+
} else if (levelTypeStr == "ANTIVOX") {
|
|
3115
|
+
levelType = SHIM_RIG_LEVEL_ANTIVOX;
|
|
3116
|
+
} else if (levelTypeStr == "SPECTRUM_MODE") {
|
|
3117
|
+
levelType = SHIM_RIG_LEVEL_SPECTRUM_MODE;
|
|
3118
|
+
} else if (levelTypeStr == "SPECTRUM_SPAN") {
|
|
3119
|
+
levelType = SHIM_RIG_LEVEL_SPECTRUM_SPAN;
|
|
3120
|
+
} else if (levelTypeStr == "SPECTRUM_EDGE_LOW") {
|
|
3121
|
+
levelType = SHIM_RIG_LEVEL_SPECTRUM_EDGE_LOW;
|
|
3122
|
+
} else if (levelTypeStr == "SPECTRUM_EDGE_HIGH") {
|
|
3123
|
+
levelType = SHIM_RIG_LEVEL_SPECTRUM_EDGE_HIGH;
|
|
3124
|
+
} else if (levelTypeStr == "SPECTRUM_SPEED") {
|
|
3125
|
+
levelType = SHIM_RIG_LEVEL_SPECTRUM_SPEED;
|
|
3126
|
+
} else if (levelTypeStr == "SPECTRUM_REF") {
|
|
3127
|
+
levelType = SHIM_RIG_LEVEL_SPECTRUM_REF;
|
|
3128
|
+
} else if (levelTypeStr == "SPECTRUM_AVG") {
|
|
3129
|
+
levelType = SHIM_RIG_LEVEL_SPECTRUM_AVG;
|
|
3130
|
+
} else if (levelTypeStr == "SPECTRUM_ATT") {
|
|
3131
|
+
levelType = SHIM_RIG_LEVEL_SPECTRUM_ATT;
|
|
2975
3132
|
} else {
|
|
2976
3133
|
Napi::TypeError::New(env, "Invalid level type").ThrowAsJavaScriptException();
|
|
2977
3134
|
return env.Null();
|
|
@@ -3032,6 +3189,14 @@ Napi::Value NodeHamLib::GetSupportedLevels(const Napi::CallbackInfo & info) {
|
|
|
3032
3189
|
if (levels & SHIM_RIG_LEVEL_COMP_METER) levelArray[index++] = Napi::String::New(env, "COMP_METER");
|
|
3033
3190
|
if (levels & SHIM_RIG_LEVEL_VD_METER) levelArray[index++] = Napi::String::New(env, "VD_METER");
|
|
3034
3191
|
if (levels & SHIM_RIG_LEVEL_ID_METER) levelArray[index++] = Napi::String::New(env, "ID_METER");
|
|
3192
|
+
if (levels & SHIM_RIG_LEVEL_SPECTRUM_MODE) levelArray[index++] = Napi::String::New(env, "SPECTRUM_MODE");
|
|
3193
|
+
if (levels & SHIM_RIG_LEVEL_SPECTRUM_SPAN) levelArray[index++] = Napi::String::New(env, "SPECTRUM_SPAN");
|
|
3194
|
+
if (levels & SHIM_RIG_LEVEL_SPECTRUM_EDGE_LOW) levelArray[index++] = Napi::String::New(env, "SPECTRUM_EDGE_LOW");
|
|
3195
|
+
if (levels & SHIM_RIG_LEVEL_SPECTRUM_EDGE_HIGH) levelArray[index++] = Napi::String::New(env, "SPECTRUM_EDGE_HIGH");
|
|
3196
|
+
if (levels & SHIM_RIG_LEVEL_SPECTRUM_SPEED) levelArray[index++] = Napi::String::New(env, "SPECTRUM_SPEED");
|
|
3197
|
+
if (levels & SHIM_RIG_LEVEL_SPECTRUM_REF) levelArray[index++] = Napi::String::New(env, "SPECTRUM_REF");
|
|
3198
|
+
if (levels & SHIM_RIG_LEVEL_SPECTRUM_AVG) levelArray[index++] = Napi::String::New(env, "SPECTRUM_AVG");
|
|
3199
|
+
if (levels & SHIM_RIG_LEVEL_SPECTRUM_ATT) levelArray[index++] = Napi::String::New(env, "SPECTRUM_ATT");
|
|
3035
3200
|
if (levels & SHIM_RIG_LEVEL_TEMP_METER) levelArray[index++] = Napi::String::New(env, "TEMP_METER");
|
|
3036
3201
|
|
|
3037
3202
|
return levelArray;
|
|
@@ -3112,6 +3277,12 @@ Napi::Value NodeHamLib::SetFunction(const Napi::CallbackInfo & info) {
|
|
|
3112
3277
|
funcType = SHIM_RIG_FUNC_RESUME;
|
|
3113
3278
|
} else if (funcTypeStr == "TBURST") {
|
|
3114
3279
|
funcType = SHIM_RIG_FUNC_TBURST;
|
|
3280
|
+
} else if (funcTypeStr == "TRANSCEIVE") {
|
|
3281
|
+
funcType = SHIM_RIG_FUNC_TRANSCEIVE;
|
|
3282
|
+
} else if (funcTypeStr == "SPECTRUM") {
|
|
3283
|
+
funcType = SHIM_RIG_FUNC_SPECTRUM;
|
|
3284
|
+
} else if (funcTypeStr == "SPECTRUM_HOLD") {
|
|
3285
|
+
funcType = SHIM_RIG_FUNC_SPECTRUM_HOLD;
|
|
3115
3286
|
} else {
|
|
3116
3287
|
Napi::TypeError::New(env, "Invalid function type").ThrowAsJavaScriptException();
|
|
3117
3288
|
return env.Null();
|
|
@@ -3196,6 +3367,12 @@ Napi::Value NodeHamLib::GetFunction(const Napi::CallbackInfo & info) {
|
|
|
3196
3367
|
funcType = SHIM_RIG_FUNC_RESUME;
|
|
3197
3368
|
} else if (funcTypeStr == "TBURST") {
|
|
3198
3369
|
funcType = SHIM_RIG_FUNC_TBURST;
|
|
3370
|
+
} else if (funcTypeStr == "TRANSCEIVE") {
|
|
3371
|
+
funcType = SHIM_RIG_FUNC_TRANSCEIVE;
|
|
3372
|
+
} else if (funcTypeStr == "SPECTRUM") {
|
|
3373
|
+
funcType = SHIM_RIG_FUNC_SPECTRUM;
|
|
3374
|
+
} else if (funcTypeStr == "SPECTRUM_HOLD") {
|
|
3375
|
+
funcType = SHIM_RIG_FUNC_SPECTRUM_HOLD;
|
|
3199
3376
|
} else {
|
|
3200
3377
|
Napi::TypeError::New(env, "Invalid function type").ThrowAsJavaScriptException();
|
|
3201
3378
|
return env.Null();
|
|
@@ -3244,6 +3421,9 @@ Napi::Value NodeHamLib::GetSupportedFunctions(const Napi::CallbackInfo & info) {
|
|
|
3244
3421
|
if (functions & SHIM_RIG_FUNC_SCOPE) funcArray[index++] = Napi::String::New(env, "SCOPE");
|
|
3245
3422
|
if (functions & SHIM_RIG_FUNC_RESUME) funcArray[index++] = Napi::String::New(env, "RESUME");
|
|
3246
3423
|
if (functions & SHIM_RIG_FUNC_TBURST) funcArray[index++] = Napi::String::New(env, "TBURST");
|
|
3424
|
+
if (functions & SHIM_RIG_FUNC_TRANSCEIVE) funcArray[index++] = Napi::String::New(env, "TRANSCEIVE");
|
|
3425
|
+
if (functions & SHIM_RIG_FUNC_SPECTRUM) funcArray[index++] = Napi::String::New(env, "SPECTRUM");
|
|
3426
|
+
if (functions & SHIM_RIG_FUNC_SPECTRUM_HOLD) funcArray[index++] = Napi::String::New(env, "SPECTRUM_HOLD");
|
|
3247
3427
|
|
|
3248
3428
|
return funcArray;
|
|
3249
3429
|
}
|
|
@@ -3730,9 +3910,12 @@ Napi::Function NodeHamLib::GetClass(Napi::Env env) {
|
|
|
3730
3910
|
// VFO Info (Hamlib >= 4.7.0)
|
|
3731
3911
|
NodeHamLib::InstanceMethod("getVfoInfo", & NodeHamLib::GetVfoInfo),
|
|
3732
3912
|
|
|
3733
|
-
// Rig Info /
|
|
3913
|
+
// Rig Info / Spectrum / Conf (async)
|
|
3734
3914
|
NodeHamLib::InstanceMethod("getInfo", & NodeHamLib::GetInfo),
|
|
3735
3915
|
NodeHamLib::InstanceMethod("sendRaw", & NodeHamLib::SendRaw),
|
|
3916
|
+
NodeHamLib::InstanceMethod("getSpectrumCapabilities", & NodeHamLib::GetSpectrumCapabilities),
|
|
3917
|
+
NodeHamLib::InstanceMethod("startSpectrumStream", & NodeHamLib::StartSpectrumStream),
|
|
3918
|
+
NodeHamLib::InstanceMethod("stopSpectrumStream", & NodeHamLib::StopSpectrumStream),
|
|
3736
3919
|
NodeHamLib::InstanceMethod("setConf", & NodeHamLib::SetConf),
|
|
3737
3920
|
NodeHamLib::InstanceMethod("getConf", & NodeHamLib::GetConf),
|
|
3738
3921
|
|
|
@@ -5809,6 +5992,104 @@ Napi::Value NodeHamLib::SendRaw(const Napi::CallbackInfo& info) {
|
|
|
5809
5992
|
return asyncWorker->GetPromise();
|
|
5810
5993
|
}
|
|
5811
5994
|
|
|
5995
|
+
Napi::Value NodeHamLib::GetSpectrumCapabilities(const Napi::CallbackInfo& info) {
|
|
5996
|
+
Napi::Env env = info.Env();
|
|
5997
|
+
Napi::Object result = Napi::Object::New(env);
|
|
5998
|
+
|
|
5999
|
+
result.Set("asyncDataSupported", Napi::Boolean::New(env, shim_rig_is_async_data_supported(my_rig) != 0));
|
|
6000
|
+
|
|
6001
|
+
Napi::Array scopes = Napi::Array::New(env);
|
|
6002
|
+
int scopeCount = shim_rig_get_caps_spectrum_scope_count(my_rig);
|
|
6003
|
+
for (int i = 0; i < scopeCount; ++i) {
|
|
6004
|
+
shim_spectrum_scope_t scope{};
|
|
6005
|
+
if (shim_rig_get_caps_spectrum_scope(my_rig, i, &scope) != SHIM_RIG_OK) {
|
|
6006
|
+
continue;
|
|
6007
|
+
}
|
|
6008
|
+
Napi::Object scopeObject = Napi::Object::New(env);
|
|
6009
|
+
scopeObject.Set("id", Napi::Number::New(env, scope.id));
|
|
6010
|
+
scopeObject.Set("name", Napi::String::New(env, scope.name));
|
|
6011
|
+
scopes.Set(i, scopeObject);
|
|
6012
|
+
}
|
|
6013
|
+
result.Set("scopes", scopes);
|
|
6014
|
+
|
|
6015
|
+
Napi::Array modes = Napi::Array::New(env);
|
|
6016
|
+
int modeCount = shim_rig_get_caps_spectrum_mode_count(my_rig);
|
|
6017
|
+
for (int i = 0; i < modeCount; ++i) {
|
|
6018
|
+
int modeId = 0;
|
|
6019
|
+
if (shim_rig_get_caps_spectrum_mode(my_rig, i, &modeId) != SHIM_RIG_OK) {
|
|
6020
|
+
continue;
|
|
6021
|
+
}
|
|
6022
|
+
Napi::Object modeObject = Napi::Object::New(env);
|
|
6023
|
+
modeObject.Set("id", Napi::Number::New(env, modeId));
|
|
6024
|
+
modeObject.Set("name", Napi::String::New(env, shim_rig_str_spectrum_mode(modeId)));
|
|
6025
|
+
modes.Set(i, modeObject);
|
|
6026
|
+
}
|
|
6027
|
+
result.Set("modes", modes);
|
|
6028
|
+
|
|
6029
|
+
Napi::Array spans = Napi::Array::New(env);
|
|
6030
|
+
int spanCount = shim_rig_get_caps_spectrum_span_count(my_rig);
|
|
6031
|
+
for (int i = 0; i < spanCount; ++i) {
|
|
6032
|
+
double spanHz = 0;
|
|
6033
|
+
if (shim_rig_get_caps_spectrum_span(my_rig, i, &spanHz) != SHIM_RIG_OK) {
|
|
6034
|
+
continue;
|
|
6035
|
+
}
|
|
6036
|
+
spans.Set(i, Napi::Number::New(env, spanHz));
|
|
6037
|
+
}
|
|
6038
|
+
result.Set("spans", spans);
|
|
6039
|
+
|
|
6040
|
+
Napi::Array avgModes = Napi::Array::New(env);
|
|
6041
|
+
int avgModeCount = shim_rig_get_caps_spectrum_avg_mode_count(my_rig);
|
|
6042
|
+
for (int i = 0; i < avgModeCount; ++i) {
|
|
6043
|
+
shim_spectrum_avg_mode_t avgMode{};
|
|
6044
|
+
if (shim_rig_get_caps_spectrum_avg_mode(my_rig, i, &avgMode) != SHIM_RIG_OK) {
|
|
6045
|
+
continue;
|
|
6046
|
+
}
|
|
6047
|
+
Napi::Object avgModeObject = Napi::Object::New(env);
|
|
6048
|
+
avgModeObject.Set("id", Napi::Number::New(env, avgMode.id));
|
|
6049
|
+
avgModeObject.Set("name", Napi::String::New(env, avgMode.name));
|
|
6050
|
+
avgModes.Set(i, avgModeObject);
|
|
6051
|
+
}
|
|
6052
|
+
result.Set("avgModes", avgModes);
|
|
6053
|
+
|
|
6054
|
+
return result;
|
|
6055
|
+
}
|
|
6056
|
+
|
|
6057
|
+
Napi::Value NodeHamLib::StartSpectrumStream(const Napi::CallbackInfo& info) {
|
|
6058
|
+
Napi::Env env = info.Env();
|
|
6059
|
+
if (!rig_is_open) {
|
|
6060
|
+
Napi::TypeError::New(env, "Rig is not open!").ThrowAsJavaScriptException();
|
|
6061
|
+
return env.Null();
|
|
6062
|
+
}
|
|
6063
|
+
if (info.Length() < 1 || !info[0].IsFunction()) {
|
|
6064
|
+
Napi::TypeError::New(env, "Expected (callback: Function)").ThrowAsJavaScriptException();
|
|
6065
|
+
return env.Null();
|
|
6066
|
+
}
|
|
6067
|
+
|
|
6068
|
+
std::lock_guard<std::mutex> lock(spectrum_mutex_);
|
|
6069
|
+
if (spectrum_stream_running_) {
|
|
6070
|
+
Napi::Error::New(env, "Spectrum stream is already running").ThrowAsJavaScriptException();
|
|
6071
|
+
return env.Null();
|
|
6072
|
+
}
|
|
6073
|
+
|
|
6074
|
+
Napi::Function callback = info[0].As<Napi::Function>();
|
|
6075
|
+
spectrum_tsfn_ = Napi::ThreadSafeFunction::New(env, callback, "HamLibSpectrumStream", 0, 1);
|
|
6076
|
+
int ret = shim_rig_set_spectrum_callback(my_rig, &NodeHamLib::spectrum_line_cb, this);
|
|
6077
|
+
if (ret != SHIM_RIG_OK) {
|
|
6078
|
+
spectrum_tsfn_.Release();
|
|
6079
|
+
spectrum_tsfn_ = Napi::ThreadSafeFunction();
|
|
6080
|
+
Napi::Error::New(env, shim_rigerror(ret)).ThrowAsJavaScriptException();
|
|
6081
|
+
return env.Null();
|
|
6082
|
+
}
|
|
6083
|
+
spectrum_stream_running_ = true;
|
|
6084
|
+
return Napi::Boolean::New(env, true);
|
|
6085
|
+
}
|
|
6086
|
+
|
|
6087
|
+
Napi::Value NodeHamLib::StopSpectrumStream(const Napi::CallbackInfo& info) {
|
|
6088
|
+
Napi::Env env = info.Env();
|
|
6089
|
+
StopSpectrumStreamInternal();
|
|
6090
|
+
return Napi::Boolean::New(env, true);
|
|
6091
|
+
}
|
|
6092
|
+
|
|
5812
6093
|
// ===== SetConf (async) =====
|
|
5813
6094
|
|
|
5814
6095
|
class SetConfAsyncWorker : public HamLibAsyncWorker {
|
package/src/hamlib.h
CHANGED
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
#include "shim/hamlib_shim.h"
|
|
5
5
|
#include <memory>
|
|
6
6
|
#include <string>
|
|
7
|
+
#include <atomic>
|
|
8
|
+
#include <mutex>
|
|
9
|
+
#include <vector>
|
|
10
|
+
#include <cstdint>
|
|
7
11
|
|
|
8
12
|
// Forward declaration
|
|
9
13
|
class NodeHamLib;
|
|
@@ -173,6 +177,9 @@ class NodeHamLib : public Napi::ObjectWrap<NodeHamLib> {
|
|
|
173
177
|
// Rig Info / Raw / Conf (async)
|
|
174
178
|
Napi::Value GetInfo(const Napi::CallbackInfo&);
|
|
175
179
|
Napi::Value SendRaw(const Napi::CallbackInfo&);
|
|
180
|
+
Napi::Value GetSpectrumCapabilities(const Napi::CallbackInfo&);
|
|
181
|
+
Napi::Value StartSpectrumStream(const Napi::CallbackInfo&);
|
|
182
|
+
Napi::Value StopSpectrumStream(const Napi::CallbackInfo&);
|
|
176
183
|
Napi::Value SetConf(const Napi::CallbackInfo&);
|
|
177
184
|
Napi::Value GetConf(const Napi::CallbackInfo&);
|
|
178
185
|
|
|
@@ -217,6 +224,7 @@ class NodeHamLib : public Napi::ObjectWrap<NodeHamLib> {
|
|
|
217
224
|
|
|
218
225
|
// Frequency change callback (uses basic C types via shim)
|
|
219
226
|
static int freq_change_cb(void* handle, int vfo, double freq, void* arg);
|
|
227
|
+
static int spectrum_line_cb(void* handle, const shim_spectrum_line_t* line, void* arg);
|
|
220
228
|
|
|
221
229
|
public:
|
|
222
230
|
hamlib_shim_handle_t my_rig; // Opaque handle instead of RIG*
|
|
@@ -234,4 +242,10 @@ class NodeHamLib : public Napi::ObjectWrap<NodeHamLib> {
|
|
|
234
242
|
|
|
235
243
|
// Static callback helper for shim_rig_list_foreach
|
|
236
244
|
static int rig_list_callback(const shim_rig_info_t* info, void* data);
|
|
245
|
+
|
|
246
|
+
void EmitSpectrumLine(const shim_spectrum_line_t& line);
|
|
247
|
+
void StopSpectrumStreamInternal();
|
|
248
|
+
std::atomic<bool> spectrum_stream_running_{false};
|
|
249
|
+
Napi::ThreadSafeFunction spectrum_tsfn_;
|
|
250
|
+
std::mutex spectrum_mutex_;
|
|
237
251
|
};
|
package/src/shim/hamlib_shim.c
CHANGED
|
@@ -333,14 +333,20 @@ SHIM_API int shim_rig_get_strength(hamlib_shim_handle_t h, int vfo, int* strengt
|
|
|
333
333
|
|
|
334
334
|
/* ===== Level control ===== */
|
|
335
335
|
|
|
336
|
+
static void shim_ensure_targetable_level(hamlib_shim_handle_t h);
|
|
337
|
+
|
|
336
338
|
SHIM_API int shim_rig_set_level_f(hamlib_shim_handle_t h, int vfo, uint64_t level, float value) {
|
|
339
|
+
shim_ensure_targetable_level(h);
|
|
337
340
|
value_t val;
|
|
341
|
+
memset(&val, 0, sizeof(val));
|
|
338
342
|
val.f = value;
|
|
339
343
|
return rig_set_level((RIG*)h, (vfo_t)vfo, (setting_t)level, val);
|
|
340
344
|
}
|
|
341
345
|
|
|
342
346
|
SHIM_API int shim_rig_set_level_i(hamlib_shim_handle_t h, int vfo, uint64_t level, int value) {
|
|
347
|
+
shim_ensure_targetable_level(h);
|
|
343
348
|
value_t val;
|
|
349
|
+
memset(&val, 0, sizeof(val));
|
|
344
350
|
val.i = value;
|
|
345
351
|
return rig_set_level((RIG*)h, (vfo_t)vfo, (setting_t)level, val);
|
|
346
352
|
}
|
|
@@ -383,6 +389,10 @@ SHIM_API int shim_rig_get_level_i(hamlib_shim_handle_t h, int vfo, uint64_t leve
|
|
|
383
389
|
return ret;
|
|
384
390
|
}
|
|
385
391
|
|
|
392
|
+
SHIM_API int shim_rig_level_is_float(uint64_t level) {
|
|
393
|
+
return RIG_LEVEL_IS_FLOAT((setting_t)level) ? 1 : 0;
|
|
394
|
+
}
|
|
395
|
+
|
|
386
396
|
/*
|
|
387
397
|
* Auto-detect int/float level type using RIG_LEVEL_IS_FLOAT macro.
|
|
388
398
|
* Returns the value as double regardless of the underlying type.
|
|
@@ -837,9 +847,15 @@ struct shim_ptt_cb_adapter {
|
|
|
837
847
|
void* user_arg;
|
|
838
848
|
};
|
|
839
849
|
|
|
850
|
+
struct shim_spectrum_cb_adapter {
|
|
851
|
+
shim_spectrum_cb_t user_cb;
|
|
852
|
+
void* user_arg;
|
|
853
|
+
};
|
|
854
|
+
|
|
840
855
|
/* We store adapters statically (one per rig handle - simplified) */
|
|
841
856
|
static struct shim_freq_cb_adapter freq_cb_adapter = {NULL, NULL};
|
|
842
857
|
static struct shim_ptt_cb_adapter ptt_cb_adapter = {NULL, NULL};
|
|
858
|
+
static struct shim_spectrum_cb_adapter spectrum_cb_adapter = {NULL, NULL};
|
|
843
859
|
|
|
844
860
|
static int shim_freq_cb_thunk(RIG *rig, vfo_t vfo, freq_t freq, rig_ptr_t arg) {
|
|
845
861
|
struct shim_freq_cb_adapter *adapter = (struct shim_freq_cb_adapter*)arg;
|
|
@@ -857,6 +873,33 @@ static int shim_ptt_cb_thunk(RIG *rig, vfo_t vfo, ptt_t ptt, rig_ptr_t arg) {
|
|
|
857
873
|
return 0;
|
|
858
874
|
}
|
|
859
875
|
|
|
876
|
+
static int shim_spectrum_cb_thunk(RIG *rig, struct rig_spectrum_line *line, rig_ptr_t arg) {
|
|
877
|
+
struct shim_spectrum_cb_adapter *adapter = (struct shim_spectrum_cb_adapter*)arg;
|
|
878
|
+
shim_spectrum_line_t safe_line;
|
|
879
|
+
|
|
880
|
+
if (!adapter || !adapter->user_cb || !line) {
|
|
881
|
+
return 0;
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
memset(&safe_line, 0, sizeof(safe_line));
|
|
885
|
+
safe_line.id = line->id;
|
|
886
|
+
safe_line.data_level_min = line->data_level_min;
|
|
887
|
+
safe_line.data_level_max = line->data_level_max;
|
|
888
|
+
safe_line.signal_strength_min = line->signal_strength_min;
|
|
889
|
+
safe_line.signal_strength_max = line->signal_strength_max;
|
|
890
|
+
safe_line.spectrum_mode = (int)line->spectrum_mode;
|
|
891
|
+
safe_line.center_freq = (double)line->center_freq;
|
|
892
|
+
safe_line.span_freq = (double)line->span_freq;
|
|
893
|
+
safe_line.low_edge_freq = (double)line->low_edge_freq;
|
|
894
|
+
safe_line.high_edge_freq = (double)line->high_edge_freq;
|
|
895
|
+
safe_line.data_length = (int)((line->spectrum_data_length > sizeof(safe_line.data)) ? sizeof(safe_line.data) : line->spectrum_data_length);
|
|
896
|
+
if (safe_line.data_length > 0 && line->spectrum_data) {
|
|
897
|
+
memcpy(safe_line.data, line->spectrum_data, (size_t)safe_line.data_length);
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
return adapter->user_cb((void*)rig, &safe_line, adapter->user_arg);
|
|
901
|
+
}
|
|
902
|
+
|
|
860
903
|
SHIM_API int shim_rig_set_freq_callback(hamlib_shim_handle_t h, shim_freq_cb_t cb, void* arg) {
|
|
861
904
|
freq_cb_adapter.user_cb = cb;
|
|
862
905
|
freq_cb_adapter.user_arg = arg;
|
|
@@ -869,6 +912,12 @@ SHIM_API int shim_rig_set_ptt_callback(hamlib_shim_handle_t h, shim_ptt_cb_t cb,
|
|
|
869
912
|
return rig_set_ptt_callback((RIG*)h, shim_ptt_cb_thunk, &ptt_cb_adapter);
|
|
870
913
|
}
|
|
871
914
|
|
|
915
|
+
SHIM_API int shim_rig_set_spectrum_callback(hamlib_shim_handle_t h, shim_spectrum_cb_t cb, void* arg) {
|
|
916
|
+
spectrum_cb_adapter.user_cb = cb;
|
|
917
|
+
spectrum_cb_adapter.user_arg = arg;
|
|
918
|
+
return rig_set_spectrum_callback((RIG*)h, cb ? shim_spectrum_cb_thunk : NULL, cb ? &spectrum_cb_adapter : NULL);
|
|
919
|
+
}
|
|
920
|
+
|
|
872
921
|
/* rig_set_trn: deprecated in Hamlib 4.7.0, may be removed in future versions. */
|
|
873
922
|
#ifdef __GNUC__
|
|
874
923
|
#pragma GCC diagnostic push
|
|
@@ -908,6 +957,92 @@ SHIM_API uint64_t shim_rig_get_caps_has_set_func(hamlib_shim_handle_t h) {
|
|
|
908
957
|
return (uint64_t)(rig->caps->has_set_func);
|
|
909
958
|
}
|
|
910
959
|
|
|
960
|
+
SHIM_API int shim_rig_is_async_data_supported(hamlib_shim_handle_t h) {
|
|
961
|
+
RIG* rig = (RIG*)h;
|
|
962
|
+
if (!rig || !rig->caps) return 0;
|
|
963
|
+
return rig->caps->async_data_supported ? 1 : 0;
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
SHIM_API int shim_rig_get_caps_spectrum_scope_count(hamlib_shim_handle_t h) {
|
|
967
|
+
int count = 0;
|
|
968
|
+
RIG* rig = (RIG*)h;
|
|
969
|
+
if (!rig || !rig->caps) return 0;
|
|
970
|
+
while (count < HAMLIB_MAX_SPECTRUM_SCOPES && rig->caps->spectrum_scopes[count].name) {
|
|
971
|
+
count++;
|
|
972
|
+
}
|
|
973
|
+
return count;
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
SHIM_API int shim_rig_get_caps_spectrum_scope(hamlib_shim_handle_t h, int index, shim_spectrum_scope_t* out) {
|
|
977
|
+
RIG* rig = (RIG*)h;
|
|
978
|
+
if (!rig || !rig->caps || !out || index < 0 || index >= HAMLIB_MAX_SPECTRUM_SCOPES) return -RIG_EINVAL;
|
|
979
|
+
if (!rig->caps->spectrum_scopes[index].name) return -RIG_ENAVAIL;
|
|
980
|
+
memset(out, 0, sizeof(*out));
|
|
981
|
+
out->id = rig->caps->spectrum_scopes[index].id;
|
|
982
|
+
strncpy(out->name, rig->caps->spectrum_scopes[index].name, sizeof(out->name) - 1);
|
|
983
|
+
return RIG_OK;
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
SHIM_API int shim_rig_get_caps_spectrum_mode_count(hamlib_shim_handle_t h) {
|
|
987
|
+
int count = 0;
|
|
988
|
+
RIG* rig = (RIG*)h;
|
|
989
|
+
if (!rig || !rig->caps) return 0;
|
|
990
|
+
while (count < HAMLIB_MAX_SPECTRUM_MODES && rig->caps->spectrum_modes[count] != RIG_SPECTRUM_MODE_NONE) {
|
|
991
|
+
count++;
|
|
992
|
+
}
|
|
993
|
+
return count;
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
SHIM_API int shim_rig_get_caps_spectrum_mode(hamlib_shim_handle_t h, int index, int* out) {
|
|
997
|
+
RIG* rig = (RIG*)h;
|
|
998
|
+
if (!rig || !rig->caps || !out || index < 0 || index >= HAMLIB_MAX_SPECTRUM_MODES) return -RIG_EINVAL;
|
|
999
|
+
if (rig->caps->spectrum_modes[index] == RIG_SPECTRUM_MODE_NONE) return -RIG_ENAVAIL;
|
|
1000
|
+
*out = (int)rig->caps->spectrum_modes[index];
|
|
1001
|
+
return RIG_OK;
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
SHIM_API int shim_rig_get_caps_spectrum_span_count(hamlib_shim_handle_t h) {
|
|
1005
|
+
int count = 0;
|
|
1006
|
+
RIG* rig = (RIG*)h;
|
|
1007
|
+
if (!rig || !rig->caps) return 0;
|
|
1008
|
+
while (count < HAMLIB_MAX_SPECTRUM_SPANS && rig->caps->spectrum_spans[count] != 0) {
|
|
1009
|
+
count++;
|
|
1010
|
+
}
|
|
1011
|
+
return count;
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
SHIM_API int shim_rig_get_caps_spectrum_span(hamlib_shim_handle_t h, int index, double* out) {
|
|
1015
|
+
RIG* rig = (RIG*)h;
|
|
1016
|
+
if (!rig || !rig->caps || !out || index < 0 || index >= HAMLIB_MAX_SPECTRUM_SPANS) return -RIG_EINVAL;
|
|
1017
|
+
if (rig->caps->spectrum_spans[index] == 0) return -RIG_ENAVAIL;
|
|
1018
|
+
*out = (double)rig->caps->spectrum_spans[index];
|
|
1019
|
+
return RIG_OK;
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
SHIM_API int shim_rig_get_caps_spectrum_avg_mode_count(hamlib_shim_handle_t h) {
|
|
1023
|
+
int count = 0;
|
|
1024
|
+
RIG* rig = (RIG*)h;
|
|
1025
|
+
if (!rig || !rig->caps) return 0;
|
|
1026
|
+
while (count < HAMLIB_MAX_SPECTRUM_AVG_MODES && rig->caps->spectrum_avg_modes[count].name) {
|
|
1027
|
+
count++;
|
|
1028
|
+
}
|
|
1029
|
+
return count;
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
SHIM_API int shim_rig_get_caps_spectrum_avg_mode(hamlib_shim_handle_t h, int index, shim_spectrum_avg_mode_t* out) {
|
|
1033
|
+
RIG* rig = (RIG*)h;
|
|
1034
|
+
if (!rig || !rig->caps || !out || index < 0 || index >= HAMLIB_MAX_SPECTRUM_AVG_MODES) return -RIG_EINVAL;
|
|
1035
|
+
if (!rig->caps->spectrum_avg_modes[index].name) return -RIG_ENAVAIL;
|
|
1036
|
+
memset(out, 0, sizeof(*out));
|
|
1037
|
+
out->id = rig->caps->spectrum_avg_modes[index].id;
|
|
1038
|
+
strncpy(out->name, rig->caps->spectrum_avg_modes[index].name, sizeof(out->name) - 1);
|
|
1039
|
+
return RIG_OK;
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
SHIM_API const char* shim_rig_str_spectrum_mode(int mode) {
|
|
1043
|
+
return rig_strspectrummode((enum rig_spectrum_mode_e)mode);
|
|
1044
|
+
}
|
|
1045
|
+
|
|
911
1046
|
SHIM_API int shim_rig_sprintf_mode(uint64_t modes, char* buf, int buflen) {
|
|
912
1047
|
if (!buf || buflen <= 0) return 0;
|
|
913
1048
|
buf[0] = '\0';
|