gadgets-OSC/showbuttons.c
2024-03-31 21:46:50 +02:00

341 lines
7.2 KiB
C

/*
* SHOW BUTTONS
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <errno.h>
#include <getopt.h>
#include <lo/lo.h>
#include "functions/ncursefuncs.h"
/* ----------------------------------------------------------------- */
#define LOCAL_PORT "9002"
#define NB_BUTTONS 24
int verbosity;
typedef struct {
int type;
int value;
char texte[20];
} Event;
#define BUTTONS_EV 1
#define XY_EV 2
#define ID_EV 3
static int count;
static int pipefd[2];
#define EVNT_RD (pipefd[0])
#define EVNT_WR (pipefd[1])
unsigned char buttons[NB_BUTTONS];
short xy_values[2];
/* ----------------------------------------------------------------- */
#define LINE0 8 /* vertical position of the top line */
int draw_buttons(unsigned char *states, int nbre, int unused)
{
int idx, pos_c, pos_l;
char txt[20];
#if DEBUG_LEVEL
fprintf(stderr, "--> %s ( %p %d )\n", __func__, states, nbre);
#endif
for (idx=0; idx<nbre; idx++) {
pos_c = 5 + ((idx % 8) * 9);
pos_l = LINE0 + ((idx / 8) * 5);
sprintf(txt, "%03d", idx);
draw_a_button(stdscr, pos_l, pos_c, txt, states[idx]);
}
return 0;
}
/* ----------------------------------------------------------------- */
int display_a_value(int lig, short value, char letter)
{
char buffer[80], symbol;
int width, seuil, foo;
width = 60;
sprintf(buffer, "%6d [", value);
mvaddstr(lig, 4, buffer);
mvaddch(lig, width+12, ']');
if (value < 0) symbol = '-';
else symbol = '+';
seuil = (abs((int)value) * width) / 32767;
#if DEBUG_LEVEL > 1
fprintf(stderr, "in %s : value=%6d, seuil=%d\n", __func__, value, seuil);
#endif
for (foo=0; foo<width; foo++) {
if (foo < seuil) mvaddch(lig, foo+12, symbol);
else mvaddch(lig, foo+12, ' ');
}
refresh();
#if DEBUG_LEVEL > 1
sprintf(buffer, "%s : %6d ", __func__, value);
blast_error_message(buffer, 0, 0);
#endif
return 0;
}
/* ----------------------------------------------------------------- */
int display_values(short *vals, int nbre, int ligne)
{
int foo;
char buffer[80];
for (foo=0; foo<nbre; foo ++) {
display_a_value(ligne + foo, vals[foo], '?');
}
return 0;
}
/* ----------------------------------------------------------------- */
int animation(int cycles, int speed)
{
int foo;
short values[2];
#if DEBUG_LEVEL
fprintf(stderr, "entering %s ( %d %d )\n", __func__, cycles, speed);
#endif
for (foo=0; foo<cycles; foo++) {
draw_buttons(buttons, NB_BUTTONS, 0);
display_values(values, 2, 2);
refresh();
usleep(speed*1000);
buttons[rand()%NB_BUTTONS] = rand() & 1;
values[0] += rand() % 320;
values[0] = abs(values[0]);
if (rand()%100 < 10)
values[1] = rand() % 32000;
}
/* may be we can make some cleanup after the show ? */
return 0;
}
/* ----------------------------------------------------------------- */
int do_animation(int cycles, int speed)
{
(void)initcurses();
animation(cycles, speed);
sleep(2); exit(0);
return 0;
}
/* ----------------------------------------------------------------- */
void error(int num, const char *msg, const char *path)
{
fprintf(stderr, "liblo server error %d in path %s : %s\n", num, path, msg);
exit(1);
}
/* ----------------------------------------------------------------- */
int xy_handler(const char *path, const char *types, lo_arg ** argv,
int argc, void *data, void *user_data)
{
int x, y, foo;
Event evt;
#if DEBUG_LEVEL
fprintf(stderr, "%s : %s %s %d %p\n", __func__,
path, types, argc, user_data);
#endif
x = argv[0]->i; y = argv[1]->i;
/* may be we can bound-check that pair or values ? */
xy_values[0] = x; xy_values[1] = y;
evt.type = XY_EV; evt.value = 0x55;
foo = write(EVNT_WR, &evt, sizeof(Event));
if (sizeof(Event) != foo) {
fprintf(stderr, "%s : fifo error %d\n", __func__, errno);
exit(1);
}
count++;
return 0;
}
/* ----------------------------------------------------------------- */
int id_handler(const char *path, const char *types, lo_arg ** argv,
int argc, void *data, void *user_data)
{
Event evt;
int foo;
evt.type = ID_EV; evt.value = 0x55;
foo = write(EVNT_WR, &evt, sizeof(Event));
if (sizeof(Event) != foo) {
fprintf(stderr, "%s : fifo error %d\n", __func__, errno);
exit(1);
}
return 0;
}
/* ----------------------------------------------------------------- */
int button_handler(const char *path, const char *types, lo_arg ** argv,
int argc, void *data, void *user_data)
{
// char ligne[80];
int button, state, foo;
Event evt;
#if DEBUG_LEVEL
fprintf(stderr, "%s : %s %s %d %p\n", __func__,
path, types, argc, user_data);
#endif
button = argv[0]->i; state = argv[1]->i;
if (button<0 || button>=NB_BUTTONS) {
return 1;
}
((unsigned char *)user_data)[button] = state;
evt.type = BUTTONS_EV; evt.value = 0x55;
foo = write(EVNT_WR, &evt, sizeof(Event));
if (sizeof(Event) != foo) {
fprintf(stderr, "%s : fifo error %d\n", __func__, errno);
exit(1);
}
count++;
return 0;
}
/* ----------------------------------------------------------------- */
static void help(int k)
{
puts("\t*** showbuttons " __DATE__ " ***");
puts("\t-a\tshow animation and exit");
puts("\t-p\tlocal udp port ("LOCAL_PORT")");
puts("\t-v\tenhance my verbosity");
exit(0);
}
/* ----------------------------------------------------------------- */
int main(int argc, char *argv[])
{
int foo;
lo_server_thread st;
char *local_port = LOCAL_PORT;
int opt;
char ligne[81];
long tdebut;
Event event;
/* parsing command line options */
while ((opt = getopt(argc, argv, "ahp:vE:C:")) != -1) {
switch (opt) {
case 'a': do_animation(200, 20); break;
case 'h': help(0); break;
case 'p': local_port = optarg; break;
case 'v': verbosity++; break;
default: exit(1);
}
}
tdebut = time(NULL);
count = 0;
/*
* setup the inter-thread event synthetizer
*/
foo = pipe(pipefd);
if (foo) {
perror("pipe for event synth");
exit(1);
}
/* set up the pretty screen user interface */
foo = initcurses();
sprintf(ligne, "showbuttons port=%s ", local_port);
foo = draw_main_screen(ligne, 0);
if (foo) {
endwin();
fprintf(stderr, "main screen : err %d\n", foo);
exit(1);
}
/* fireup the OSC liblo engine */
st = lo_server_thread_new(local_port, error);
#if DEBUG_LEVEL
fprintf(stderr, "Address of 'values' = %p\n", buttons);
#endif
lo_server_thread_add_method(st, "/joystick/b", "ii",
button_handler, buttons);
lo_server_thread_add_method(st, "/joystick/xy", "ii",
xy_handler, NULL);
lo_server_thread_start(st);
#if DEBUG_LEVEL
fprintf(stderr, "pid %d: osc server thread started\n", getpid());
#endif
sprintf(ligne, "process %d on board, captain ", getpid());
blast_error_message(ligne, 0, 0);
sleep(3);
erase_error_message(' ');
for (;;) {
/* wait for un event from liblo threads */
foo = read(EVNT_RD, &event, sizeof(Event));
if (sizeof(Event) != foo) { /* FAILURE */
perror("event fifo read error");
exit(1);
}
#if DEBUG_LEVEL
fprintf(stderr, "event %5d %8d %s\n",
event.type, event.value, event.texte);
#endif
switch (event.type) {
case BUTTONS_EV:
draw_buttons(buttons, NB_BUTTONS, 0);
break;
case XY_EV:
display_values(xy_values, 2, 4);
break;
case ID_EV:
break;
default:
blast_error_message("bad event", 0, 0);
break;
}
}
if (verbosity)
{ fprintf(stderr, "elapsed %ld s.\n", time(NULL)-tdebut); }
return 0;
}
/* ----------------------------------------------------------------- */