gnokii: API error? - api

I have issues with the following code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gnokii.h>
#define CONFIG_FILE "config"
struct gn_statemachine *state;
void terminate(void) {
gn_lib_phone_close(state);
gn_lib_phoneprofile_free(&state);
gn_lib_library_free();
}
int main() {
gn_data data;
gn_error error;
gn_sms_folder_list folderlist;
atexit(terminate);
if((error = gn_lib_phoneprofile_load(CONFIG_FILE,&state))
!= GN_ERR_NONE)
{
fprintf(stderr,"%s\n",gn_error_print(error));
exit(1);
}
memset(&folderlist,0,sizeof(gn_sms_folder_list));
gn_data_clear(&data);
data.sms_folder_list = &folderlist;
error = gn_sm_functions(GN_OP_GetSMSFolders, &data, state);
printf("ada %d sms dun\n",folderlist.number);
return 0;
}
I'm compiling it with gcc -o main main.c -lgnokii, but when it's executed it generates errors when looking for config file:
# ./gnokiitest
No phone_config section in the config file.
Either global or given phone section cannot be found.
Segmentation fault
because I included the config file within one folder of main output:
$ cat config
[global]
connection = bluetooth
port = 24:22:AB:AB:C1:F8
model = AT
rfcomm_channel = 2
Whats wrong then?

For starters, the following will cause issues:
if((error = gn_lib_phoneprofile_load(CONFIG_FILE,&state))
state variable is not initialized here. That will cause random pointer being passed and most likely segfault.
Next, the first argument to gn_lib_phoneprofile_load() is not the config file name, but the phone section in the config where the connection details are provided. Given that you pass config as this parameter you'd need:
[phone_config]
connection = bluetooth
port = 24:22:AB:AB:C1:F8
model = AT
rfcomm_channel = 2
but placed in the standard gnokii config file location. To use different location use:
gn_lib_phoneprofile_load_from_file(CONFIG_FILE, NULL, &state);
Second argument is the phone section name. If NULL, then [global] would be used.
Additionally gn_lib_phoneprofile_load() just reads the config file. You need to run gn_lib_phone_open() to initialize the connection.
Finally, there is similar code already written, no need to reinvent the wheel: http://git.savannah.gnu.org/cgit/gnokii/gnokii-extras.git/tree/snippets/sms/sms_status.c

Related

JNI header missing in Objective-C

I have a file.c in my project which has #include <jni.h> header file. What is the process to include this header file in project or macOS?
Let's say you have following code
#include "jni.h"
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
#autoreleasepool {
JNIEnv *env;
JavaVM *jvm;
JavaVMInitArgs vm_args;
JavaVMOption options[3];
options[0].optionString = "-Djava.class.path=_HERE_GOES_LOCATION_OF_JNICOOKBOK_/jnicookbook/recipeNo051/target";
vm_args.options = options;
vm_args.ignoreUnrecognized = 0;
vm_args.version = JNI_VERSION_1_8;
vm_args.nOptions = 1;
int status = JNI_CreateJavaVM (&jvm, (void **) &env, &vm_args);
if (status < 0 || !env) {
printf ("Error - JVM creation failed\n");
return 1;
}
jclass cls_Main = (*env)->FindClass (env, "recipeNo051/Main");
jmethodID method_displayMessage = (*env)->GetStaticMethodID (env, cls_Main, "displayMessage", "()V");
(*env)->CallStaticVoidMethod(env, cls_Main, method_displayMessage);
(*jvm)->DestroyJavaVM( jvm );
}
return 0;
}
in order to run it you will need
location of libjvm.dylib
location of headers
location of compiled Java classes that are called from main.m
Let's start with libs and headers. You have to make sure that following paths are searched for includes (note that I am using jdk-11.0.4):
/Library/Java/JavaVirtualMachines/jdk-11.0.4.jdk/Contents/Home/include
/Library/Java/JavaVirtualMachines/jdk-11.0.4.jdk/Contents/Home/include/darwin/
You have to make sure that following path is added to Library Search Path and to Runpath Search Paths
/Library/Java/JavaVirtualMachines/jdk-11.0.4.jdk/Contents/Home/lib/server
You should have settings like that:
Make sure you are linking your code with libjvm.dylib. Add it inside Build Phases
where you can specify it's location by choosing Add Other...
Run your code, but! Make sure to ignore SIGSEGV before calling method JNI_CreateJavaVM. You can ignore it inside lldb console
(lldb) process handle --pass true --stop false SIGSEGV
After you continue, you can see your JVM instance calling classes from the recipeNo051.
Source code of class: recipeNo051/Main can be found here: https://github.com/mkowsiak/jnicookbook/tree/master/recipes/recipeNo051
Update
step by step instructions: http://www.owsiak.org/running-jni-based-code-inside-xcode/
video tutorial: https://youtu.be/WEA-3uI7Y18

./speaks: error while loading shared libraries: libespeak-ng.so.1: cannot open shared object file: No such file or directory

I have downloaded the last version of espeak-ng from github, and did ./autogen.sh ./configure make make install.
so I wrote a test program as you can see below:
#include <string.h>
#include <vector>
#include </usr/local/include/espeak-ng/speak_lib.h>
int samplerate; // determined by espeak, will be in Hertz (Hz)
const int buflength = 200; // passed to espeak, in milliseconds (ms)
std::vector<short> sounddata;
int SynthCallback(short *wav, int numsamples, espeak_EVENT *events) {
if (wav == NULL)
return 1; // NULL means done.
/* process your samples here, let's just gather them */
sounddata.insert(sounddata.end(), wav, wav + numsamples);
return 0; // 0 continues synthesis, 1 aborts
}
int main(int argc, char* argv[] ) {
char text[] = {"my name is espeak"};
samplerate = espeak_Initialize(AUDIO_OUTPUT_RETRIEVAL, buflength, NULL, 0);
espeak_SetSynthCallback(&SynthCallback);
espeak_SetVoiceByName("en");
unsigned int flags=espeakCHARS_AUTO | espeakENDPAUSE;
size_t size = strlen(text);
espeak_Synth(text, size + 1, 0, POS_CHARACTER, 0, flags, NULL, NULL);
espeak_Synchronize();
/* in theory sounddata holds your samples now... */
return 0;
}
And compiled it by this command without any errors:
g++ -W -o speaks espeak.cpp -lespeak-ng
But when I try to run the executable by ./speaks , I get this error message:
./speaks: error while loading shared libraries: libespeak-ng.so.1: cannot open shared object file: No such file or directory
What's the problem?
I know libespeak-ng.so.1 is here: /usr/local/lib/libespeak-ng.so.1
I solved the problem by adding these two lines to my `/etc/environment' file:
LD_LIBRARY_PATH=/usr/local/lib
PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
On Ubuntu 18.04 this is caused by setting the wrong path for the library.
You can fix it by:
sudo ln -s /usr/local/lib/libespeak-ng.so.1 /usr/lib/libespeak-ng.so.1

API for handling wait queues are not working

I have to make tasks as processes in Linux but I don't want the process to execute until all the processes are created. So I thought of moving the processes to wait queue soon after creation and wait until all processes are created.
#include <unistd.h> /* Symbolic Constants */
#include <sys/types.h> /* Primitive System Data Types */
#include <errno.h> /* Errors */
#include <stdio.h> /* Input/Output */
#include <stdlib.h> /* General Utilities */
#include <pthread.h> /* POSIX Threads */
#include <string.h> /* String handling */
#include <sched.h>
#include <linux/kernel.h>
#include <time.h>
#include <sys/resource.h>
#include <stddef.h>
#include <linux/sched.h>
#include <linux/wait.h> /* for wait_event_interruptible() & wake_up_interruptible() */
int done = 0;
static DECLARE_WAIT_QUEUE_HEAD(queue);
int main()
{
int pid1, pid2;
if ((pid1 = fork()) < 0) //create a child process
exit(1);
if ((pid2 = fork()) < 0) //create a child process
exit(1);
if (pid1 == 0) //child process
{
wait_event_interruptible(queue, done == 2);
printf("child 1\n");
}
else //parent process
{
done = done+1;
wake_up_interruptible(&queue);
}
if (pid2 == 0) //child process
{
wait_event_interruptible(queue, done == 2);
printf("child 2\n");
}
else //parent process
{
done = done+1;
wake_up_interruptible(&queue);
}
return 0;
}
But when I tried this sample code it shows these errors.
$ gcc -Wall try.c
try.c:18:8: warning: type defaults to ‘int’ in declaration of ‘DECLARE_WAIT_QUEUE_HEAD’ [-Wimplicit-int]
try.c:18:1: warning: parameter names (without types) in function declaration [enabled by default]
try.c: In function ‘main’:
try.c:33:6: warning: implicit declaration of function ‘wait_event_interruptible’ [-Wimplicit-function-declaration]
try.c:33:31: error: ‘queue’ undeclared (first use in this function)
try.c:33:31: note: each undeclared identifier is reported only once for each function it appears in
try.c:39:2: warning: implicit declaration of function ‘wake_up_interruptible’ [-Wimplicit-function-declaration]
try.c: At top level:
try.c:18:8: warning: ‘DECLARE_WAIT_QUEUE_HEAD’ declared ‘static’ but never defined [-Wunused-function]
When I checked $ man wait_event_interruptible, it says "No manual entry for wait_event_interruptible". So the API is missing in the library. How can I add it to the library? Thanks in advance.
wait_event_interruptible(), wake_up_interruptible() are some of the Kernel's API to create and use wait queues. You cannot use those from the user-land!
If I understand your purpose correctly, what you need to do is to create N processes barrier. If you know the number of the processes (N), you can easily use semaphores: initialize the semaphore with zero, all processes call down() and the last process calls up() N times. You can also use message queues.
You can also use the Linux API for barriers: pthread_barrier_wait and pthread_barrier_init, but I have not used this before.

How do I open and read a file in C?

I'm starting a new program and one of the first steps is to read a file that was written in a previous program. The program fails to run between the fseek() line and the fread() line, I get the following error:
debug assertion failed
expression:(stream!=NULL)
My code is the following:
#include <stdio.h>
#include <string.h>
int main (void)
{
int m = 0;
char stream[20];
FILE *fp;
/* opens a file which had data written into it in a previous program */
fp = fopen("codetree.bin", "r");
/* makes sure the file pointer is set at the beginning of the file */
fseek(fp, 0, SEEK_SET);
m = sizeof(stream);
fread(&stream, m, 1, fp);
/* ... */
}
If I add the following lines to check whether fopen was successful or not:
if (fp == NULL) {
printf("fopen() error...%s\n", strerror(errno));
}
I get the following error:
no such file or directory exists
What am I overlooking or missing in my code?

GNU Radio File Format for the recorded samples

Do you know the format in which GNU Radio ( File Sink in GNU Radio Companion) stores the samples in the Binary File?
I need to read these samples in Matlab, but the problem is the file is too big to be read in Matlab.
I am writing the program in C++ to read this binary file.
The file sink is just a dump of the data stream. If the data stream content was simple bytes then the content of the file is straightforward. If the data stream contained complex numbers then the file will contain a list of complex numbers where each complex number is given by two floats and each float by (usually) 4 bytes.
See the files gnuradio/gnuradio-core/src/lib/io/gr_file_sink.cc and gr_file_source.cc for the implementations of the gnuradio file reading and writing blocks.
You could also use python and gnuradio to convert the files into some other format.
from gnuradio import gr
# Assuming the data stream was complex numbers.
src = gr.file_source(gr.sizeof_gr_complex, "the_file_name")
snk = gr.vector_sink_c()
tb = gr.top_block()
tb.connect(src, snk)
tb.run()
# The complex numbers are then accessible as a python list.
data = snk.data()
Ben's answer still stands – but it's from a time long past (the module organization points at GNU Radio 3.6, I think). Organizationally, things are different now; data-wise, the File Sink remained the same.
GNU Radio now has relatively much block documentation in their wiki. In particular, the File Sink documentation page has a section on Handling File Sink data; not to overquote that:
// This is C++17
#include <algorithm>
#include <cmath>
#include <complex>
#include <cstddef>
#include <filesystem>
#include <fstream>
#include <string_view>
#include <vector>
#include <fmt/format.h>
#include <fmt/ranges.h>
using sample_t = std::complex<float>;
using power_t = float;
constexpr std::size_t read_block_size = 1 << 16;
int main(int argc, char *argv[]) {
// expect exactly one argument, a file name
if (argc != 2) {
fmt::print(stderr, "Usage: {} FILE_NAME", argv[0]);
return -1;
}
// just for convenience; we could as well just use `argv[1]` throughout the
// code
std::string_view filename(argv[1]);
// check whether file exists
if (!std::filesystem::exists(filename.data())) {
fmt::print(stderr, "file '{:s}' not found\n", filename);
return -2;
}
// calculate how many samples to read
auto file_size = std::filesystem::file_size(std::filesystem::path(filename));
auto samples_to_read = file_size / sizeof(sample_t);
// construct and reserve container for resulting powers
std::vector<power_t> powers;
powers.reserve(samples_to_read);
std::ifstream input_file(filename.data(), std::ios_base::binary);
if (!input_file) {
fmt::print(stderr, "error opening '{:s}'\n", filename);
return -3;
}
// construct and reserve container for read samples
// if read_block_size == 0, then read the whole file at once
std::vector<sample_t> samples;
if (read_block_size)
samples.resize(read_block_size);
else
samples.resize(samples_to_read);
fmt::print(stderr, "Reading {:d} samples…\n", samples_to_read);
while (samples_to_read) {
auto read_now = std::min(samples_to_read, samples.size());
input_file.read(reinterpret_cast<char *>(samples.data()),
read_now * sizeof(sample_t));
for (size_t idx = 0; idx < read_now; ++idx) {
auto magnitude = std::abs(samples[idx]);
powers.push_back(magnitude * magnitude);
}
samples_to_read -= read_now;
}
// we're not actually doing anything with the data. Let's print it!
fmt::print("Power\n{}\n", fmt::join(powers, "\n"));
}