Compare commits

...

63 Commits

Author SHA1 Message Date
tTh
494f9ebf01 cosmetic 2024-03-31 21:46:50 +02:00
tTh
e19f6b311b cosmetic again 2024-03-31 21:35:08 +02:00
tTh
593eeeddc9 cosmetic 2024-03-31 21:25:19 +02:00
tTh
7879c84020 add z & w joystick values to sender 2024-03-31 21:12:40 +02:00
tTh
16917ad551 add mandary dependencies 2024-03-31 21:08:13 +02:00
tTh
31087627ac better err msg 2024-03-30 14:42:05 +01:00
tTh
00920841d2 commit before morning nap 2023-03-17 10:33:53 +01:00
tTh
f804d2c7ab some tuning... 2023-01-13 15:36:31 +01:00
tTh
655a528192 bla 2022-10-30 22:42:30 +01:00
tth
b55f9f3575 oups... 2022-01-08 03:52:48 +01:00
tth
85c1846a0b 2020+2 a new hope ? 2022-01-08 03:34:05 +01:00
tth
95046aa71d more debug msg 2021-07-23 23:30:52 +02:00
tth
6a1fc34031 fine tuning 2021-07-23 20:41:39 +02:00
tth
7c91072873 osc+chuck=wip 2021-07-23 14:13:56 +02:00
tth
2e9b344922 typo 2021-07-23 12:15:18 +02:00
tth
11cd7dbf5e dessiner avec chuck, premier pas 2021-07-22 18:34:34 +02:00
tth
2a8c892e33 ok 2021-07-20 22:24:05 +02:00
tth
3301315367 oups, need more tests 2021-07-20 12:04:47 +02:00
tth
030472e7d9 + send_button 2021-07-20 11:24:27 +02:00
tth
47e6f7a690 a new idea is floating 2021-07-20 11:20:03 +02:00
tth
dea4232d8e first step done ? 2021-07-09 12:46:18 +02:00
tth
5b6359ce9e changes to an unused function 2021-07-09 08:43:14 +02:00
tth
1fc36d8790 suite du projet 2021-06-29 09:57:27 +02:00
tth
1c32695589 to be continued... 2021-06-29 08:49:12 +02:00
tth
a2d33084f1 to be continued... 2021-06-29 08:38:53 +02:00
tth
55b7f5b85b laser de Gaby, le début 2021-06-29 08:12:55 +02:00
tth
5e3149e170 cpan recipe 2021-06-28 17:43:09 +02:00
tth
2e4aa5ee22 print the name of the stick 2021-06-07 09:28:59 +02:00
tth
cd57c7378b oups... 2021-06-07 09:19:21 +02:00
tth
5e8b0e498a bla 2020-11-08 17:35:29 +01:00
tth
3fa163cc2d fedora 2020-11-07 23:17:57 +01:00
tth
6fdbf840b7 udp-dumper: better display 2020-11-04 09:46:21 +01:00
tth
c1327cf318 NON WORKING CODE 2020-11-02 08:41:33 +01:00
tth
87e2dfa4c8 bla 2020-10-31 02:24:50 +01:00
tth
8dc0acc382 loth project, next step again 2020-10-31 02:12:17 +01:00
tth
2e2db9d427 loth project, next step 2020-10-31 01:08:23 +01:00
tth
f33a0189a5 go go go 2020-10-30 22:39:26 +01:00
tth
9c4595ef4c begining of the Loth project 2020-10-30 22:37:05 +01:00
tth
36f712dc98 asyncburp: boilerplate 2020-10-30 22:21:20 +01:00
tth
18b0fceff4 better error message 2020-10-27 09:42:14 +01:00
tth
11eca2fdc7 adding more bugs... 2020-10-20 10:00:55 +02:00
tth
7cc708c0fd update du couvre-feu 2020-10-17 00:53:45 +02:00
tth
5029f59dd0 more doc again 2020-10-12 15:13:58 +02:00
tth
7d3b81c3bf +s 2020-10-12 14:11:46 +02:00
tth
608d18bb30 more doc 2020-10-12 14:00:28 +02:00
tth
845450cad2 variations 2020-10-12 13:53:08 +02:00
tth
14c673f7e0 bla... 2020-10-11 23:23:31 +02:00
tth
ada15d4817 fine tuning ? 2020-10-10 13:52:53 +02:00
tth
10568aa609 more doc 2020-10-10 08:57:55 +02:00
tth
17cf449e0a more doc 2020-10-10 02:15:33 +02:00
tth
d5d858a043 expand -h option 2020-10-09 23:35:01 +02:00
tth
a724173b76 tweaking... 2020-10-09 23:27:29 +02:00
tth
a2e28adcd9 premiere version du translateur Joystick -> Laser 2020-10-09 20:58:37 +02:00
tth
7d961bc79f Merge branch 'master' of ssh://tetalab.org:2213/tTh/gadgets-OSC
expect garbage !
2020-10-09 02:38:37 +02:00
tth
5e8ce2e84e add generators/lissajous.pl 2020-10-09 02:38:03 +02:00
tonton Th
2ce7b5dd14 adding udp-dumper.c bis 2020-04-14 13:07:57 +02:00
tonton Th
1b26e5b328 adding udp-dumper.c 2020-04-14 13:07:21 +02:00
tonton Th
a3aa74b3b9 converting to python3 2020-04-14 11:08:52 +02:00
tth
cff083a21d reworking the kluge 2020-02-21 18:05:13 +01:00
tth
e540df566a use also the numeric digits 2019-08-28 23:08:53 +02:00
tth
0f386d0d29 minor tweak 2019-08-28 22:42:57 +02:00
tth
244ff8d131 demo Blaise = bonaldi 2019-08-28 22:39:06 +02:00
tth
517b381360 adding text2osc, need more cleanup 2019-08-25 16:51:36 +02:00
63 changed files with 2788 additions and 58 deletions

15
.gitignore vendored
View File

@@ -4,6 +4,8 @@ tarball
osc2cursor
osc-joy
text2osc
showbuttons
doc/*.toc
doc/*.log
@@ -14,3 +16,16 @@ doc/*.ilg
doc/*.ind
functions/*.[oa]
tools/udp-dumper
tools/wait-for-joystick
tools/*.o
Gaby/*.[oa]
Gaby/gabylaser
Gaby/DUMP*
specific/joy2laser
specific/asyncburp
specific/*.o

30
Gaby/Makefile Normal file
View File

@@ -0,0 +1,30 @@
# ------------------------------------------------------
# Piloter le laser de Gaby
# ------------------------------------------------------
DEPS = Makefile transmit.h receive-osc.h
receive-osc.o: receive-osc.c $(DEPS)
gcc -Wall -c $<
transmit.o: transmit.c $(DEPS)
gcc -Wall -c $<
audiodrive.o: audiodrive.c $(DEPS)
gcc -Wall -c $<
# ------------------------------------------------------
gabylaser.o: gabylaser.c $(DEPS)
gcc -Wall -c $<
OBJS = receive-osc.o transmit.o
gabylaser: gabylaser.o $(DEPS) $(OBJS)
gcc -Wall $< $(OBJS) -llo -o $@
# ------------------------------------------------------

44
Gaby/README.md Normal file
View File

@@ -0,0 +1,44 @@
# Le laser de Gaby
Une nouvelle aventure se prépare à Valensole, en voici l'histoire...
## Caractéristiques
Encore très flou, mais où donc est rangée cette doc ?
- position X/Y par deux valeurs analogiques
- niveau RGB par trois signaux PWM
https://en.wikipedia.org/wiki/International_Laser_Display_Association
## Logiciels
Deux composantes : le contrôleur "physique" du laser tournera dans
un Arduino Mega, et sera lui même piloté par un "récepteur" OSC dans
la machine hote. Ces deux parties vont communiquer par le classique
lien série/usb avec un protocole encore à définir.
### Coté hote/OSC
Dans un premier temps, je vais reprendre mon protocole utilisé pour
les joysticks, d'abord pour le positionnement X/Y, et ensuite pour
la gestion du RGB.
### Coté Arduino
Les choses sont moins claires, car j'ignore encore certaines choses comme
la qualité des sortie analogiques de l'Arduino. Il sera peut-être
nécessaire de conditionner les deux valeurs (intégration, gain, offset)
par un matériel approprié.
D'autre part, la fréquence de rafraichissement sera-elle suffisante ?
Et pour finir y aura-t-il assez de mémoire RAM pour stocker des dessins
de taille conséquente ?
## Conclusion
Il faut maintenant envoyer le Gobeti :)

13
Gaby/audiodrive.c Normal file
View File

@@ -0,0 +1,13 @@
/*
* LE LASER DE GABY
*
* +--------------------------------------------------+
* | pilotage du bouzin par la sortie audio (wtf?) |
* +--------------------------------------------------+
*/
/**** note de l'auteur : on devrait essayer de faire ça en chuck ***/
#include <stdio.h>
/* ---------------------------------------------------------------- */

8
Gaby/burps.sh Executable file
View File

@@ -0,0 +1,8 @@
#!/bin/bash
for x in $(seq -32000 133 32000)
do
echo $x
oscsend localhost 9001 /joystick/xy ii $x -9999
done

102
Gaby/gabylaser.c Normal file
View File

@@ -0,0 +1,102 @@
/*
* LE LASER DE GABY
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <getopt.h>
#include <lo/lo.h>
#include "transmit.h"
#include "receive-osc.h"
int verbosity;
/* ---------------------------------------------------------------- */
static 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 init_rx_osc(char *port)
{
lo_server_thread st;
st = lo_server_thread_new(port, error);
lo_server_thread_add_method(st, "/joystick/xy", "ii", xy_handler, NULL);
lo_server_thread_add_method(st, "/joystick/b", "ii", button_handler, NULL);
lo_server_thread_start(st);
fprintf(stderr, "%s [done]\n", __func__);
return 0;
}
/* ---------------------------------------------------------------- */
static void print_lo_version(char *bla)
{
#define SZ 100
char str[SZ];
char extra[SZ];
lo_version(str, SZ, 0, 0, extra, SZ, 0, 0, 0);
fprintf(stderr, "%s: liblo v%s %s\n", bla, str, extra);
}
/* ---------------------------------------------------------------- */
int help(int k)
{
fprintf(stderr, "help = %d\n", k);
return 1;
}
/* ---------------------------------------------------------------- */
int main(int argc, char *argv[])
{
char *local_port = "9001";
int bauds = 0;
int foo, opt;
fprintf(stderr, "GabyLaser - compiled %s %s\n", __DATE__, __TIME__);
while ((opt = getopt(argc, argv, "hp:v")) != -1) {
switch (opt) {
case 'h': if (help(0)) exit(1); break;
case 'p': local_port = optarg; break;
case 'v': verbosity++; break;
}
}
if (verbosity) print_lo_version(argv[0]);
foo = init_rx_osc(local_port);
if (foo) {
fprintf(stderr, "init rx osc -> %d\n", foo);
exit(1);
}
foo = init_transmit("./DUMP", bauds);
if (foo < 0) {
fprintf(stderr, "init transmit -> %d\n", foo);
exit(1);
}
/*
* infinite loop is infinite
*/
for (;;) {
if (verbosity)
fprintf(stderr, "t = %ld\n", time(NULL));
sleep(100);
}
return 0;
}
/* ---------------------------------------------------------------- */

13
Gaby/protocole.md Normal file
View File

@@ -0,0 +1,13 @@
# Le protocole
Le lien série-sur-usb de l'arduino est parfois capricieux et souvent
plein de mystères...
Ayant de gros doutes sur sa capacité à transmettre des données binaires,
le choix d'un codage ASCII semble évident.
D'un autre coté, le débit du lien est assez faible, il faut compacter
le plus possible les données transférées. Un encodage type `base64`
est-il la bonne solution ?

56
Gaby/receive-osc.c Normal file
View File

@@ -0,0 +1,56 @@
/*
* LE LASER DE GABY
*
* +--------------------------------------------------+
* | reception des trames osc depuis le grand monde |
* +--------------------------------------------------+
*/
#include <stdio.h>
#include <lo/lo.h>
#include "receive-osc.h"
#include "transmit.h"
/* ---------------------------------------------------------------- */
static int old_x, old_y;
int xy_handler(const char *path, const char *types, lo_arg ** argv,
int argc, void *data, void *user_data)
{
int val_x, val_y;
int foo;
// fprintf(stderr, ">>> %s ( '%s' '%s' )\n", __func__, path, types);
val_x = argv[0]->i; val_y = argv[1]->i;
fprintf(stderr, "osc -> %7d %7d\n", val_x, val_y);
if (old_x != val_x) {
foo = send_position('X', val_x);
old_x = val_x;
}
if (old_y != val_y) {
foo = send_position('Y', val_y);
old_y = val_y;
}
return -1;
}
/* ---------------------------------------------------------------- */
int button_handler(const char *path, const char *types, lo_arg ** argv,
int argc, void *data, void *user_data)
{
int foo;
fprintf(stderr, ">>> %s ( '%s' '%s' )\n", __func__, path, types);
foo = send_button(argv[0]->i, argv[1]->i);
return -1;
}
/* ---------------------------------------------------------------- */

12
Gaby/receive-osc.h Normal file
View File

@@ -0,0 +1,12 @@
int xy_handler(const char *path, const char *types, lo_arg ** argv,
int argc, void *data, void *user_data);
int button_handler(const char *path, const char *types, lo_arg ** argv,
int argc, void *data, void *user_data);

126
Gaby/transmit.c Normal file
View File

@@ -0,0 +1,126 @@
/*
* LE LASER DE GABY
*
* +---------------------------------------------+
* | transmission des commandes vers l'arduino |
* +---------------------------------------------+
$ oscsend localhost 9001 /joystick/xy ii 32000 -2210
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include "../functions/serial.h"
#include "transmit.h"
/* ---------------------------------------------------------------- */
static int fdtx = -1;
/* ---------------------------------------------------------------- */
/*
* parametres :
* fname: a file for dumping data or a serial device
* bauds: speed of serial port, 0 for a file dump
*
*/
int init_transmit(char *fname, int bauds)
{
int fd;
int baudsymb;
fprintf(stderr, ">>> %s ( '%s' %d )\n", __func__, fname, bauds);
if (0 == bauds) {
/* open as a dump file */
fd = open(fname, O_CREAT|O_WRONLY|O_TRUNC, S_IRWXU);
if (fd < 0) {
perror(fname);
exit(1);
}
}
else {
/* open as as a serial out to Arduino */
fprintf(stderr, "bauds are %d, exiting\n", bauds);
exit(1);
/* XXX */
}
fdtx = fd;
fprintf(stderr, "%s: fd is %d\n", __func__, fdtx);
return fd;
}
/* ---------------------------------------------------------------- */
/*
* ici on présupoose que la valeur est un "short int"
* donc 2^16 valeurs -32768 32767
*/
int send_position(char xy, int value)
{
char message[100];
char val8;
int foo;
if (fdtx < 0) {
fprintf(stderr, "%s: fdtx not initialized !\n", __func__);
exit(1);
}
if (xy != 'X' && xy != 'Y') {
fprintf(stderr, "%s: invalid xy tag '%c'\n", __func__, xy);
return -1;
}
val8 = (char)(value / 256); /* -> signed byte */
sprintf(message, "%c%02x", xy, (unsigned char)val8);
fprintf(stderr, " %c %8d %8d %s\n", xy, value, val8, message);
foo = write(fdtx, message, 3);
if (3 != foo) {
perror("write ?");
return -1;
}
return 0;
}
/* ---------------------------------------------------------------- */
/*
* comment gerer le up/down des boutons ?
*/
int send_button(int number, int state)
{
char message[100];
if (fdtx < 0) {
fprintf(stderr, "%s: fdtx not initialized !\n", __func__);
exit(1);
}
if (number<0 || number>16) {
return -1;
}
sprintf(message, "T%01x%1x", number, state);
fprintf(stderr, "%s ----> '%s'\n", __func__, message);
foo = write(fdtx, message, 3);
if (3 != foo) {
perror("write ?");
return -1;
}
return 0;
}
/* ---------------------------------------------------------------- */

13
Gaby/transmit.h Normal file
View File

@@ -0,0 +1,13 @@
/*
* LE LASER DE GABY
*
* +---------------------------------------------+
* | transmission des commandes vers l'arduino |
* +---------------------------------------------+
*/
int init_transmit(char *fname, int k);
int send_position(char xy, int value);
int send_button(int number, int state);

6
Loth/Makefile Normal file
View File

@@ -0,0 +1,6 @@
# ----------------------------------------------------------
#
#

31
Loth/README.md Normal file
View File

@@ -0,0 +1,31 @@
# Loth Hacks for fun and profit
Le problème est complxe : comment découvrir l'adresse IP d'un machin
qui tourne avec MadMapper ?
Il y a toute une procédure vu que leur truc utilise __Bonjour__ pour
découvrir leurs adresses IP.
`$ mdns-scan` et ensuite, si on repère indice MINIMAD avec ce
que semble être une adresse MAC :
`/usr/sbin/arp -a | grep b8:27:eb:51:db:32`
Mais il y a aussi b8:27:eb:be:18:9f ???
## en shell
Les paramètres sont dans `config.sh` pour adresser les madboites
vidéo et lumière.
Voir `play.sh`.
## en C
Krkrkr...
## Et ensuite ?
Une petite bière ?

8
Loth/config.sh Normal file
View File

@@ -0,0 +1,8 @@
# LOTH PROJECT
# config pour le MapMachin
IP_VIDEO="10.20.25.6"
IP_LIGHT="localhost"
R_PORT="1111"

19
Loth/play.sh Executable file
View File

@@ -0,0 +1,19 @@
#!/bin/bash
source config.sh
function envoyer
{
msg=$1
echo $msg
oscsend $IP_VIDEO $R_PORT $msg
}
envoyer "/play"
sleep 15
envoyer "/pause"

26
Loth/sender.sh Executable file
View File

@@ -0,0 +1,26 @@
#!/bin/bash
#
# c'est juste du code d'exemple
#
R_IP="10.20.31.170"
R_PORT="1111"
DEVICE=42
oscpath=$(printf "/loth/truc/%d" $DEVICE)
oscsend $R_IP $R_PORT $oscpath s "==========="
for foo in $(seq 20 7 80)
do
echo " " $foo
message=$(printf " 0x%02x" $foo)
oscsend $R_IP $R_PORT $oscpath s "$message"
sleep 1
done

2
MIDI/README.md Normal file
View File

@@ -0,0 +1,2 @@
# Musical Instrument Digital Interface

View File

@@ -1,10 +1,14 @@
# ----------------------------------------------------
# --------------------------------------------------------------
# umpf...
OPTS = -Wall -g -DDEBUG_LEVEL=1
OPTS = -Wall -g -DDEBUG_LEVEL=0
DEPS = Makefile functions/senders.h functions/joyutils.h \
functions/ncursefuncs.h
# ----------------------------------------------------
all: osc-joy osc2cursor text2osc showbuttons
# --------------------------------------------------------------
osc2cursor: osc2cursor.c ${DEPS} functions/libpocosc.a
gcc ${OPTS} $< functions/libpocosc.a -llo -lcurses -o $@
@@ -12,4 +16,12 @@ osc2cursor: osc2cursor.c ${DEPS} functions/libpocosc.a
osc-joy: osc-joy.c ${DEPS} functions/libpocosc.a
gcc ${OPTS} $< functions/libpocosc.a -llo -o $@
# ----------------------------------------------------
text2osc: text2osc.c ${DEPS} functions/libpocosc.a
gcc ${OPTS} $< functions/libpocosc.a -llo -o $@
# --------------------------------------------------------------
showbuttons: showbuttons.c functions/libpocosc.a ${DEPS}
gcc ${OPTS} $< functions/libpocosc.a -llo -lcurses -o $@
# --------------------------------------------------------------

View File

@@ -1 +1,58 @@
# Gadgets autou du protocole OSC
# Gadgets autour du protocole OSC
Oui, je sais, tout ça n'est pas vraiment clair. Mais je me soigne.
Première étape : consulter le
[site d'OSC](https://opensoundcontrol.stanford.edu/) pour comprendre comment
ça fonctionne.
## prérequis
Première étape avant de générer les binaires, installer quelques
bibliothèques de support :
```
apt install liblo-tools liblo-dev
apt install libasound2-dev
apt install ncurses-dev
```
Plus le module Perl `Net::OpenSoundControl` à chercher dans le CPAN.
Ensuite, il faut compiler quelques fonctions utilisées par plusieurs
exemples :
```
cd functions
make
```
Et ensuite `make` dans le répertoire de base, je pense que c'est
assez simple, et parfois ça marche...
# Les programmes
## osc-joy
Lecture d'une manette de jeu USB et envoi des coordonnées x/y/z/w
et des boutons vers un écouteur OSC.
L'option `-o NN` rajoute NN au numéro de bouton.
Voir les [générateurs](generators/) pour les détails.
## osc2cursor
Une appli ncurses trop choupie :)
## text2osc
Pour faire __beep__ vers Chuck...
## showbuttons
Presque fini depuis quelques mois/années.

16
chuck/README.md Normal file
View File

@@ -0,0 +1,16 @@
# trucs en ChucK
Attention, il faut parfois utiliser l'option `--silent`
pour lancer Chuck sans connexion audio.
## dessiner.ck
Faire des courbes de Lissajous...
## pouet.ck
## midi2osc.ck
## zwouik.ck

46
chuck/dessiner.ck Normal file
View File

@@ -0,0 +1,46 @@
/*
* dessiner par OSC
* (avec le laser de Gaby ?)
*
* nouveau Rural Art System 2021 - TerreBlanque
*
*/
9000 => int OSCPort;
32760.0 => float Amplitude;
OscOut xmit;
float dx, dy;
xmit.dest("localhost", OSCPort);
clear_the_screen();
for (0 => int foo; foo<25800; foo++) {
<<< foo >>>;
Amplitude * Math.sin(foo * 0.3001) => dx;
Amplitude * Math.cos(foo * 0.4999) => dy;
xmit.start("/joystick/xy");
Std.ftoi(dx) => xmit.add;
Std.ftoi(dy) => xmit.add;
xmit.send();
0.025::second => now;
}
// ----------------------------------------------------
fun void clear_the_screen()
{
xmit.start("/joystick/b");
50 => xmit.add; 1 => xmit.add;
xmit.send();
xmit.start("/joystick/b");
50 => xmit.add; 0 => xmit.add;
xmit.send();
}
// ----------------------------------------------------

43
chuck/midi2osc.ck Normal file
View File

@@ -0,0 +1,43 @@
/*
* recevoir des notes on/off par le MIDI
* et envoyer des boutons de joy par OSC
*
* nouveau Rural Art System 2021 - TerreBlanque
*/
MidiIn input;
MidiMsg msg;
OscOut xmit;
1 => int port; // please explain
9000 => int OSCPort;
if (!input.open(port)) {
<<< "erreur open" >>>;
me.exit();
}
// print out device that was opened
<<< "MIDI device:", input.num(), " -> ", input.name() >>>;
xmit.dest("localhost", OSCPort);
// infinite loop
while (1) {
input => now;
while ( input.recv(msg) ) {
<<< msg.data1, msg.data2, msg.data3 >>>;
xmit.start("/joystick/b");
}
}

42
chuck/pouet.ck Normal file
View File

@@ -0,0 +1,42 @@
/*
faire pouet avec chuck osc et un joystick
-----------------------------------------
reception des boutons
*/
7778 => int InPort;
SqrOsc sl => Envelope envl => dac.left;
SawOsc sr => Envelope envr => dac.right;
0.5 => sl.gain => sr.gain;
0.22 => envl.time; 0.22 => envr.time;
OscIn oscin; OscMsg msg;
InPort => oscin.port; oscin.addAddress( "/joystick/b, ii" );
int button, value; 50 => int base;
<<< "listening on port", InPort >>>;
while( true ) {
oscin => now;
while ( oscin.recv(msg) ) {
msg.getInt(0) => button;
msg.getInt(1) => value;
<<< "got (via ", InPort,")\tb", button, "\tv", value >>>;
if (1 == value) { /* button down */
Std.mtof(base+(button)) => sl.freq;
Std.mtof(base+12+(button)) => sr.freq;
1 => envl.keyOn => envr.keyOn;
}
else {
1 => envl.keyOff => envr.keyOff;
}
0.1::second => now;
}
}
/* made in pi-ta-mere by tTh */

42
chuck/zwouit.ck Normal file
View File

@@ -0,0 +1,42 @@
/*
-----------------------------------------
reception des XY
*/
7777 => int InPort;
15.55 => float divisor;
SqrOsc sl => dac.left;
SawOsc sr => dac.right;
0.0 => sl.gain => sr.gain;
OscIn oscin;
OscMsg msg;
InPort => oscin.port;
oscin.addAddress( "/joystick/xy, ii" );
int x, y;
55 => int base;
0.5 => sl.gain => sr.gain;
<<< "listening on port", InPort >>>;
while( true ) {
oscin => now;
while ( oscin.recv(msg) ) {
msg.getInt(0) => x;
msg.getInt(1) => y;
<<< "got (via ", InPort,") ", x, y >>>;
x/12.0 => sl.freq;
y/12.0 => sr.freq;
}
}
/* made in doubledragon2 by tTh */
/* --------------------------------------------------------
conversion coordonnées vers frequence */

View File

@@ -24,10 +24,15 @@
\section{Open Sound Control}
De quoi parle-t-on exactement ?
\vspace{5em}
OSC est un protocole réseau basé sur UDP\index{UDP}.
% -------------------------------------------------------------------
\section{Example}
TODO\index{TODO}
% -------------------------------------------------------------------

4
functions/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
mkbigchars
t

BIN
functions/8x8thin Normal file

Binary file not shown.

View File

@@ -4,7 +4,9 @@
#
#----------------------------------------------------
OPTS = -Wall -g -DDEBUG_LEVEL=1
all: libpocosc.a
OPTS = -Wall -g -DDEBUG_LEVEL=0
senders.o: senders.c senders.h Makefile
gcc ${OPTS} -c $<
@@ -15,8 +17,32 @@ alsaseq.o: alsaseq.c alsaseq.h Makefile
serial.o: serial.c serial.h Makefile
gcc ${OPTS} -c $<
joyutils.o: joyutils.c joyutils.h Makefile
gcc ${OPTS} -c $<
ncursefuncs.o: ncursefuncs.c ncursefuncs.h Makefile
gcc ${OPTS} -c $<
libpocosc.a: senders.o alsaseq.o serial.o ncursefuncs.o
#
libpocosc.a: senders.o alsaseq.o serial.o ncursefuncs.o \
joyutils.o bigchars.o
ar r $@ $?
#
mkbigchars: mkbigchars.c Makefile
gcc ${OPTS} $< -o $@
chars8x8.def: mkbigchars Makefile
./mkbigchars 8x8thin $@
bigchars.o: bigchars.c chars8x8.def ncursefuncs.h Makefile
gcc ${OPTS} -c $<
# programmes de test
t: t.c Makefile libpocosc.a ncursefuncs.h
gcc $(OPTS) $< libpocosc.a -o $@

18
functions/README.md Normal file
View File

@@ -0,0 +1,18 @@
# Fonctions diverses
## alsaseq
## joyutils
Fonction d'affichage des données du device joystick.
Utilisation : ` osc-joy -D `.
## ncursesfuncs
## senders
La seule documentation existante sur le protocole utilisé au dessus d'OSC.
## serial

44
functions/bigchars.c Normal file
View File

@@ -0,0 +1,44 @@
/*
! ncurses widgets for poc-osc
!
! nnnnn n nnnn
! n n n n n
! nnnnn n n
! n n n n nnn
! n n n n n
! nnnnn n nnnn
!
!
! nnnn n n nn nnnnn nnnn
! n n n n n n n n n
! n nnnnnn n n n n nnnn
! n n n nnnnnn nnnnn n
! n n n n n n n n n n
! nnnn n n n n n n nnnn
!
*/
#include <stdio.h>
#include <stdlib.h>
#include <curses.h>
#include <signal.h>
#include <locale.h>
#include "ncursefuncs.h"
/* XXX */
#include "chars8x8.def"
extern int verbosity; /* to be declared public near main() */
/* ----------------------------------------------------------------- */
/* ----------------------------------------------------------------- */
int essai_bigchars(char *texte, int stand)
{
fprintf(stderr, ">>> %s ( '%s' %d )\n", __func__, texte, stand);
return -1;
}
/* ----------------------------------------------------------------- */

67
functions/joyutils.c Normal file
View File

@@ -0,0 +1,67 @@
/*
* joystick utility functions
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <linux/joystick.h>
#include "joyutils.h"
/* ----------------------------------------------------------------- */
static char *type2txt(unsigned char type)
{
static char temp[100];
if (!(type & JS_EVENT_INIT)) {
switch(type) {
case JS_EVENT_BUTTON: return "button";
case JS_EVENT_AXIS: return "axis";
}
}
else {
sprintf(temp, "init %d", type & 0x7f);
return temp;
}
return "???";
}
/* ----------------------------------------------------------------- */
void dump_my_joystick(char *joy_device)
{
int joy_fd, foo;
struct js_event js;
int flag = 0;
unsigned long debut;
char joy_name[128];
if( ( joy_fd = open(joy_device , O_RDONLY)) == -1 ) {
fprintf(stderr, "%s: couldn't open %s\n", __func__, joy_device);
exit(1);
}
if (ioctl(joy_fd, JSIOCGNAME(sizeof(joy_name)), joy_name) < 0)
strncpy(joy_name, "Unknown", sizeof(joy_name));
fprintf(stderr, "Name: \"%s\"\n", joy_name);
for (;;) {
foo = read(joy_fd, &js, sizeof(struct js_event));
if (8 != foo) {
fprintf(stderr, "%s: err reading joy\n", __func__);
exit(1);
}
if ( ! flag ) {
debut = js.time;
flag = 1;
}
printf("%8lu %4d %-8s %3d %7d\n",
js.time-debut,
js.type, type2txt(js.type),
js.number, js.value);
}
}
/* ----------------------------------------------------------------- */
/* ----------------------------------------------------------------- */

6
functions/joyutils.h Normal file
View File

@@ -0,0 +1,6 @@
/*
* joystick utility functions
*/
void dump_my_joystick(char *joy_device);

77
functions/mkbigchars.c Normal file
View File

@@ -0,0 +1,77 @@
/*
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
/* ----------------------------------------------------------------- */
int make_bigfont_def(char *input, char *deffile)
{
FILE *fp;
int fd, idx, foo;
unsigned char buffer[2048];
fprintf(stderr, ">>> %s ( '%s' '%s' )\n", __func__, input, deffile);
/*
* load the binary font datas
*/
fd = open(input, O_RDONLY, 0);
if (-1 == fd) {
perror(input);
exit(1);
}
foo = read(fd, buffer, 2048);
if (2048 != foo) {
fprintf(stderr, "%s: read %d bytes, 2048 expected\n", __func__, foo);
close(fd);
return 1;
}
close(fd);
/*
* write the definition file as a .h c-file
*/
fp = fopen(deffile, "w");
if (NULL == fp) {
perror(deffile);
exit(1);
}
fprintf(fp, "/*\n * ! ! ! GENERATED FILE ! ! !\n*/\n");
for (idx=0; idx-256; idx++) {
fprintf(fp, "/*\n *\t***\t%3d 0x%02x\n */\n", idx, idx);
fprintf(fp, "\n");
}
fprintf(fp, "/* yolo? */\n");
fclose(fp);
return 0;
}
/* ----------------------------------------------------------------- */
int main(int argc, char *argv[])
{
int foo;
if (3 != argc) {
fprintf(stderr, "ERR: %s need two filenames\n", argv[0]);
exit(1);
}
foo = make_bigfont_def(argv[1], argv[2]);
if (foo) {
fprintf(stderr, "got %d from font converter.\n", foo);
exit(1);
}
return 0;
}
/* ----------------------------------------------------------------- */

View File

@@ -49,7 +49,7 @@ char ligne[81];
int foo;
#if DEBUG_LEVEL
fprintf(stderr, "--> %s ( '%s' %d )\n", __func__, title, unused);
fprintf(stderr, ">>> %s ( '%s' %d )\n", __func__, title, unused);
#endif
if (verbosity) {
@@ -68,10 +68,10 @@ return 0; /* this is not a magic number */
int blast_error_message(char *txt, int violence, int unused)
{
int line, foo;
char buff[60];
char buff[80];
#if DEBUG_LEVEL
fprintf(stderr, "--> %s ( '%s' %d %d )\n", __func__,
fprintf(stderr, ">>> %s ( '%s' %d %d )\n", __func__,
txt, violence, unused);
#endif
@@ -82,26 +82,42 @@ if (verbosity > 3) {
}
standout();
// clear our part of screen
// setup our part of screen
for (foo=0; foo<COLS; foo++) {
mvaddch(line, foo, '_');
mvaddch(line, foo, '|');
}
mvaddstr(line, 0, "SYS$MSG_ ");
mvaddstr(line, 9, txt);
mvaddstr(line, 0, "SYS$MSG_| ");
mvaddstr(line, 10, txt);
standend();
refresh();
return 0;
}
/* ----------------------------------------------------------------- */
int erase_error_message(int ascii)
{
int foo;
#if DEBUG_LEVEL
fprintf(stderr, ">>> %s ( '%c' )\n", __func__, ascii);
#endif
standout();
// clear our part of screen
for (foo=0; foo<COLS; foo++) {
mvaddch(LINES-1, foo, ascii);
}
standend(); refresh();
return 0;
}
/* ----------------------------------------------------------------- */
/* warning: only use the bit 0 of the 'state' arg */
int draw_a_button(WINDOW *w, int lig, int col, char *txt, int state)
{
#if DEBUG_LEVEL > 1
fprintf(stderr, "--> %s ( %3d %3d '%s' %d )\n", __func__,
fprintf(stderr, ">>> %s ( %3d %3d '%s' %d )\n", __func__,
lig, col, txt, state);
#endif

View File

@@ -9,6 +9,13 @@ void endcurses(int p);
int draw_main_screen(char *title, int unused);
int blast_error_message(char *txt, int violence, int unused);
int erase_error_message(int ascii);
/* warning: only use the bit 0 of the 'state' arg */
int draw_a_button(WINDOW *w, int lig, int col, char *txt, int state);
/*
* bigchars.c
*/
int essai_bigchars(char *texte, int stand);

View File

@@ -22,6 +22,19 @@ if (verbosity > 2) {
return foo;
}
/* ----------------------------------------------------------------- */
/* function added Sun Mar 31 18:51:46 UTC 2024 */
int send_data_zw(lo_address dst, int w, int z)
{
int foo;
if (verbosity) fprintf(stderr, "sending w z %7d %7d\n", w, z);
foo = lo_send(dst, "/joystick/wz", "ii", w, z);
if (verbosity > 2) {
fprintf(stderr, "lo_send -> %d\n", foo);
}
return foo;
}
/* ----------------------------------------------------------------- */
int send_data_button(lo_address dst, int n, int v)
{
int foo;

View File

@@ -5,6 +5,7 @@
/* ------------------------------------------------------- */
int send_data_xy(lo_address dst, int x, int y);
int send_data_zw(lo_address dst, int w, int z);
int send_data_button(lo_address dst, int n, int v);
int send_data_id(lo_address dst, char *s);

View File

@@ -41,22 +41,10 @@ return fd;
this will disconnect the line.
*/
int bauds_str_to_B(char *strb, int unused)
int bauds_to_B(int bauds)
{
long value;
#if DEBUG_LEVEL
fprintf(stderr, "--> %s ( '%s' 0x%x )\n", __func__, strb, unused);
#endif
if (1 != sscanf(strb, "%ld", &value)) {
return B0;
}
#if DEBUG_LEVEL
fprintf(stderr, " computed baudrate = %ld\n", value);
#endif
switch (value) {
switch (bauds) {
case 50: return B50;
case 75: return B75;
case 110: return B110;

View File

@@ -4,4 +4,5 @@
*/
int open_serial(char *dev, int bauds, int unused);
int bauds_str_to_B(char *strb, int unused);
int bauds_to_B(int bauds);

21
functions/t.c Normal file
View File

@@ -0,0 +1,21 @@
/*
*
*/
#include <stdio.h>
#include <stdlib.h>
#include "ncursefuncs.h"
/* ----------------------------------------------------------------- */
int main(int argc, char *argv[])
{
int foo;
foo = essai_bigchars("foo", 0);
fprintf(stderr, " essai bigchars -> %d\n", foo);
return 0;
}
/* ----------------------------------------------------------------- */

31
generators/README.md Normal file
View File

@@ -0,0 +1,31 @@
# Générateurs
Pour la plupart de ces logiciels, le bouton 50 est utilisé
pour demander l'effacement d'un hypothétique écran.
Voir [osc-joy](../#osc-joy) pour les détails pratiques.
```
tth@fubar:~/Devel/gadgets-OSC/generators$ ./lissajous.pl
Can't locate Net/OpenSoundControl/Client.pm in @INC
(you may need to install the Net::OpenSoundControl::Client module)
```
Oups, que faire ?
```
root@fubar:~# cpan
cpan[3]> install Net::OpenSoundControl
```
Et voilà...
## moresinus.pl
Options : `-d host:port` et `-v`
## lissajous
Options : `-d host:port` et `-v`

75
generators/lissajous.pl Executable file
View File

@@ -0,0 +1,75 @@
#!/usr/bin/perl -w
#
# Ugly code by tTh
#
my $port = 9000;
my $target = "localhost";
# ----------------------------------------------------------
use Net::OpenSoundControl::Client;
use Data::Dumper qw(Dumper);
use Getopt::Std;
my $client;
my $verbose = 0;
# ----------------------------------------------------------
sub lissajous($$$)
{
my $kx = shift; my $ky = shift;
my $phi = shift;
my ($i, $rads, $x, $y);
for ($i = 0; $i <= 360; $i++) {
$rads = $i * (3.141592654/180);
$x = int(31250*sin(($rads*$kx)+$phi));
$y = int(31250*cos($rads*$ky));
# printf "%5d %9f %6d %6d\n", $i, $rads, $x, $y;
$client->send(['/joystick/xy', 'i', $x, 'i', $y]);
# sleep 0.42;
}
sleep 1+rand(2);
$client->send(['/joystick/b', 'i', 50, 'i', 1]);
$client->send(['/joystick/b', 'i', 50, 'i', 0]);
}
# ----------------------------------------------------------
# main proggy
getopts('d:v', \%options);
if (defined $options{"d"}) {
# print Dumper $options{"d"};
($target, $port) = split /:/, $options{"d"};
}
$verbose = 1 if (defined $options{"v"});
print "trashing ", $target, " on port ", $port, "\n";
$client = Net::OpenSoundControl::Client->new(
Host => $target, Port => $port)
or die "Could not start client: $@\n";
print Dumper $client if $verbose;
my ($xk, $yk, $phase);
for ($xk=1; $xk<6; $xk++) {
for ($yk=1; $yk<6; $yk++) {
print "$$ -> $xk $yk\n";
for ($phase=0.0; $phase<1.5705; $phase+=0.0911) {
print "phi = ", $phase, "\n" if $verbose;
lissajous($xk, $yk, $phase);
}
}
}

63
generators/moresinus.pl Executable file
View File

@@ -0,0 +1,63 @@
#!/usr/bin/perl -w
use Net::OpenSoundControl::Client;
use Data::Dumper qw(Dumper);
use Getopt::Std;
my $client;
my $verbose = 0;
my $dhost = "localhost";
my $dport = 9000;
# ----------------------------------------------------------
sub AskErase($)
{
my $b = shift;
$client->send(['/joystick/b', 'i', $b, 'i', 1]);
$client->send(['/joystick/b', 'i', $b, 'i', 0]);
}
# ----------------------------------------------------------
print "--- Moresinus $$ ---\n";
getopts('d:v', \%options);
if (defined $options{"d"}) {
# print Dumper $options{"d"};
($dhost, $dport) = split /:/, $options{"d"};
}
$verbose = 1 if (defined $options{"v"});
print "trashing ", $dhost, " on port ", $dport, "\n";
$client = Net::OpenSoundControl::Client->new(
Host => $dhost, Port => $dport)
or die "Could not start client: $@\n";
print Dumper $client if $verbose;
# ----------------------------------------------------------
AskErase(50);
srand($$);
print " ", rand(1000), "\n";
my ($t, $v, $r1, $r2, $phi);
$r1 = rand(100) + 1600;
$r2 = rand(100) + 3200;
$phi = rand(3124) / 1000.0;
print " $r1 $r2 $phi\n" if $verbose;
for ($t = -32000; $t < 32000; $t+=150) {
$v = 15000 * (sin($t / $r1) + cos($phi + ($t / $r2)));
# print $t, " --> ", $v, "\n";
$client->send(['/joystick/xy', 'i', $t, 'i', $v]);
sleep 1 if (($t % 16) == 0);
}

48
generators/testkontrol.pl Executable file
View File

@@ -0,0 +1,48 @@
#!/usr/bin/perl -w
my $port = 9001;
my $target = "localhost";
# ----------------------------------------------------------
use Net::OpenSoundControl::Client;
use Data::Dumper qw(Dumper);
use Getopt::Std;
my $client;
my $verbose = 0;
# ----------------------------------------------------------
#
# MAIN
#
getopts('d:v', \%options);
if (defined $options{"d"}) {
# print Dumper $options{"d"};
($target, $port) = split /:/, $options{"d"};
}
$verbose = 1 if (defined $options{"v"});
print "trashing ", $target, " on port ", $port, "\n";
$client = Net::OpenSoundControl::Client->new(
Name => "testkontrol",
Host => $target, Port => $port)
or die "Could not start client: $@\n";
print Dumper $client if $verbose;
my ($foo, $knum, $kval);
for ($foo=0; $foo<128; $foo++) {
$kval = int(128*rand());
$knum = int(128*rand());
print "$knum -> $kval\n" if $verbose;
$client->send(['/kontrol/v', 'i', $knum, 'i', $kval]);
sleep(1);
}
# ----------------------------------------------------------

View File

@@ -21,6 +21,7 @@
#include <lo/lo.h>
#include "functions/senders.h"
#include "functions/joyutils.h"
/* default values, can be changed on command line */
@@ -39,11 +40,12 @@ char *my_id = MY_TEXT_ID;
static void help(int k)
{
puts("\t * joystick -> osc "__DATE__" *");
puts("\t-D\tdump joystick datas");
puts("\t-r\tremote host ("REMOTE_HOST")");
puts("\t-p\tremote UDP port ("REMOTE_PORT")");
puts("\t-j\tjoystick device ("JOY_DEVICE")");
puts("\t-v\tincrease verbosity");
puts("\t-o\toffset added to button number");
printf("\t-o\toffset added to button number (%d)\n", button_offset);
puts("\t-I\tchange text id (\""MY_TEXT_ID"\")");
exit(0);
}
@@ -52,16 +54,18 @@ int main(int argc, char *argv[])
{
int foo, joy_fd;
struct js_event js;
int x_pos, y_pos, flag;
int x_pos, y_pos, z_pos, w_pos, what;
char joy_name[128];
int opt;
char *remote_host = REMOTE_HOST;
char *remote_port = REMOTE_PORT;
char *joy_device = JOY_DEVICE;
int do_dump = 0;
/* parsing command line options */
while ((opt = getopt(argc, argv, "hp:r:vj:o:I:")) != -1) {
while ((opt = getopt(argc, argv, "Dhp:r:vj:o:I:")) != -1) {
switch (opt) {
case 'D': do_dump = 1; break;
case 'h': help(0); break;
case 'r': remote_host = optarg; break;
case 'p': remote_port = optarg; break;
@@ -74,6 +78,11 @@ while ((opt = getopt(argc, argv, "hp:r:vj:o:I:")) != -1) {
}
}
if (do_dump) {
fprintf(stderr, "dumping data from '%s'\n", joy_device);
dump_my_joystick(joy_device);
}
if (verbosity) {
fprintf(stderr, " %s is sending to %s:%s\n", argv[0],
remote_host, remote_port);
@@ -81,9 +90,12 @@ if (verbosity) {
}
lo_address t = lo_address_new(remote_host, remote_port);
/*
* XXX no error check ? wtf ?
*/
if( ( joy_fd = open(joy_device , O_RDONLY)) == -1 ) {
fprintf(stderr, "Couldn't open %s\n", JOY_DEVICE);
fprintf(stderr, "%s: Couldn't open %s\n", argv[0], joy_device);
exit(1);
}
@@ -95,14 +107,13 @@ if (verbosity) {
send_data_id(t, my_id);
x_pos = y_pos = 0;
x_pos = y_pos = z_pos = w_pos = 0;
for (;;) {
foo = read(joy_fd, &js, sizeof(struct js_event));
if (8 != foo) {
fprintf(stderr, "err reading joy\n");
exit(1);
}
/* calibration datas ignored */
if (js.type > 128) continue;
@@ -110,24 +121,37 @@ for (;;) {
fprintf(stderr, "%10u %2d %2d %7d\n",
js.time, js.type, js.number, js.value);
}
if (2==js.type) { /* oscillating stick */
flag = 0;
switch (js.number)
{
what = 0;
switch (js.number) {
case 0:
x_pos = js.value;
flag = 1;
what = 1;
break;
case 1:
y_pos = js.value;
flag = 1;
what = 1;
break;
case 2:
z_pos = js.value;
what = 2;
break;
case 3:
w_pos = js.value;
what = 2;
break;
}
if (flag) {
/* now, send the datas */
// fprintf(stderr, "\t\twhat = %d\n", what);
switch (what) {
case 1:
foo = send_data_xy(t, x_pos, y_pos);
flag = 0;
what = 0;
break;
case 2:
foo = send_data_zw(t, z_pos, w_pos);
what = 0;
break;
}
}
@@ -135,7 +159,6 @@ for (;;) {
foo = send_data_button(t, js.number+button_offset,
js.value);
}
}
return 0;

View File

@@ -46,6 +46,8 @@ printf(stderr, "%s : %s %s %d\n", __func__, path, types, argc);
if (verbosity) {
sprintf(ligne, "%s %s %s %d\n", __func__, path, types, argc);
mvaddstr(2, 2, ligne);
sprintf(ligne, "button : %6d %6d", argv[0]->i, argv[1]->i);
mvaddstr(3, 2, ligne);
refresh();
}
@@ -54,6 +56,8 @@ if (-1 == erase_button) return 0;
if ( (argv[0]->i == erase_button) &&
(argv[1]->i == 0) ) {
must_erase = 1;
mvaddstr(3, 2, "KILL ! KILL !");
refresh();
}
return 0;
@@ -116,7 +120,7 @@ if (verbosity) {
}
/* erase the old spot */
if (old_l) mvaddch(old_l, old_c, current_char);
if (old_l || old_c) mvaddch(old_l, old_c, current_char);
standout();
mvaddch(cur_l, cur_c, '#');
@@ -169,9 +173,9 @@ fprintf(stderr, "erase %d\n", erase_button);
st = lo_server_thread_new(local_port, error);
foo = initcurses();
sprintf(ligne, ":%s ", local_port);
sprintf(ligne, ":%s e=%d ", local_port, erase_button);
foo = draw_main_screen(ligne, 0);
if (verbosity) fprintf(stderr, "dms %d\n", foo);
// if (verbosity) fprintf(stderr, "dms %d\n", foo);
lo_server_thread_add_method(st, "/joystick/xy", "ii", xy_handler, NULL);
lo_server_thread_add_method(st, "/joystick/b", "ii", button_handler, NULL);

340
showbuttons.c Normal file
View File

@@ -0,0 +1,340 @@
/*
* 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;
}
/* ----------------------------------------------------------------- */

28
specific/Makefile Normal file
View File

@@ -0,0 +1,28 @@
OPTS = -Wall -g -DDEBUG_LEVEL=0
all: joy2laser asyncburp
# --------------------------------------------
laserblast.o: laserblast.c Makefile
gcc -c ${OPTS} $<
joy2laser: joy2laser.c Makefile laserblast.o
gcc ${OPTS} $< laserblast.o ../functions/libpocosc.a -llo -o $@
# --------------------------------------------
asyncburp.o: asyncburp.c burpmsg.h laserblast.h Makefile
gcc -c ${OPTS} $<
burpmsg.o: burpmsg.c burpmsg.h Makefile
gcc -c ${OPTS} $<
asyncburp: asyncburp.o burpmsg.o laserblast.o
gcc ${OPTS} $< laserblast.o burpmsg.o -llo -o $@
# --------------------------------------------

38
specific/README.md Normal file
View File

@@ -0,0 +1,38 @@
# Du joystick au laser
## joy2laser
Kluge intuité pendant [Sonoptic 2020](http://sonoptic.net/).
```
tth@debian:~/Devel/gadgets-OSC/specific$ ./joy2laser -h
HELP ME !
-p NNN local listening port
-R a.b.c.d remote host
-P NNN remote port
-L N laser number
-S N scene number
-v increase verbosity
```
En réception, c'est fait pour fonctionner avec des choses comme
[osc-joy](../osc-joy.c) ou un [générateur](../generators/) de sinusoïde.
Le [protocole](../functions/senders.c) utilisé est simple
(parfois un peu trop) mais fonctionne bien.
En émission, ça tente de se conformer au
[protocole](https://git.interhacker.space/teamlaser/LJ/src/branch/master/README.md#lj-commands-reference)
défini par la teamlaser. Hélas, le soft de Sam n'étant pas très stable, ce logiciel.
n'a pas été vraiment testé sur le système réel.
```
<tth> vos lasers, la déviation elle se fait à quelle fréquence maxi ?
<sammmm> plop
<sammmm> voila une reponse si j'ai bien compris la question.
<sammmm> Le plus rapide de nos lasers peut tracer 30 000 pts /sec avec un angle max de 8°
<sammmm> Apres si tu traces que 2 points plus proches que 8° le nombre d'oscillations va etre plus elevé evidement puisqu'il faudra moins de tps pour aller au pts suivant puisqu'il est plus pres.
<sammmm> en resumé la frequence maxi est inversement proportionnelle a la deviation.
<sammmm> plus tu devies plus ca va etre long a tracer donc plus la frequence baisse.
```

135
specific/asyncburp.c Normal file
View File

@@ -0,0 +1,135 @@
/*
* Joystick to Laser
* async version, with continuous refresh
* post Sonoptic 2020
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <lo/lo.h> /* OSC library */
#include "laserblast.h"
#include "burpmsg.h"
/* ------------------------------------------------------------------- */
#define LOCAL_PORT "9000"
#define REMOTE_HOST "localhost" /* just loling */
#define REMOTE_PORT "9999"
/* ------------------------------------------------------------------- */
int verbosity; /* global variable */
/* ------------------------------------------------------------------- */
/* ------------------------------------------------------------------- */
int init_osc_receiver(char *port, int notused)
{
#if DEBUG_LEVEL
fprintf(stderr, ">>> %s ( '%s' %d )\n", __func__, port, notused);
#endif
return -1;
}
/* ------------------------------------------------------------------- */
int init_osc_sender(char *r_host, char *r_port, int notused)
{
int foo;
#if DEBUG_LEVEL
fprintf(stderr, ">>> %s ( '%s' '%s' %d )\n", __func__,
r_host, r_port, notused);
#endif
foo = blast_init(r_host, r_port, 0, 0);
if (foo) {
fprintf(stderr, "blast_init return %d\n", foo);
return -2;
}
if (verbosity) blast_NOP(getpid());
return 0;
}
/* ------------------------------------------------------------------- */
/*
* this is a tool function for debugging, do not use in real life
*/
static int tentative(void)
{
int foo;
blast_rewind();
blast_addpoint(200, 200, 0xff0000);
blast_addpoint(300, 300, 0xff0000);
blast_flush(0);
return 42;
}
/* ------------------------------------------------------------------- */
static int help(int krkrkr)
{
puts("HELP ME !");
puts("\t-p NNN\t\tlocal listening port");
puts("\t-R a.b.c.d\tremote host");
puts("\t-P NNN\t\tremote port");
puts("\t-L N\t\tlaser number");
puts("\t-S N\t\tscene number");
puts("\t-v\t\tincrease verbosity");
return 1;
}
/* ------------------------------------------------------------------- */
int main(int argc, char *argv[])
{
char *local_port = LOCAL_PORT;
char *remote_host = REMOTE_HOST;
char *remote_port = REMOTE_PORT;
int lasernumber, scenenumber;
int opt, foo;
fprintf(stderr, "%s compiled %s at %s\n",argv[0], __DATE__, __TIME__);
/* set some default values */
lasernumber = scenenumber = 0;
/* parsing command line options */
while ((opt = getopt(argc, argv, "hp:vL:S:R:P:")) != -1) {
switch (opt) {
case 'h': if (help(0)) exit(1); break;
case 'p': local_port = optarg; break;
case 'R': remote_host = optarg; break;
case 'P': remote_port = optarg; break;
case 'L': lasernumber = atoi(optarg); break;
case 'S': scenenumber = atoi(optarg); break;
case 'v': verbosity++; break;
}
}
if (verbosity) {
fprintf(stderr, "-------------: %s\n", argv[0]);
fprintf(stderr, "pid : %d\n", getpid());
fprintf(stderr, "local port : %s\n", local_port);
fprintf(stderr, "remote : %s %s\n", remote_host, remote_port);
fprintf(stderr, "scn/laser : %d %d\n", scenenumber, lasernumber);
}
foo = init_osc_sender(remote_host, remote_port, 0);
fprintf(stderr, "init osc sender -> %d\n", foo);
tentative();
return 2;
}
/* ------------------------------------------------------------------- */

101
specific/burpmsg.c Normal file
View File

@@ -0,0 +1,101 @@
/*
* BURPMSG.C
*/
#include <stdio.h>
#include <stdint.h>
#include <sys/select.h>
#include <unistd.h>
#include "laserblast.h"
#include "burpmsg.h"
/* ------------------------------------------------------------------- */
int display_burp_msg(BurpMsg *header, void *data)
{
char *txt_type;
if (BURP_MAGIC != header->magic) {
fprintf(stderr, "burpmsg at %p : invalid magic %08X\n",
header, header->magic);
return -1;
}
txt_type = "wtf?"; /* nice default value */
switch(header->msgtype) {
case BURP_RESET:
txt_type = "reset";
break;
case BURP_SETSIZE:
txt_type = "setsize";
break;
case BURP_LASER:
txt_type = "laser";
break;
case BURP_SCENE:
txt_type = "scene";
break;
case BURP_TEXTE:
txt_type = "texte";
break;
default:
fprintf(stderr, "burpmsg at %p : invalid msgtype %d\n",
header, header->msgtype);
return -1;
}
fprintf(stderr, "type %4d/%-8s serial %9d szdata %3d\n",
header->msgtype, txt_type, header->serial, header->szdata);
return 0;
}
/* ------------------------------------------------------------------- */
void la_grande_boucle( int fromfifo )
{
struct timeval tv;
fd_set fds;
int resval, foo;
BurpMsg message;
for(;;) { /* start of infinite loop */
FD_ZERO(&fds);
FD_SET(fromfifo, &fds);
tv.tv_sec = 1;
tv.tv_usec = 0;
resval = select(1, &fds, NULL, NULL, &tv);
if (-1 == resval) {
perror("select()");
/* ABORTING HERE ? */
continue;
}
if (resval) {
/* message available */
foo = read(fromfifo, &message, sizeof(BurpMsg));
if (sizeof(BurpMsg) != foo) {
fprintf(stderr, "err: %d read, %lu expected\n",
foo, sizeof(BurpMsg));
}
display_burp_msg(&message, NULL);
/* read appended datas */
}
else {
/* got a time out */
fprintf(stderr, "TIMEOUT\n");
}
}
/* NOT REACHED */
}
/* ------------------------------------------------------------------- */

31
specific/burpmsg.h Normal file
View File

@@ -0,0 +1,31 @@
/*
* BURPMSG.H
*/
/* ------------------------------------------------------------------- */
typedef struct {
uint32_t magic;
uint32_t serial;
uint16_t msgtype;
uint16_t szdata;
} BurpMsg;
#define BURP_MAGIC 0x98769876
/* message type */
#define BURP_RESET 1
#define BURP_SETSIZE 2
#define BURP_LASER 3
#define BURP_SCENE 4
#define BURP_COLOR 5
#define BURP_TEXTE 6
/* ------------------------------------------------------------------- */
int display_burp_msg(BurpMsg *header, void *data);
/* ------------------------------------------------------------------- */

18
specific/fedora.txt Normal file
View File

@@ -0,0 +1,18 @@
---------- Compiler le bouzin
[root@laserbox ~]# dnf install alsa-lib-devel
Installed:
alsa-lib-devel-1.2.4-5.fc33.x86_64
---------- Comprendre pourquoi ça marche pas
tth@debian:~/Devel/gadgets-OSC$ oscsend 10.20.0.23 9000 '/fuck' i 1337
[tth@laserbox gadgets-OSC]$ oscdump 9000
... rien ...
Donc, voilà, il y a un blocage UDP en entrée de la Fedora /o\

145
specific/joy2laser.c Normal file
View File

@@ -0,0 +1,145 @@
/*
* Joystick to Laser
*
* Sonoptic 2020
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <getopt.h>
#include <time.h>
#include <lo/lo.h> /* OSC library */
#include "laserblast.h"
/* ------------------------------------------------------------------- */
#define LOCAL_PORT "9000"
#define REMOTE_HOST "localhost" /* just loling */
#define REMOTE_PORT "9999"
int verbosity = 0;
int scenenumber = 1,
lasernumber = 1;
/* ------------------------------------------------------------------- */
int draw_this_point(int x, int y)
{
float fx, fy;
fx = (32768.0 + (float)x) / 94.7;
fy = (32768.0 + (float)y) / 94.7;
#define SZ 10.0
blast_rewind();
blast_addpoint(fx-SZ, fy-SZ, 0xffffff);
blast_addpoint(fx-SZ, fy+SZ, 0xffffff);
blast_addpoint(fx+SZ, fy+SZ, 0xffffff);
blast_addpoint(fx+SZ, fy-SZ, 0xffffff);
blast_addpoint(fx-SZ, fy-SZ, 0);
blast_flush(0);
return 0;
}
/* ------------------------------------------------------------------- */
int xy_handler(const char *path, const char *types, lo_arg ** argv,
int argc, void *data, void *user_data)
{
int val_x, val_y;
int foo;
#if DEBUG_LEVEL
fprintf(stderr, ">>> %s ( %s %s %d )\n", __func__, path, types, argc);
#endif
val_x = argv[0]->i; val_y = argv[1]->i;
if (verbosity) fprintf(stderr, "%6d %6d\n", val_x, val_y);
foo = draw_this_point(val_x, val_y);
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 help(int k)
{
puts("HELP ME !");
puts("\t-p NNN\t\tlocal listening port");
puts("\t-R a.b.c.d\tremote host");
puts("\t-P NNN\t\tremote port");
puts("\t-L N\t\tlaser number");
puts("\t-S N\t\tscene number");
puts("\t-v\t\tincrease verbosity");
return 1;
}
/* ------------------------------------------------------------------- */
int main(int argc, char *argv[])
{
char *local_port = LOCAL_PORT;
char *remote_host = REMOTE_HOST;
char *remote_port = REMOTE_PORT;
int opt, foo;
lo_server_thread st;
long starttime;
fprintf(stderr, "%s compiled %s at %s\n",argv[0], __DATE__, __TIME__);
/* parsing command line options */
while ((opt = getopt(argc, argv, "hp:vL:S:R:P:")) != -1) {
switch (opt) {
case 'h': if (help(0)) exit(1); break;
case 'p': local_port = optarg; break;
case 'R': remote_host = optarg; break;
case 'P': remote_port = optarg; break;
case 'L': lasernumber = atoi(optarg); break;
case 'S': scenenumber = atoi(optarg); break;
case 'v': verbosity++; break;
}
}
if (verbosity) {
fprintf(stderr, "-----------: %s\n", argv[0]);
fprintf(stderr, "pid : %d\n", getpid());
fprintf(stderr, "local port : %s\n", local_port);
fprintf(stderr, "scene : %d\n", scenenumber);
fprintf(stderr, "laser : %d\n", lasernumber);
fprintf(stderr, "remote : %s %s\n", remote_host, remote_port);
}
foo = blast_init(remote_host, remote_port, scenenumber, lasernumber);
if (foo) {
fprintf(stderr, "blast init error : %d\n", foo);
exit(1);
}
st = lo_server_thread_new(local_port, error);
lo_server_thread_add_method(st, "/joystick/xy", "ii", xy_handler, NULL);
lo_server_thread_start(st);
starttime = time(NULL) / 60;
for (;;) {
if (verbosity)
fprintf(stderr, "\tt = %ld min.\n",
(time(NULL)/60L) - starttime);
sleep(60);
}
return 8;
}
/* ------------------------------------------------------------------- */

143
specific/laserblast.c Normal file
View File

@@ -0,0 +1,143 @@
/*
* laserblsat over OSC
*
* Sonoptic 2020
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <lo/lo.h> /* OSC library */
/* ------------------------------------------------------------------- */
#define BUFF_SIZE 8000
static char big_buffer[BUFF_SIZE+2];
static int curpos;
static int la_scene, le_laser;
static lo_address lo_addr;
static int x_scale, y_scale;
extern int verbosity;
/* ------------------------------------------------------------------- */
/*
* - prepare OSC transmission
*/
int blast_init(char *host, char *port, int scene, int laser)
{
#if DEBUG_LEVEL
fprintf(stderr, ">>> %s ( '%s:%p' %d %d )\n", __func__, host, port,
scene, laser);
#endif
lo_addr = lo_address_new(host, port);
if (verbosity) {
fprintf(stderr, "%s is sending to %s:%s\n", __FILE__, host, port);
}
la_scene = scene, le_laser = laser;
x_scale = y_scale = 700;
/* manage our internals memories */
big_buffer[0] = '\0'; /* clear buffer */
curpos = 0; /* index in buffer */
return 0;
}
/* ------------------------------------------------------------------- */
/*
* this function is for test purpose, don't use in the
* real world, Just don't, OK?
*/
int blast_NOP(int reason)
{
int foo;
char msg[50];
fprintf(stderr, "===== BLAST NOP %d\n", reason);
sprintf(msg, "BLAST NOP %d", reason);
foo = lo_send(lo_addr, "/dev/null", "s", msg);
if (-1==foo) {
fprintf(stderr, "%s : error %d\n", __func__, foo);
return -1;
}
return 0;
}
/* ------------------------------------------------------------------- */
int blast_setscale(int width, int height)
{
#if DEBUG_LEVEL
fprintf(stderr, ">>> %s ( %d %d )\n", __func__, width, height);
#endif
/* no validity check ? */
x_scale = width;
y_scale = height;
return -1;
}
/* ------------------------------------------------------------------- */
int blast_rewind(void)
{
if (verbosity > 1) fprintf(stderr, "Blast rewind\n");
big_buffer[0] = '\0'; /* clear buffer */
curpos = 0; /* index in buffer */
strcat(big_buffer, "["); curpos++;
return -1;
}
/* ------------------------------------------------------------------- */
int blast_addpoint(float x, float y, long col)
{
char buff[100];
int sz;
sz = sprintf(buff, "(%.2f, %.2f, %ld),", x, y, col);
if (verbosity > 1) fprintf(stderr, "%s --> %s\n", __func__, buff);
/* check free space in bigbuffer */
if ( (curpos+sz) > BUFF_SIZE ) {
fprintf(stderr, "buffer overflow in %s\n", __func__);
exit(1);
}
strcat(big_buffer, buff); curpos += sz;
return -1;
}
/* ------------------------------------------------------------------- */
int blast_flush(void)
{
int foo;
char buffer[100];
/* we have to kill the last ',' in the big buff before send */
big_buffer[curpos-1] = ']'; big_buffer[curpos] = '\0';
if (verbosity) fprintf(stderr, "BLAST %s\n", big_buffer);
sprintf(buffer, "/pl/%d/%d", la_scene, le_laser);
foo = lo_send(lo_addr, buffer, "s", big_buffer);
if (-1==foo) {
fprintf(stderr, "%s : error %d\n", __func__, foo);
return -1;
}
return 0;
}
/* ------------------------------------------------------------------- */
/* ------------------------------------------------------------------- */
/* ------------------------------------------------------------------- */

14
specific/laserblast.h Normal file
View File

@@ -0,0 +1,14 @@
/*
* laserblast.h
*
* sonoptic 2020
*/
int blast_init(char *host, char *port, int scene, int laser);
int blast_rewind(void);
int blast_setscale(int width, int height);
int blast_addpoint(float fx, float fy, long col);
int blast_flush(int notused);
int blast_NOP(int reason);

162
text2osc.c Normal file
View File

@@ -0,0 +1,162 @@
/*
* WARNING, THIS IS JUST A WIP !
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <lo/lo.h>
#include "functions/senders.h"
#define REMOTE_HOST "localhost" /* just loling */
#define REMOTE_PORT "9000"
#define MY_TEXT_ID "<@TROLL>"
/* ----------------------------------------------------------------- */
int verbosity = 0;
char *my_id = MY_TEXT_ID;
int wait_time = 80; /* in milliseconds */
/* ----------------------------------------------------------------- */
int megaloop(FILE *fp, lo_address loa)
{
int caractere, note;
short x_val, y_val;
int must_send_xy;
int char_count;
x_val = y_val = 0;
must_send_xy = 1;
char_count = 0;
rewind(fp); /* so we can run this code again and again
on the same fopened file */
while (EOF != (caractere=getc(fp))) {
char_count++;
if (verbosity) fprintf(stderr, "char = %4d %c\n",
caractere, caractere);
if (isalpha(caractere)) {
/* Play a sound */
note=toupper(caractere) - 'A';
// fprintf(stderr, "%c -> %3d\n", caractere, note);
send_data_button(loa, note, 1);
usleep(wait_time*1000);
send_data_button(loa, note, 0);
usleep(40*1000);
}
else if (isdigit(caractere)) {
note = caractere - '0';
send_data_button(loa, note, 1);
usleep(wait_time*1000);
send_data_button(loa, note, 0);
usleep(20*1000);
}
else if (isblank(caractere)) {
usleep(200*1000);
}
else if (caractere == '!') {
send_data_id(loa, my_id);
}
/* imagine : we are a XY joystick */
else if (caractere == '+') {
x_val++;
if (x_val > 32000) x_val = 0;
must_send_xy = 1;
}
else if (caractere == '-') {
x_val--;
if (x_val < -32000) x_val = 0;
must_send_xy = 1;
}
else if (caractere == '^') {
y_val++;
if (y_val > 32000) y_val = 0;
must_send_xy = 1;
}
else if (caractere == '$') {
y_val--;
if (y_val < -32000) y_val = 0;
must_send_xy = 1;
}
/* default case */
else {
usleep(wait_time*1000);
}
if (must_send_xy) {
fprintf(stderr, "... X %6d Y %6d\n",
x_val, y_val);
send_data_xy(loa, x_val, y_val);
must_send_xy = 0;
}
}
return 0;
}
/* ----------------------------------------------------------------- */
static void help(int k)
{
puts("\t * text -> osc "__DATE__" *");
puts("\t-r\tremote host ("REMOTE_HOST")");
puts("\t-p\tremote UDP port ("REMOTE_PORT")");
puts("\t-v\tincrease verbosity");
puts("\t-w\twait time unit in ms.");
puts("\t-I\tchange text id (\""MY_TEXT_ID"\")");
exit(0);
}
/* ----------------------------------------------------------------- */
int main(int argc, char *argv[])
{
int opt;
char *remote_host = REMOTE_HOST;
char *remote_port = REMOTE_PORT;
lo_address loaddr;
FILE *fp;
/* parsing command line options */
while ((opt = getopt(argc, argv, "hp:r:vw:I:")) != -1) {
switch (opt) {
case 'h': help(0); break;
case 'r': remote_host = optarg; break;
case 'p': remote_port = optarg; break;
case 'v': verbosity++; break;
case 'w': wait_time=atoi(optarg); break;
case 'I': my_id = optarg; break;
default: exit(1);
}
}
if (optind >= argc) {
fprintf(stderr, "Expected a filename after options\n");
exit(EXIT_FAILURE);
}
loaddr = lo_address_new(remote_host, remote_port);
if (verbosity) {
fprintf(stderr, "%s (%s) is sending to %s:%s\n",
argv[0], my_id, remote_host, remote_port);
}
if (NULL==(fp=fopen(argv[optind], "r"))) {
perror (argv[optind]);
exit(1);
}
if (verbosity) fprintf(stderr, "now playing %s\n", argv[optind]);
megaloop(fp, loaddr);
return 0;
}
/* ----------------------------------------------------------------- */

11
tools/Makefile Normal file
View File

@@ -0,0 +1,11 @@
#
# Various OSC (and UDP) tools
#
# https://git.tetalab.org/tTh/gadgets-OSC
udp-dumper: udp-dumper.c Makefile
gcc -Wall $< -o $@
wait-for-joystick: wait-for-joystick.c Makefile
gcc -Wall $< -o $@

11
tools/README.md Normal file
View File

@@ -0,0 +1,11 @@
# Various OSC tools
## relay.py
Quick hack build with a disgusting language.
## udp-dumper
This is not really an OSC dedicated tools, but a general purpose one.

2
tools/destinations.liste Normal file
View File

@@ -0,0 +1,2 @@
localhost:9001
localhost:9002

60
tools/relay.py Executable file
View File

@@ -0,0 +1,60 @@
#!/usr/bin/python3
import socket, sys, getopt
# --- default values
RX_UDP_IP = "" # pour ecouter sur toutes les interfaces
RX_UDP_PORT = 5005 # entree du relais
# ---
rx_port = RX_UDP_PORT
verbose = 0
# --- parse command line arguments
options = "hvp:c:"
arguments = sys.argv[1:]
opts, args = getopt.getopt(arguments, options)
for o, a in opts:
print (' ', o, ' --> ', a)
if "-v" == o: verbose += 1
elif "-p" == o: rx_port = int(a)
print ("listening port : ", rx_port)
# ---
cibles = [ ];
for ligne in open("destinations.liste"):
a, p = ligne.replace('\n', '').split(":")
# print a, p
if p: cibles.append((a, int(p)))
for cible in cibles:
print (" -> ", cible)
# point d'entree, d'ecoute
sock_rx = socket.socket(socket.AF_INET, # Internet
socket.SOCK_DGRAM) # UDP
sock_rx.bind((RX_UDP_IP, rx_port))
# point de sortie vers les autres
sock_tx = socket.socket(socket.AF_INET, # Internet
socket.SOCK_DGRAM) # UDP
while True:
data, addr = sock_rx.recvfrom(1024) # buffer size is 1024 bytes
if verbose:
print ("got:", addr, " ", len(data))
for cible in cibles:
# print cible
sock_tx.sendto(data, cible)
# hop, ce truc doit fonctionner !

127
tools/udp-dumper.c Normal file
View File

@@ -0,0 +1,127 @@
/*
* general purpose UDP dumper
*
* made by tTh, around 2019...
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#define PORT 5002
#define BUFLEN 1024
int verbosity = 0;
/* ----------------------------------------------------------------- */
int dumpln(unsigned char *ptr)
{
int foo;
for (foo=0; foo<16; foo++)
printf("%02x ", ptr[foo]);
printf("| ");
for (foo=0; foo<16; foo++)
if (isprint(ptr[foo])) putchar(ptr[foo]);
else putchar('.');
printf(" |\n");
return 0;
}
/* ----------------------------------------------------------------- */
void udp_dumper(uint16_t port)
{
unsigned char buffer[BUFLEN];
struct sockaddr_in si_me, si_other;
int sock, foo, bar, flag_exit;
unsigned int slen=sizeof(si_other);
long serial;
double starttime, curtime;
struct timeval tp;
fprintf(stderr, "%s: listen on port %d\n", __func__, port);
if (-1==(sock=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))) {
perror("socket fail ");
exit(1);
}
#if DEBUG_LEVEL
fprintf(stderr, "port %d / sock -> %d\n", port, sock);
#endif
memset((char *) &si_me, 0, sizeof(si_me));
si_me.sin_family = AF_INET;
si_me.sin_port = htons(port);
si_me.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sock, (struct sockaddr *)&si_me, sizeof(si_me))==-1) {
perror("'bind' failure ");
exit(1);
}
flag_exit = 0; serial = 0L;
gettimeofday(&tp, NULL);
starttime = tp.tv_sec + tp.tv_usec / 1e6;
do {
memset(buffer, 0, BUFLEN);
slen = sizeof(si_other);
foo = recvfrom(sock, buffer, BUFLEN, 0,
(struct sockaddr *)&si_other, &slen);
if (verbosity) {
gettimeofday(&tp, NULL);
curtime = tp.tv_sec + tp.tv_usec / 1e6;
printf("----+ frame %4ld %5d bytes t= %.3f sec.\n",
serial, foo, curtime - starttime);
/*
* MUST display ip:port of the sender !
*/
}
for (bar=0; bar<=foo; bar+=16) {
printf("%3d | ", bar);
dumpln(buffer+bar);
}
serial++;
} while ( !flag_exit);
}
/* ----------------------------------------------------------------- */
void help(int foo)
{
puts("\t-h\tthis help text");
puts("\t-p NNNN\treceiving port number");
puts("\t-v\tincrease verbosity");
exit(0);
return ;
}
/* ----------------------------------------------------------------- */
int main(int argc, char *argv[])
{
int opt, port;
port = PORT;
/* parsing command line options */
while ((opt = getopt(argc, argv, "hp:v")) != -1) {
switch (opt) {
case 'h': help(0); break;
case 'p': port = atoi(optarg); break;
case 'v': verbosity++; break;
default: exit(1);
}
}
udp_dumper(port);
return 0;
}
/* ----------------------------------------------------------------- */

44
tools/wait-for-joystick.c Normal file
View File

@@ -0,0 +1,44 @@
/*
* wait for joystick event
* -----------------------
*
# https://git.tetalab.org/tTh/gadgets-OSC
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int verbosity = 0;
/* ----------------------------------------------------------------- */
/* ----------------------------------------------------------------- */
void help(int k)
{
puts("XXX");
exit(0);
}
/* ----------------------------------------------------------------- */
int main(int argc, char *argv[])
{
int foo, opt;
char *device = "/dev/input/js0";
/* parsing command line options */
while ((opt = getopt(argc, argv, "d:hv")) != -1) {
switch (opt) {
case 'd': device = optarg; break;
case 'h': help(0); break;
case 'v': verbosity++; break;
default: exit(1);
}
}
if (verbosity) {
fprintf(stderr, "%s on %s\n", argv[0], device);
}
return 0;
}
/* ----------------------------------------------------------------- */