this is my main.c
static int l_psd_stop_f(void)
{
int res;
int fd_psd_socket;
if(pthread_mutex_lock(&l_mutex_wrc)) {
LOG_ERR("Can not lock WRC mutex");
return -1;
}
fd_psd_socket = l_s_wrc.fd_psd;
l_s_wrc.fd_psd = -1;
if(pthread_mutex_unlock(&l_mutex_wrc)) {
LOG_ERR("Can not unlock WRC mutex");
return -1;}
res = l_stop_psd_receiver_f(fd_psd_socket);
fd_psd_socket = -1;
if(res < 0) {
LOG_ERR("Can not close PSD socket %d : %s", res, strerror(errno));
return -1;
}
return 0;
}
i want to call and refer to this codes but it bring me error when i click on the button which run on x-code ipad simulator.
this is on ViewController.m
- (IBAction)disconnect:(id)sender {
[self l_psd_stop_f];}
instead of declaring "l_psd_stop_f" in your main.c, put it in your ViewController.m and declare it like this:
- (int) l_psd_stop_f
{
int res;
int fd_psd_socket;
...
...
...
}
And then your "disconnect" action will compile and should work.
By declaring it as "static int l_psd_stop_f(void)" in your main.c, it was a C function that was probably only available to any function calling it from within main.c. But that function wasn't available to your view controller.
So what I'm having you do is change that C function into an Objective-C method, a member of that ViewController class.
Related
I am initializing a loop in libuv, but if I need to return after I initialized the loop but before I have called uv_run, how do I correctly clean up all memory and file descriptors? Here is my example code, loop being uv_loop_t* and server being uv_tcp_t*:
if (uv_loop_init(loop) < 0) {
return -1;
}
if (uv_tcp_init(loop, server) < 0) {
// What code here?
return -1;
}
if (some_other_function() < 0) {
// What code here?
return -1;
}
uv_run(loop, UV_RUN_DEFAULT);
According to this question, I should stop, walk and run the loop, closing all the handles; but that assumes I'm already running the loop, which I'm not. I could just call uv_loop_close(loop), but that doesn't free the handles.
As mentioned in the link, you need to do something like this;
uv_loop_init(&loop);
uv_tcp_init(&loop, &server);
uv_walk(&loop,
[](uv_handle_t* handle, void* arg) {
printf("closing...%p\n", handle);
uv_close(handle, [](uv_handle_t* handle) {
printf("closed...%p\n", handle);
}
);
uv_run(&loop, UV_RUN_ONCE);
},
NULL);
int mqtt_connection()
{
mqtt_broker_handle_t *broker = mqtt_connect(client_name, ip_addr, port);
if(broker == 0) {
printf("Connection failed, Please check the IP and port of broker\n");
return 0;
}
else {
printf("Connection established successfully\n");
}
return 1;
}
int publish_mqtt()
{
char msg[128] = "Test 2";
if(mqtt_publish(broker, topic1, msg, QoS1) == -1)
{
printf("publish failed\n");
}
else {
printf("Sent messages\n");
}
return(0);
}
I am getting error while building using scons as
master.c: In function 'publish_mqtt':
master.c:39:17: error: 'broker' undeclared (first use in this function)
if(mqtt_publish(broker, topic1, msg, QoS1) == -1)
^
master.c:39:17: note: each undeclared identifier is reported only once for each function it appears in
scons: *** [master.o] Error 1
scons: building terminated because of errors.
How to exchange the value of broker between two functions?. Is there any other way to implement this?
How to exchange the value of broker between two functions?. Is there any other way to implement this?.
Change the signatures of both functions.
Change the first function to return broker.
Change the second function to expect broker as an argument.
mqtt_broker_handle_t* mqtt_connection()
{
mqtt_broker_handle_t *broker = mqtt_connect(client_name, ip_addr, port);
if(broker == 0)
{
printf("Connection failed, Please check the IP and port of broker\n");
return NULL;
}
else
{
printf("Connection established successfully\n");
return broker;
}
}
int publish_mqtt(mqtt_broker_handle_t* broker)
{
char msg[128] = "Test 2";
if(mqtt_publish(broker, topic1, msg, QoS1) == -1)
{
printf("publish failed\n");
}
else
{
printf("Sent messages\n");
}
return(0);
}
Change the calling function.
mqtt_broker_handle_t* broker = mqtt_connection();
publish_mqtt(broker);
The problem lies in the fact broker is not available in the publish_mqtt function due to variable scoping.
Ie: Once the end brace of mqtt_connection is hit, broker no longer exists.
int mqtt_connection()
{
mqtt_broker_handle_t *broker = mqtt_connect(client_name, ip_addr, port);
...
}
If you wish to use it within publish_mqtt you need to shift the scope of the variable to be one that covers both functions. Ie:
mqtt_broker_handle_t *broker = NULL;
int mqtt_connection()
{
broker = mqtt_connect(client_name, ip_addr, port);
...
}
int publish_mqtt()
{
...
}
Here is a simple program using libevent on linux, it tracks the stdout fd, when it's writable, the callback will print some info to stdout.
Code
hello_libevent.c:
// libevent hello
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <event2/event.h>
#include <event2/thread.h>
void event_callback(evutil_socket_t fd, short events, void *arg) {
if(events | EV_WRITE) {
write(fd, "hello\n", 7);
}
sleep(1);
}
int libevent_test() {
int opr;
// enable pthread
if(evthread_use_pthreads() == -1) {
printf("error while evthread_use_pthreads(): %s\n", strerror(errno));
return -1;
}
// create event_base
struct event_base* eb;
if((eb = event_base_new()) == NULL) {
printf("error while event_base_new(): %s\n", strerror(errno));
return -1;
}
// create event
int fd_stdout = fileno(stdout);
struct event* event_stdout;
event_stdout = event_new(eb, fd_stdout, EV_WRITE, &event_callback, NULL);
// add event as pending
struct timeval timeout = {10, 0};
if(event_add(event_stdout, &timeout) == -1) {
printf("error while event_add(): %s\n", strerror(errno));
return -1;
}
// dispatch
if((opr = event_base_loop(eb, EVLOOP_NONBLOCK)) == -1) {
printf("error while event_base_dispatch(): %s\n", strerror(errno));
return -1;
} else if(opr == 1) {
printf("no more events\n");
} else {
printf("exit normally\n");
}
// free event
event_free(event_stdout);
return 0;
}
int main(int argc, char * argv[]) {
return libevent_test();
}
Compile:
gcc -Wall hello_libevent.c -levent -levent_pthreads
Execution result:
hello
no more events
Questions:
In the test, event only occur once, is that the expected behavior? Or it should loop to get more event until timeout?
How to make it get event continuously? Is it necessary to call event_base_loop within a loop, while it's already a loop?
I think the event flag EV_PERSIST mentioned in event.h File Reference might help.
Persistent event: won't get removed automatically when activated.
When a persistent event with a timeout becomes activated, its timeout is reset to 0.
Instead of
//...
event_stdout = event_new(eb, fd_stdout, EV_WRITE, &event_callback, NULL);
//...
you can pass this flag to event_new
//...
event_stdout = event_new(eb, fd_stdout, EV_WRITE|EV_PERSIST, &event_callback, NULL);
//...
and the other parts of code remain unchanged. At this time you create and add an event once and there's no need to call event_base_loop within a loop.
The compiled program just keeps printing lines of "hello" until it is terminated.
By the way, I noticed that changing
write(fd, "hello\n", 7);
into
write(fd, "hello\n", 6);
eliminates the leading character '\0' of each line.
From http://www.wangafu.net/~nickm/libevent-book/Ref3_eventloop.html it looks like you can call event_base_loop or event_base_dispatch from within a loop.
while (1) {
/* This schedules an exit ten seconds from now. */
event_base_loopexit(base, &ten_sec);``
event_base_dispatch(base);
puts("Tick");
}
The main purpose of events is to inform some busy thread about some event that happened elsewhere. So, this looks logical.
How do you listen to changes in volume on the Master channel on the default sound card? I'd like to be notified through dbus or a callback or something that the volume has changed.
I have tried looking and the ALSA and PulseAudio APIs and they only seem to allow you to set and get the volume, but not listen for changes in the volume.
Any programming language is fine.
Edit: In the second example, an event isn't generated for me when volume is below 5% or above 100%. The first example works perfectly as far as I know.
pactl subscribe will print out data about the sinks when the volume changes. What I'm doing now is piping the output to a small C program that will run a script.
run.sh:
pactl subscribe | grep --line-buffered "sink" | ./prog
or for a specific sink, e.g. 3:
pactl subscribe | grep --line-buffered "sink #3" | ./prog
prog.c:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[]){
while(1){
while(getchar() != '\n');
system("./volume_notify.sh");
}
}
When the volume of the sink is changed, pactl will print a line, which will cause the program to run the script.
-or-
Here's an example based on the amixer monitor, as referenced by CL.
The while loop will iterate each time the volume changes, so put your callback in there.
#include <stdio.h>
#include <alsa/asoundlib.h>
#define MAX_CARDS 256
int monitor_native(char const *name);
int open_ctl(const char *name, snd_ctl_t **ctlp);
void close_all(snd_ctl_t* ctls[], int ncards);
int main(int argc, char* argv[]){
const char *ctl_name = "hw:0";
while(monitor_native(ctl_name) == 1){
//volume has been changed, do something
system("~/.volume_notify.sh");
}
return 0;
}
int monitor_native(char const *name) {
snd_ctl_t *ctls[MAX_CARDS];
int ncards = 0;
int i, err = 0;
if (!name) {
int card = -1;
while (snd_card_next(&card) >= 0 && card >= 0) {
char cardname[16];
if (ncards >= MAX_CARDS) {
fprintf(stderr, "alsactl: too many cards\n");
close_all(ctls, ncards);
return -E2BIG;
}
sprintf(cardname, "hw:%d", card);
err = open_ctl(cardname, &ctls[ncards]);
if (err < 0) {
close_all(ctls, ncards);
return err;
}
ncards++;
}
} else {
err = open_ctl(name, &ctls[0]);
if (err < 0) {
close_all(ctls, ncards);
return err;
}
ncards++;
}
for (;ncards > 0;) {
pollfd* fds = new pollfd[ncards];
for (i = 0; i < ncards; i++) {
snd_ctl_poll_descriptors(ctls[i], &fds[i], 1);
}
err = poll(fds, ncards, -1);
if (err <= 0) {
err = 0;
break;
}
for (i = 0; i < ncards; i++) {
unsigned short revents;
snd_ctl_poll_descriptors_revents(ctls[i], &fds[i], 1, &revents);
if (revents & POLLIN) {
snd_ctl_event_t *event;
snd_ctl_event_alloca(&event);
if (snd_ctl_read(ctls[i], event) < 0) {
continue;
}
if (snd_ctl_event_get_type(event) != SND_CTL_EVENT_ELEM) {
continue;
}
unsigned int mask = snd_ctl_event_elem_get_mask(event);
if (mask & SND_CTL_EVENT_MASK_VALUE) {
close_all(ctls, ncards);
return 1;
}
}
}
}
close_all(ctls, ncards);
return 0;
}
int open_ctl(const char *name, snd_ctl_t **ctlp) {
snd_ctl_t *ctl;
int err;
err = snd_ctl_open(&ctl, name, SND_CTL_READONLY);
if (err < 0) {
fprintf(stderr, "Cannot open ctl %s\n", name);
return err;
}
err = snd_ctl_subscribe_events(ctl, 1);
if (err < 0) {
fprintf(stderr, "Cannot open subscribe events to ctl %s\n", name);
snd_ctl_close(ctl);
return err;
}
*ctlp = ctl;
return 0;
}
void close_all(snd_ctl_t* ctls[], int ncards) {
for (ncards -= 1; ncards >= 0; --ncards) {
snd_ctl_close(ctls[ncards]);
}
}
This is possible with the ALSA API.
When you have a control device, call snd_ctl_subscribe_events() to enable events.
Then use snd_ctl_read() to read events; to wait for them, use blocking mode or poll().
If the event is of type SND_CTL_EVENT_ELEM, and if its event bit mask contains SND_CTL_EVENT_MASK_VALUE, that element's value has changed.
See the implementation of amixer monitor for an example.
Similar to #sealj553's answer, but does not need a C-program:
pactl subscribe | grep --line-buffered "sink" | xargs -n1 ./volume_notify.sh
When I call the function PeekEvents below the program prints zeros on the standard output and never finishes even though I type on the keyboard when the SDL window has focus. Why doesn't the function catch my keystrokes?
void PeekEvents(void)
{
SDL_Event events[1];
int count;
do {
count = SDL_PeepEvents(events, LEN(events), SDL_PEEKEVENT, SDL_EVENTMASK(SDL_KEYDOWN));
printf("%d\n", count);
} while (count == 0);
}
Here is the complete program:
#include <SDL/SDL.h>
#include <stdio.h>
#define LEN(a) ((int) (sizeof (a) / sizeof (a)[0]))
static void PeekEvents(void)
{
SDL_Event events[1];
int count;
do {
count = SDL_PeepEvents(events, LEN(events), SDL_PEEKEVENT, SDL_EVENTMASK(SDL_KEYDOWN));
printf("%d\n", count);
} while (count == 0);
}
static void Init(int *error)
{
SDL_Surface *display;
*error = SDL_Init(SDL_INIT_VIDEO);
if (! *error) {
display = SDL_SetVideoMode(640, 480, 8, 0);
if (display != NULL) {
*error = 0;
} else {
fprintf(stderr, "SDL_SetVideoMode: %s\n", SDL_GetError());
*error = 1;
}
} else {
fprintf(stderr, "SDL_Init: %s\n", SDL_GetError());
*error = 1;
}
}
int main(void)
{
int error;
Init(&error);
if (! error) {
PeekEvents();
}
return error;
}
Documentation states somewhere that SDL_INIT_EVENTS is implicit when using SDL_INIT_VIDEO.
You need to add a call to SDL_PumpEvents in your loop, otherwise no messages will ever get in the queue.
SDL_PumpEvents gathers all the pending input information from devices and places it on the event queue. Without calls to SDL_PumpEvents no events would ever be placed on the queue. Often the need for calls to SDL_PumpEvents is hidden from the user since SDL_PollEvent and SDL_WaitEvent implicitly call SDL_PumpEvents. However, if you are not polling or waiting for events (e.g. you are filtering them), then you must call SDL_PumpEvents to force an event queue update.