cava with pipe, and template
This commit is contained in:
parent
7117cbbe4c
commit
6add75c64e
@ -12,7 +12,7 @@ source = plughw:1
|
|||||||
method = raw
|
method = raw
|
||||||
channels = mono
|
channels = mono
|
||||||
mono_option = left
|
mono_option = left
|
||||||
raw_target = /tmp/cava_output
|
;raw_target = /dev/stdout
|
||||||
data_format = ascii
|
data_format = ascii
|
||||||
ascii_max_range=65535
|
ascii_max_range=65535
|
||||||
bit_format = 16bit
|
bit_format = 16bit
|
||||||
|
25
RpiLedBars/cava_config_namedpipe
Normal file
25
RpiLedBars/cava_config_namedpipe
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
[general]
|
||||||
|
framerate = 60
|
||||||
|
autosens = 0
|
||||||
|
sensitivity = 200
|
||||||
|
bars = 128
|
||||||
|
|
||||||
|
[input]
|
||||||
|
method = alsa
|
||||||
|
source = plughw:1
|
||||||
|
|
||||||
|
[output]
|
||||||
|
method = raw
|
||||||
|
channels = mono
|
||||||
|
mono_option = left
|
||||||
|
raw_target = /tmp/cava_output
|
||||||
|
data_format = ascii
|
||||||
|
ascii_max_range=65535
|
||||||
|
bit_format = 16bit
|
||||||
|
|
||||||
|
[smoothing]
|
||||||
|
integral = 0
|
||||||
|
monstercat = 1
|
||||||
|
waves = 0
|
||||||
|
gravity = 0
|
||||||
|
|
@ -1,5 +1,6 @@
|
|||||||
#include "rpi_gpio.h"
|
#include "rpi_gpio.h"
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@ -17,6 +18,8 @@
|
|||||||
|
|
||||||
#define GPIO_MODE_STRS "IN", "OUT", "ALT5", "ALT4", "ALT0", "ALT1", "ALT2", "ALT3"
|
#define GPIO_MODE_STRS "IN", "OUT", "ALT5", "ALT4", "ALT0", "ALT1", "ALT2", "ALT3"
|
||||||
|
|
||||||
|
bool isInitialized = false;
|
||||||
|
|
||||||
// Virtual memory pointers to acceess GPIO, DMA and PWM from user space
|
// Virtual memory pointers to acceess GPIO, DMA and PWM from user space
|
||||||
MEM_MAP gpio_regs;
|
MEM_MAP gpio_regs;
|
||||||
|
|
||||||
@ -24,9 +27,19 @@ char *gpio_mode_strs[] = {GPIO_MODE_STRS};
|
|||||||
|
|
||||||
// definitions
|
// definitions
|
||||||
|
|
||||||
void gpio_setup() { map_periph(&gpio_regs, (void *)GPIO_BASE, PAGE_SIZE); }
|
void gpio_setup() {
|
||||||
|
if (!isInitialized) {
|
||||||
|
map_periph(&gpio_regs, (void *)GPIO_BASE, PAGE_SIZE);
|
||||||
|
isInitialized = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void gpio_close() { unmap_periph_mem(&gpio_regs); }
|
void gpio_close() {
|
||||||
|
if (isInitialized) {
|
||||||
|
unmap_periph_mem(&gpio_regs);
|
||||||
|
isInitialized = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Set input or output with pullups
|
// Set input or output with pullups
|
||||||
void gpio_set(int pin, int mode, int pull) {
|
void gpio_set(int pin, int mode, int pull) {
|
||||||
|
@ -1,11 +1,37 @@
|
|||||||
|
/** \file rpi_selector.c
|
||||||
|
* \brief This module is used to manage selector on gpio
|
||||||
|
*/
|
||||||
|
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Includes
|
||||||
|
**************************************************************************************************/
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <wiringPi.h>
|
#include <wiringPi.h>
|
||||||
|
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Preprocessor Constants and Macros
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Type and Contant Definitions
|
||||||
|
**************************************************************************************************/
|
||||||
unsigned const selectorPinNumber = 4;
|
unsigned const selectorPinNumber = 4;
|
||||||
|
/* TODO use GPIO function from ../gpio/gipo.h (same pin number) */
|
||||||
int selectorPins[4] = {5, 6, 26, 27};
|
int selectorPins[4] = {5, 6, 26, 27};
|
||||||
|
|
||||||
void setup_selector() {
|
/***************************************************************************************************
|
||||||
|
* Persistent Variables
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Internal Function Prototypes
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************************************
|
||||||
|
* External Function Definitions
|
||||||
|
**************************************************************************************************/
|
||||||
|
void selector_setup() {
|
||||||
wiringPiSetupGpio();
|
wiringPiSetupGpio();
|
||||||
|
|
||||||
for (size_t i = 0; i < selectorPinNumber; ++i) {
|
for (size_t i = 0; i < selectorPinNumber; ++i) {
|
||||||
@ -14,7 +40,7 @@ void setup_selector() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int get_selector_position() {
|
int selector_get_position() {
|
||||||
for (size_t i = 0; i < selectorPinNumber; ++i) {
|
for (size_t i = 0; i < selectorPinNumber; ++i) {
|
||||||
if (digitalRead(selectorPins[i])) {
|
if (digitalRead(selectorPins[i])) {
|
||||||
return i;
|
return i;
|
||||||
@ -23,10 +49,14 @@ int get_selector_position() {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_selector() {
|
void selector_print() {
|
||||||
char modeStr[] = "0 | 0 | 0 | 0 \n";
|
char modeStr[] = "0 | 0 | 0 | 0 \n";
|
||||||
for (size_t i = 0; i < selectorPinNumber; ++i) {
|
for (size_t i = 0; i < selectorPinNumber; ++i) {
|
||||||
modeStr[i * 4] = digitalRead(selectorPins[i]) ? '1' : '0';
|
modeStr[i * 4] = digitalRead(selectorPins[i]) ? '1' : '0';
|
||||||
}
|
}
|
||||||
printf(modeStr);
|
fprintf(stderr, modeStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Internal Function Definitions
|
||||||
|
**************************************************************************************************/
|
@ -1,10 +1,40 @@
|
|||||||
|
/** \file rpi_selector.h
|
||||||
|
* \brief This module is used to manage selector on gpio
|
||||||
|
*/
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Includes
|
||||||
|
**************************************************************************************************/
|
||||||
#if !defined(__RPI_SELECTOR_H__)
|
#if !defined(__RPI_SELECTOR_H__)
|
||||||
#define __RPI_SELECTOR_H__
|
#define __RPI_SELECTOR_H__
|
||||||
|
|
||||||
void setup_selector();
|
/***************************************************************************************************
|
||||||
|
* Preprocessor Constants and Macros
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
int get_selector_position();
|
/***************************************************************************************************
|
||||||
|
* Type and Contant Definitions
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
void print_selector();
|
/***************************************************************************************************
|
||||||
|
* Global Variables
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************************************
|
||||||
|
* External Function Prototypes
|
||||||
|
**************************************************************************************************/
|
||||||
|
/**
|
||||||
|
* \brief setup the selector module
|
||||||
|
**/
|
||||||
|
void selector_setup();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief get the selector position
|
||||||
|
**/
|
||||||
|
int selector_get_position();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief debug: print the selector position
|
||||||
|
**/
|
||||||
|
void selector_print();
|
||||||
|
|
||||||
#endif /* __RPI_SELECTOR_H__ */
|
#endif /* __RPI_SELECTOR_H__ */
|
@ -49,18 +49,10 @@ int main(int argc, char const *argv[]) {
|
|||||||
fprintf(stderr, "WARNING: Failed to set stepper thread to real-time priority\n");
|
fprintf(stderr, "WARNING: Failed to set stepper thread to real-time priority\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
setup_selector();
|
midi_controller_setup();
|
||||||
|
selector_setup();
|
||||||
// // setup led
|
|
||||||
// map_devices();
|
|
||||||
// init_smi(LED_NCHANS, SMI_TIMING);
|
|
||||||
// map_uncached_mem(&vc_mem, VC_MEM_SIZE);
|
|
||||||
|
|
||||||
// setup_smi_dma(&vc_mem, TX_BUFF_LEN(chanLedCount), &txdata);
|
|
||||||
|
|
||||||
leddriver_setup();
|
leddriver_setup();
|
||||||
|
|
||||||
setup_midi_controller();
|
|
||||||
artnet_init();
|
artnet_init();
|
||||||
setup_cava();
|
setup_cava();
|
||||||
|
|
||||||
@ -68,8 +60,8 @@ int main(int argc, char const *argv[]) {
|
|||||||
while (1) {
|
while (1) {
|
||||||
struct timespec loopStart;
|
struct timespec loopStart;
|
||||||
clock_gettime(CLOCK_MONOTONIC, &loopStart);
|
clock_gettime(CLOCK_MONOTONIC, &loopStart);
|
||||||
int mode = get_selector_position();
|
int mode = selector_get_position();
|
||||||
execute_midi_controller();
|
midi_controller_execute();
|
||||||
|
|
||||||
if (mode != -1) {
|
if (mode != -1) {
|
||||||
if (mode != previousMode) {
|
if (mode != previousMode) {
|
||||||
@ -79,7 +71,7 @@ int main(int argc, char const *argv[]) {
|
|||||||
/* stop previous bg task */
|
/* stop previous bg task */
|
||||||
switch (previousMode) {
|
switch (previousMode) {
|
||||||
case 1:
|
case 1:
|
||||||
stop_artnet_bg_worker();
|
artnet_stop();
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
stop_cava_bg_worker();
|
stop_cava_bg_worker();
|
||||||
@ -91,7 +83,7 @@ int main(int argc, char const *argv[]) {
|
|||||||
/* start new bg task */
|
/* start new bg task */
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case 1:
|
case 1:
|
||||||
start_artnet_bg_worker();
|
artnet_start();
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
start_cava_bg_worker();
|
start_cava_bg_worker();
|
||||||
|
@ -14,7 +14,7 @@ void handle_system_port_events(snd_seq_event_t *ev);
|
|||||||
|
|
||||||
void handle_in_port_events(snd_seq_event_t *ev);
|
void handle_in_port_events(snd_seq_event_t *ev);
|
||||||
|
|
||||||
void setup_midi_controller() {
|
void midi_controller_setup() {
|
||||||
if (snd_seq_open(&seq_handle, "default", SND_SEQ_OPEN_INPUT, SND_SEQ_NONBLOCK) != 0) {
|
if (snd_seq_open(&seq_handle, "default", SND_SEQ_OPEN_INPUT, SND_SEQ_NONBLOCK) != 0) {
|
||||||
SNDERR("snd_seq_open");
|
SNDERR("snd_seq_open");
|
||||||
}
|
}
|
||||||
@ -45,7 +45,7 @@ void setup_midi_controller() {
|
|||||||
subscribe_midi_controller(controller);
|
subscribe_midi_controller(controller);
|
||||||
}
|
}
|
||||||
|
|
||||||
void execute_midi_controller() {
|
void midi_controller_execute() {
|
||||||
snd_seq_event_t *ev = NULL;
|
snd_seq_event_t *ev = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
while ((ret = snd_seq_event_input(seq_handle, &ev)) > 0) {
|
while ((ret = snd_seq_event_input(seq_handle, &ev)) > 0) {
|
||||||
@ -63,7 +63,7 @@ void execute_midi_controller() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void close_midi_controller() {}
|
void midi_controller_close() {}
|
||||||
|
|
||||||
void subscribe_system_port() {
|
void subscribe_system_port() {
|
||||||
snd_seq_addr_t sender = {.client = 0, .port = SND_SEQ_PORT_SYSTEM_ANNOUNCE};
|
snd_seq_addr_t sender = {.client = 0, .port = SND_SEQ_PORT_SYSTEM_ANNOUNCE};
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
#if !defined(__RPI_MIDI_CONTROLLER_H__)
|
#if !defined(__RPI_MIDI_CONTROLLER_H__)
|
||||||
#define __RPI_MIDI_CONTROLLER_H__
|
#define __RPI_MIDI_CONTROLLER_H__
|
||||||
|
|
||||||
void setup_midi_controller();
|
void midi_controller_setup();
|
||||||
|
|
||||||
void execute_midi_controller();
|
void midi_controller_execute();
|
||||||
|
|
||||||
void close_midi_controller();
|
void midi_controller_close();
|
||||||
|
|
||||||
#endif /* __RPI_MIDI_CONTROLLER_H__ */
|
#endif /* __RPI_MIDI_CONTROLLER_H__ */
|
@ -1,3 +1,12 @@
|
|||||||
|
/** \file rpi_artnet.c
|
||||||
|
* \brief This module contains continuous tasks for artnet node communications.
|
||||||
|
*
|
||||||
|
* This is the implementation file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Includes
|
||||||
|
**************************************************************************************************/
|
||||||
#include "rpi_artnet.h"
|
#include "rpi_artnet.h"
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
@ -13,19 +22,57 @@
|
|||||||
|
|
||||||
#include "rpi_artnet_utils.h"
|
#include "rpi_artnet_utils.h"
|
||||||
|
|
||||||
int udpSocket = -1;
|
/***************************************************************************************************
|
||||||
char buffer[1024];
|
* Preprocessor Constants and Macros
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Type and Contant Definitions
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Persistent Variables
|
||||||
|
**************************************************************************************************/
|
||||||
|
/**
|
||||||
|
* Boolean for interrupting the main thread loop
|
||||||
|
*/
|
||||||
bool isUdpListenerRunning = false;
|
bool isUdpListenerRunning = false;
|
||||||
|
/**
|
||||||
|
* Task thread identifier
|
||||||
|
*/
|
||||||
pthread_t udpListener;
|
pthread_t udpListener;
|
||||||
|
/**
|
||||||
|
* Buffer for storing artnet dmx data received
|
||||||
|
*/
|
||||||
uint8_t artDmxBufferArray[16][512];
|
uint8_t artDmxBufferArray[16][512];
|
||||||
|
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Internal Function Prototypes
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief This function is used to thread main execution function
|
||||||
|
*
|
||||||
|
* \param arg not used.
|
||||||
|
*
|
||||||
|
* \return NULL.
|
||||||
|
*/
|
||||||
static void *artnet_udp_handler(void *arg);
|
static void *artnet_udp_handler(void *arg);
|
||||||
|
|
||||||
void artnet_send_poll_reply(struct sockaddr_in srcAddr);
|
/**
|
||||||
|
* \brief This function is used to send an artnet poll reply packet
|
||||||
|
*
|
||||||
|
* \param[in] fdUdpSocket The UDP socket file descriptor.
|
||||||
|
*
|
||||||
|
* \param[in] senderAddr The adress of poll emiter.
|
||||||
|
*/
|
||||||
|
static void artnet_send_poll_reply(int fdUdpSocket, struct sockaddr_in senderAddr);
|
||||||
|
|
||||||
void artnet_init() {}
|
/***************************************************************************************************
|
||||||
|
* External Function Definitions
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
void start_artnet_bg_worker() {
|
void artnet_start() {
|
||||||
isUdpListenerRunning = true;
|
isUdpListenerRunning = true;
|
||||||
|
|
||||||
if (pthread_create(&udpListener, NULL, artnet_udp_handler, NULL) < 0) {
|
if (pthread_create(&udpListener, NULL, artnet_udp_handler, NULL) < 0) {
|
||||||
@ -33,7 +80,7 @@ void start_artnet_bg_worker() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void stop_artnet_bg_worker() {
|
void artnet_stop() {
|
||||||
isUdpListenerRunning = false;
|
isUdpListenerRunning = false;
|
||||||
|
|
||||||
if (pthread_join(udpListener, NULL) != 0) {
|
if (pthread_join(udpListener, NULL) != 0) {
|
||||||
@ -41,7 +88,7 @@ void stop_artnet_bg_worker() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int artnet_get_dmx_data(unsigned int univerve, uint8_t **dmxData) {
|
int artnet_get_dmx_data(unsigned int univerve, uint8_t *dmxData[]) {
|
||||||
if (univerve > 8) {
|
if (univerve > 8) {
|
||||||
fprintf(stderr, "Universe %d out of bounds %d\n", univerve, 16);
|
fprintf(stderr, "Universe %d out of bounds %d\n", univerve, 16);
|
||||||
*dmxData = NULL;
|
*dmxData = NULL;
|
||||||
@ -51,27 +98,32 @@ int artnet_get_dmx_data(unsigned int univerve, uint8_t **dmxData) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Internal Function Definitions
|
||||||
|
**************************************************************************************************/
|
||||||
static void *artnet_udp_handler(void *arg) {
|
static void *artnet_udp_handler(void *arg) {
|
||||||
struct sockaddr_in serverAddr;
|
int fdUdpSocket = -1;
|
||||||
struct pollfd fds[1];
|
struct pollfd pollFdArray[1];
|
||||||
int timeoutMs;
|
int timeoutMs;
|
||||||
int ret;
|
|
||||||
int flags;
|
int flags;
|
||||||
|
char buffer[ARTNET_MAX_BUFFER];
|
||||||
|
struct sockaddr_in serverAddr, srcAddr;
|
||||||
|
socklen_t srcLen = sizeof(struct sockaddr_in);
|
||||||
|
|
||||||
/* Create UDP socket */
|
/* Create UDP socket */
|
||||||
udpSocket = socket(PF_INET, SOCK_DGRAM, 0);
|
fdUdpSocket = socket(PF_INET, SOCK_DGRAM, 0);
|
||||||
if (udpSocket < 0) {
|
if (fdUdpSocket < 0) {
|
||||||
perror("Opening socket failed");
|
perror("Opening socket failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set non-blocking socket */
|
/* Set non-blocking socket */
|
||||||
flags = fcntl(udpSocket, F_GETFL, 0);
|
flags = fcntl(fdUdpSocket, F_GETFL, 0);
|
||||||
fcntl(udpSocket, F_SETFL, flags | O_NONBLOCK);
|
fcntl(fdUdpSocket, F_SETFL, flags | O_NONBLOCK);
|
||||||
|
|
||||||
/* pollfd structure and timeout */
|
/* pollfd structure and timeout */
|
||||||
memset(fds, 0, sizeof(fds));
|
memset(pollFdArray, 0, sizeof(pollFdArray));
|
||||||
fds[0].fd = udpSocket;
|
pollFdArray[0].fd = fdUdpSocket;
|
||||||
fds[0].events = POLLIN;
|
pollFdArray[0].events = POLLIN;
|
||||||
timeoutMs = 10;
|
timeoutMs = 10;
|
||||||
|
|
||||||
/* Configure settings in address struct */
|
/* Configure settings in address struct */
|
||||||
@ -81,16 +133,14 @@ static void *artnet_udp_handler(void *arg) {
|
|||||||
memset(serverAddr.sin_zero, '\0', sizeof(serverAddr.sin_zero));
|
memset(serverAddr.sin_zero, '\0', sizeof(serverAddr.sin_zero));
|
||||||
|
|
||||||
/* Bind socket with address struct */
|
/* Bind socket with address struct */
|
||||||
bind(udpSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
|
bind(fdUdpSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
|
||||||
|
|
||||||
struct sockaddr_in srcAddr;
|
|
||||||
socklen_t srcLen = sizeof(srcAddr);
|
|
||||||
|
|
||||||
while (isUdpListenerRunning) {
|
while (isUdpListenerRunning) {
|
||||||
|
|
||||||
if ((ret = poll(fds, 1, timeoutMs)) == 1) {
|
int pollReturn;
|
||||||
|
if ((pollReturn = poll(pollFdArray, 1, timeoutMs)) == 1) {
|
||||||
ssize_t bufferLen =
|
ssize_t bufferLen =
|
||||||
recvfrom(udpSocket, buffer, ARTNET_MAX_BUFFER, 0, (struct sockaddr *)&srcAddr, &srcLen);
|
recvfrom(fdUdpSocket, buffer, ARTNET_MAX_BUFFER, 0, (struct sockaddr *)&srcAddr, &srcLen);
|
||||||
|
|
||||||
if (bufferLen <= ARTNET_MAX_BUFFER && bufferLen > sizeof(artnetHeader_t)) {
|
if (bufferLen <= ARTNET_MAX_BUFFER && bufferLen > sizeof(artnetHeader_t)) {
|
||||||
artnetHeader_t *artnetHeader = (artnetHeader_t *)buffer;
|
artnetHeader_t *artnetHeader = (artnetHeader_t *)buffer;
|
||||||
@ -110,7 +160,7 @@ static void *artnet_udp_handler(void *arg) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case OpPoll:
|
case OpPoll:
|
||||||
artnet_send_poll_reply(srcAddr);
|
artnet_send_poll_reply(fdUdpSocket, srcAddr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -118,22 +168,26 @@ static void *artnet_udp_handler(void *arg) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (ret < 0) {
|
|
||||||
fprintf(stderr, "error polling %d: %s\n", udpSocket, strerror(errno));
|
} else if (pollReturn < 0) {
|
||||||
|
fprintf(stderr, "error polling %d: %s\n", fdUdpSocket, strerror(errno));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
close(udpSocket);
|
close(fdUdpSocket);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void artnet_send_poll_reply(struct sockaddr_in srcAddr) {
|
static void artnet_send_poll_reply(int fdUdpSocket, struct sockaddr_in senderAddr) {
|
||||||
/* Configure settings in address struct */
|
/* Configure settings in address struct */
|
||||||
srcAddr.sin_family = AF_INET;
|
senderAddr.sin_family = AF_INET;
|
||||||
srcAddr.sin_port = htons(ARTNET_PORT);
|
senderAddr.sin_port = htons(ARTNET_PORT);
|
||||||
memset(srcAddr.sin_zero, '\0', sizeof(srcAddr.sin_zero));
|
memset(senderAddr.sin_zero, '\0', sizeof(senderAddr.sin_zero));
|
||||||
|
|
||||||
sendto(udpSocket, (uint8_t *)&artPollReply, sizeof(artPollReply_t), 0,
|
if (sendto(fdUdpSocket, (uint8_t *)&artPollReply, sizeof(artPollReply_t), 0,
|
||||||
(struct sockaddr *)&srcAddr, sizeof(srcAddr));
|
(struct sockaddr *)&senderAddr, sizeof(senderAddr)) < 0) {
|
||||||
|
fprintf(stderr, "Error sending poll reply to %s:%d: %s\n", inet_ntoa(senderAddr.sin_addr),
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,14 +1,50 @@
|
|||||||
|
/** \file rpi_artnet.h
|
||||||
|
* \brief This module contains continuous tasks for artnet node communications.
|
||||||
|
*
|
||||||
|
* This is the header file for the definition of services to allow managing thread acting as artnet
|
||||||
|
* node.
|
||||||
|
*/
|
||||||
#if !defined(__RPI_ARTNET_H__)
|
#if !defined(__RPI_ARTNET_H__)
|
||||||
#define __RPI_ARTNET_H__
|
#define __RPI_ARTNET_H__
|
||||||
|
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Includes
|
||||||
|
**************************************************************************************************/
|
||||||
#include "rpi_artnet_packets.h"
|
#include "rpi_artnet_packets.h"
|
||||||
|
|
||||||
void artnet_init();
|
/***************************************************************************************************
|
||||||
|
* Preprocessor Constants and Macros
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
void start_artnet_bg_worker();
|
/***************************************************************************************************
|
||||||
|
* Type and Contant Definitions
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
void stop_artnet_bg_worker();
|
/***************************************************************************************************
|
||||||
|
* Global Variables
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
int artnet_get_dmx_data(unsigned int univerve, uint8_t **dmxData);
|
/***************************************************************************************************
|
||||||
|
* External Function Prototypes
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
#endif // __RPI_ARTNET_H__
|
/**
|
||||||
|
* \brief Start artnet node module
|
||||||
|
**/
|
||||||
|
void artnet_start();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Stop artnet node module
|
||||||
|
*/
|
||||||
|
void artnet_stop();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Get last DMX data received for the specified universe
|
||||||
|
*
|
||||||
|
* \param[in] univerve The universe to get data from
|
||||||
|
*
|
||||||
|
* \param[out] dmxData The pointer to the DMX data array
|
||||||
|
*/
|
||||||
|
int artnet_get_dmx_data(unsigned int univerve, uint8_t *dmxData[]);
|
||||||
|
|
||||||
|
#endif /* __RPI_ARTNET_H__ */
|
||||||
|
@ -1,3 +1,10 @@
|
|||||||
|
/** \file rpi_cava.h
|
||||||
|
* \brief This module contains continuous tasks for cava (spectrum analyzer) comunication
|
||||||
|
*/
|
||||||
|
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Includes
|
||||||
|
**************************************************************************************************/
|
||||||
#include "rpi_cava.h"
|
#include "rpi_cava.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@ -9,23 +16,59 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#ifdef _WIN32
|
|
||||||
#include <Windows.h>
|
|
||||||
#else
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
|
||||||
|
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Preprocessor Constants and Macros
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constant for Maximum char in a line (128 number of (5 char + 1 delim) + \n )
|
||||||
|
*/
|
||||||
#define MAXLINECHAR 128 * (5 + 1) + 1
|
#define MAXLINECHAR 128 * (5 + 1) + 1
|
||||||
|
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Type and Contant Definitions
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Persistent Variables
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cava process id
|
||||||
|
*/
|
||||||
pid_t cavaPid;
|
pid_t cavaPid;
|
||||||
|
/**
|
||||||
|
* Boolean for interrupting the main thread loop
|
||||||
|
*/
|
||||||
bool isFifoReaderRunning = false;
|
bool isFifoReaderRunning = false;
|
||||||
|
/**
|
||||||
|
* Task thread identifier
|
||||||
|
*/
|
||||||
pthread_t fifoReader;
|
pthread_t fifoReader;
|
||||||
int cavaFifo;
|
|
||||||
|
int fdCavaInput;
|
||||||
char lineBuffer[MAXLINECHAR];
|
char lineBuffer[MAXLINECHAR];
|
||||||
uint16_t buffer[128 + 2];
|
uint16_t buffer[128 + 2];
|
||||||
|
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Internal Function Prototypes
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief This function is used to thread main execution function
|
||||||
|
*
|
||||||
|
* \param arg not used.
|
||||||
|
*
|
||||||
|
* \return NULL.
|
||||||
|
*/
|
||||||
static void *fifo_to_buffer(void *arg);
|
static void *fifo_to_buffer(void *arg);
|
||||||
|
|
||||||
|
/***************************************************************************************************
|
||||||
|
* External Function Definitions
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
void setup_cava() {
|
void setup_cava() {
|
||||||
if ((cavaPid = fork()) == -1) {
|
if ((cavaPid = fork()) == -1) {
|
||||||
perror("fork");
|
perror("fork");
|
||||||
@ -34,7 +77,6 @@ void setup_cava() {
|
|||||||
|
|
||||||
if (cavaPid == 0) {
|
if (cavaPid == 0) {
|
||||||
/* Child process*/
|
/* Child process*/
|
||||||
pthread_setschedprio(pthread_self(), 30);
|
|
||||||
char *args[] = {"/usr/local/bin/cava", "-p", "/home/pi/LedBars/RpiLedBars/cava_config", NULL};
|
char *args[] = {"/usr/local/bin/cava", "-p", "/home/pi/LedBars/RpiLedBars/cava_config", NULL};
|
||||||
|
|
||||||
if (execv(args[0], args) != 0) {
|
if (execv(args[0], args) != 0) {
|
||||||
@ -68,33 +110,36 @@ int get_cava_buffer(uint16_t **buffer_dst) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t valueIndex = 0, charOffset = 0;
|
/***************************************************************************************************
|
||||||
char strValue[6] = "0\0";
|
* Internal Function Definitions
|
||||||
bool hasToBeDiscarded = false;
|
**************************************************************************************************/
|
||||||
|
|
||||||
static void *fifo_to_buffer(void *arg) {
|
static void *fifo_to_buffer(void *arg) {
|
||||||
struct pollfd fds[1];
|
struct pollfd fds[1];
|
||||||
int timeoutMs;
|
int timeoutMs;
|
||||||
int ret;
|
int ret;
|
||||||
|
size_t valueIndex = 0, charOffset = 0;
|
||||||
|
char strValue[6] = "0\0";
|
||||||
|
bool hasToBeDiscarded = true;
|
||||||
|
|
||||||
if ((cavaFifo = open("/tmp/cava_output", O_RDONLY | O_NONBLOCK)) < 0) {
|
if start_cava_process ()
|
||||||
|
;
|
||||||
|
if ((fdCavaInput = open("/tmp/cava_output", O_RDONLY | O_NONBLOCK)) < 0) {
|
||||||
perror("open");
|
perror("open");
|
||||||
close_cava();
|
close_cava();
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(fds, 0, sizeof(fds));
|
memset(fds, 0, sizeof(fds));
|
||||||
fds[0].fd = cavaFifo;
|
fds[0].fd = fdCavaInput;
|
||||||
fds[0].events = POLLIN;
|
fds[0].events = POLLIN;
|
||||||
timeoutMs = 10;
|
timeoutMs = 10;
|
||||||
|
|
||||||
hasToBeDiscarded = true;
|
|
||||||
|
|
||||||
while (isFifoReaderRunning) {
|
while (isFifoReaderRunning) {
|
||||||
|
|
||||||
if ((ret = poll(fds, 1, timeoutMs)) == 1) {
|
if ((ret = poll(fds, 1, timeoutMs)) == 1) {
|
||||||
int nread;
|
int nread;
|
||||||
nread = read(cavaFifo, lineBuffer, 128 + 1);
|
nread = read(fdCavaInput, lineBuffer, 128 + 1);
|
||||||
|
|
||||||
if (nread >= 0) {
|
if (nread >= 0) {
|
||||||
for (size_t i = 0; i < nread; ++i) {
|
for (size_t i = 0; i < nread; ++i) {
|
||||||
@ -136,11 +181,54 @@ static void *fifo_to_buffer(void *arg) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (ret < 0) {
|
} else if (ret < 0) {
|
||||||
fprintf(stderr, "error polling %d: %s\n", cavaFifo, strerror(errno));
|
fprintf(stderr, "error polling %d: %s\n", fdCavaInput, strerror(errno));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
close(cavaFifo);
|
close(fdCavaInput);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int start_cava_process() {
|
||||||
|
int fdCavaPipe[2];
|
||||||
|
|
||||||
|
if (pipe(fdCavaPipe) < 0) {
|
||||||
|
fprintf(stderr, "Cava pipe failure: %s\n", strerror(errno));
|
||||||
|
return -EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((cavaPid = fork()) < 0) {
|
||||||
|
fprintf(stderr, "Cava fork failure: %s\n", strerror(errno));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cavaPid == 0) {
|
||||||
|
/* Child process*/
|
||||||
|
char *args[] = {"cava", "-p", "/home/pi/LedBars/RpiLedBars/cava_config", NULL};
|
||||||
|
|
||||||
|
/* Close reading end of the pipe */
|
||||||
|
close(fdCavaPipe[0]);
|
||||||
|
/* Dup writing end of the pipe in place of stdout */
|
||||||
|
dup2(fdCavaPipe[1], STDOUT_FILENO);
|
||||||
|
/* Close writing end of the pipe */
|
||||||
|
close(fdCavaPipe[1]);
|
||||||
|
|
||||||
|
execvp(args[0], args);
|
||||||
|
fprintf(stderr, "Cava execvp failure or return: %s\n", strerror(errno));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
} else {
|
||||||
|
/* Close writing end of the pipe */
|
||||||
|
close(fdCavaPipe[1]);
|
||||||
|
/* Set reading end of the pipe non-blocking */
|
||||||
|
flags = fcntl(fdCavaPipe[0], F_GETFL, 0);
|
||||||
|
fcntl(fdCavaPipe[0], F_SETFL, flags | O_NONBLOCK);
|
||||||
|
/* Return reading end of the pipe */
|
||||||
|
return fdCavaPipe[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unreachable */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void stop_cava_process() { kill(cavaPid, SIGTERM); }
|
||||||
|
@ -1,8 +1,33 @@
|
|||||||
|
/** \file rpi_cava.h
|
||||||
|
* \brief This module contains continuous tasks for cava (spectrum analyzer) comunication
|
||||||
|
*/
|
||||||
#if !defined(__RPI_CAVA_H__)
|
#if !defined(__RPI_CAVA_H__)
|
||||||
#define __RPI_CAVA_H__
|
#define __RPI_CAVA_H__
|
||||||
|
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Includes
|
||||||
|
**************************************************************************************************/
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Preprocessor Constants and Macros
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Type and Contant Definitions
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Global Variables
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************************************
|
||||||
|
* External Function Prototypes
|
||||||
|
**************************************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Start artnet node module
|
||||||
|
**/
|
||||||
void setup_cava();
|
void setup_cava();
|
||||||
|
|
||||||
int get_cava_buffer(uint16_t **buffer_dst);
|
int get_cava_buffer(uint16_t **buffer_dst);
|
||||||
|
Loading…
Reference in New Issue
Block a user