cava with pipe, and template
This commit is contained in:
parent
7117cbbe4c
commit
6add75c64e
@ -12,7 +12,7 @@ source = plughw:1
|
||||
method = raw
|
||||
channels = mono
|
||||
mono_option = left
|
||||
raw_target = /tmp/cava_output
|
||||
;raw_target = /dev/stdout
|
||||
data_format = ascii
|
||||
ascii_max_range=65535
|
||||
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 <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
@ -17,6 +18,8 @@
|
||||
|
||||
#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
|
||||
MEM_MAP gpio_regs;
|
||||
|
||||
@ -24,9 +27,19 @@ char *gpio_mode_strs[] = {GPIO_MODE_STRS};
|
||||
|
||||
// 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
|
||||
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 <stdlib.h>
|
||||
#include <wiringPi.h>
|
||||
|
||||
/***************************************************************************************************
|
||||
* Preprocessor Constants and Macros
|
||||
**************************************************************************************************/
|
||||
|
||||
/***************************************************************************************************
|
||||
* Type and Contant Definitions
|
||||
**************************************************************************************************/
|
||||
unsigned const selectorPinNumber = 4;
|
||||
/* TODO use GPIO function from ../gpio/gipo.h (same pin number) */
|
||||
int selectorPins[4] = {5, 6, 26, 27};
|
||||
|
||||
void setup_selector() {
|
||||
/***************************************************************************************************
|
||||
* Persistent Variables
|
||||
**************************************************************************************************/
|
||||
|
||||
/***************************************************************************************************
|
||||
* Internal Function Prototypes
|
||||
**************************************************************************************************/
|
||||
|
||||
/***************************************************************************************************
|
||||
* External Function Definitions
|
||||
**************************************************************************************************/
|
||||
void selector_setup() {
|
||||
wiringPiSetupGpio();
|
||||
|
||||
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) {
|
||||
if (digitalRead(selectorPins[i])) {
|
||||
return i;
|
||||
@ -23,10 +49,14 @@ int get_selector_position() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
void print_selector() {
|
||||
void selector_print() {
|
||||
char modeStr[] = "0 | 0 | 0 | 0 \n";
|
||||
for (size_t i = 0; i < selectorPinNumber; ++i) {
|
||||
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__)
|
||||
#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__ */
|
@ -49,18 +49,10 @@ int main(int argc, char const *argv[]) {
|
||||
fprintf(stderr, "WARNING: Failed to set stepper thread to real-time priority\n");
|
||||
}
|
||||
|
||||
setup_selector();
|
||||
|
||||
// // 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);
|
||||
|
||||
midi_controller_setup();
|
||||
selector_setup();
|
||||
leddriver_setup();
|
||||
|
||||
setup_midi_controller();
|
||||
artnet_init();
|
||||
setup_cava();
|
||||
|
||||
@ -68,8 +60,8 @@ int main(int argc, char const *argv[]) {
|
||||
while (1) {
|
||||
struct timespec loopStart;
|
||||
clock_gettime(CLOCK_MONOTONIC, &loopStart);
|
||||
int mode = get_selector_position();
|
||||
execute_midi_controller();
|
||||
int mode = selector_get_position();
|
||||
midi_controller_execute();
|
||||
|
||||
if (mode != -1) {
|
||||
if (mode != previousMode) {
|
||||
@ -79,7 +71,7 @@ int main(int argc, char const *argv[]) {
|
||||
/* stop previous bg task */
|
||||
switch (previousMode) {
|
||||
case 1:
|
||||
stop_artnet_bg_worker();
|
||||
artnet_stop();
|
||||
break;
|
||||
case 2:
|
||||
stop_cava_bg_worker();
|
||||
@ -91,7 +83,7 @@ int main(int argc, char const *argv[]) {
|
||||
/* start new bg task */
|
||||
switch (mode) {
|
||||
case 1:
|
||||
start_artnet_bg_worker();
|
||||
artnet_start();
|
||||
break;
|
||||
case 2:
|
||||
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 setup_midi_controller() {
|
||||
void midi_controller_setup() {
|
||||
if (snd_seq_open(&seq_handle, "default", SND_SEQ_OPEN_INPUT, SND_SEQ_NONBLOCK) != 0) {
|
||||
SNDERR("snd_seq_open");
|
||||
}
|
||||
@ -45,7 +45,7 @@ void setup_midi_controller() {
|
||||
subscribe_midi_controller(controller);
|
||||
}
|
||||
|
||||
void execute_midi_controller() {
|
||||
void midi_controller_execute() {
|
||||
snd_seq_event_t *ev = NULL;
|
||||
int ret;
|
||||
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() {
|
||||
snd_seq_addr_t sender = {.client = 0, .port = SND_SEQ_PORT_SYSTEM_ANNOUNCE};
|
||||
|
@ -1,10 +1,10 @@
|
||||
#if !defined(__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__ */
|
@ -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 <arpa/inet.h>
|
||||
@ -13,19 +22,57 @@
|
||||
|
||||
#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;
|
||||
/**
|
||||
* Task thread identifier
|
||||
*/
|
||||
pthread_t udpListener;
|
||||
/**
|
||||
* Buffer for storing artnet dmx data received
|
||||
*/
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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) {
|
||||
fprintf(stderr, "Universe %d out of bounds %d\n", univerve, 16);
|
||||
*dmxData = NULL;
|
||||
@ -51,27 +98,32 @@ int artnet_get_dmx_data(unsigned int univerve, uint8_t **dmxData) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***************************************************************************************************
|
||||
* Internal Function Definitions
|
||||
**************************************************************************************************/
|
||||
static void *artnet_udp_handler(void *arg) {
|
||||
struct sockaddr_in serverAddr;
|
||||
struct pollfd fds[1];
|
||||
int fdUdpSocket = -1;
|
||||
struct pollfd pollFdArray[1];
|
||||
int timeoutMs;
|
||||
int ret;
|
||||
int flags;
|
||||
char buffer[ARTNET_MAX_BUFFER];
|
||||
struct sockaddr_in serverAddr, srcAddr;
|
||||
socklen_t srcLen = sizeof(struct sockaddr_in);
|
||||
|
||||
/* Create UDP socket */
|
||||
udpSocket = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if (udpSocket < 0) {
|
||||
fdUdpSocket = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if (fdUdpSocket < 0) {
|
||||
perror("Opening socket failed");
|
||||
}
|
||||
|
||||
/* Set non-blocking socket */
|
||||
flags = fcntl(udpSocket, F_GETFL, 0);
|
||||
fcntl(udpSocket, F_SETFL, flags | O_NONBLOCK);
|
||||
flags = fcntl(fdUdpSocket, F_GETFL, 0);
|
||||
fcntl(fdUdpSocket, F_SETFL, flags | O_NONBLOCK);
|
||||
|
||||
/* pollfd structure and timeout */
|
||||
memset(fds, 0, sizeof(fds));
|
||||
fds[0].fd = udpSocket;
|
||||
fds[0].events = POLLIN;
|
||||
memset(pollFdArray, 0, sizeof(pollFdArray));
|
||||
pollFdArray[0].fd = fdUdpSocket;
|
||||
pollFdArray[0].events = POLLIN;
|
||||
timeoutMs = 10;
|
||||
|
||||
/* 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));
|
||||
|
||||
/* Bind socket with address struct */
|
||||
bind(udpSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
|
||||
|
||||
struct sockaddr_in srcAddr;
|
||||
socklen_t srcLen = sizeof(srcAddr);
|
||||
bind(fdUdpSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
|
||||
|
||||
while (isUdpListenerRunning) {
|
||||
|
||||
if ((ret = poll(fds, 1, timeoutMs)) == 1) {
|
||||
int pollReturn;
|
||||
if ((pollReturn = poll(pollFdArray, 1, timeoutMs)) == 1) {
|
||||
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)) {
|
||||
artnetHeader_t *artnetHeader = (artnetHeader_t *)buffer;
|
||||
@ -110,7 +160,7 @@ static void *artnet_udp_handler(void *arg) {
|
||||
break;
|
||||
|
||||
case OpPoll:
|
||||
artnet_send_poll_reply(srcAddr);
|
||||
artnet_send_poll_reply(fdUdpSocket, srcAddr);
|
||||
break;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 */
|
||||
srcAddr.sin_family = AF_INET;
|
||||
srcAddr.sin_port = htons(ARTNET_PORT);
|
||||
memset(srcAddr.sin_zero, '\0', sizeof(srcAddr.sin_zero));
|
||||
senderAddr.sin_family = AF_INET;
|
||||
senderAddr.sin_port = htons(ARTNET_PORT);
|
||||
memset(senderAddr.sin_zero, '\0', sizeof(senderAddr.sin_zero));
|
||||
|
||||
sendto(udpSocket, (uint8_t *)&artPollReply, sizeof(artPollReply_t), 0,
|
||||
(struct sockaddr *)&srcAddr, sizeof(srcAddr));
|
||||
if (sendto(fdUdpSocket, (uint8_t *)&artPollReply, sizeof(artPollReply_t), 0,
|
||||
(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__)
|
||||
#define __RPI_ARTNET_H__
|
||||
|
||||
/***************************************************************************************************
|
||||
* Includes
|
||||
**************************************************************************************************/
|
||||
#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 <errno.h>
|
||||
@ -9,23 +16,59 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#else
|
||||
#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
|
||||
|
||||
/***************************************************************************************************
|
||||
* Type and Contant Definitions
|
||||
**************************************************************************************************/
|
||||
|
||||
/***************************************************************************************************
|
||||
* Persistent Variables
|
||||
**************************************************************************************************/
|
||||
|
||||
/**
|
||||
* Cava process id
|
||||
*/
|
||||
pid_t cavaPid;
|
||||
/**
|
||||
* Boolean for interrupting the main thread loop
|
||||
*/
|
||||
bool isFifoReaderRunning = false;
|
||||
/**
|
||||
* Task thread identifier
|
||||
*/
|
||||
pthread_t fifoReader;
|
||||
int cavaFifo;
|
||||
|
||||
int fdCavaInput;
|
||||
char lineBuffer[MAXLINECHAR];
|
||||
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);
|
||||
|
||||
/***************************************************************************************************
|
||||
* External Function Definitions
|
||||
**************************************************************************************************/
|
||||
|
||||
void setup_cava() {
|
||||
if ((cavaPid = fork()) == -1) {
|
||||
perror("fork");
|
||||
@ -34,7 +77,6 @@ void setup_cava() {
|
||||
|
||||
if (cavaPid == 0) {
|
||||
/* Child process*/
|
||||
pthread_setschedprio(pthread_self(), 30);
|
||||
char *args[] = {"/usr/local/bin/cava", "-p", "/home/pi/LedBars/RpiLedBars/cava_config", NULL};
|
||||
|
||||
if (execv(args[0], args) != 0) {
|
||||
@ -68,33 +110,36 @@ int get_cava_buffer(uint16_t **buffer_dst) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t valueIndex = 0, charOffset = 0;
|
||||
char strValue[6] = "0\0";
|
||||
bool hasToBeDiscarded = false;
|
||||
/***************************************************************************************************
|
||||
* Internal Function Definitions
|
||||
**************************************************************************************************/
|
||||
|
||||
static void *fifo_to_buffer(void *arg) {
|
||||
struct pollfd fds[1];
|
||||
int timeoutMs;
|
||||
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");
|
||||
close_cava();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memset(fds, 0, sizeof(fds));
|
||||
fds[0].fd = cavaFifo;
|
||||
fds[0].fd = fdCavaInput;
|
||||
fds[0].events = POLLIN;
|
||||
timeoutMs = 10;
|
||||
|
||||
hasToBeDiscarded = true;
|
||||
|
||||
while (isFifoReaderRunning) {
|
||||
|
||||
if ((ret = poll(fds, 1, timeoutMs)) == 1) {
|
||||
int nread;
|
||||
nread = read(cavaFifo, lineBuffer, 128 + 1);
|
||||
nread = read(fdCavaInput, lineBuffer, 128 + 1);
|
||||
|
||||
if (nread >= 0) {
|
||||
for (size_t i = 0; i < nread; ++i) {
|
||||
@ -136,11 +181,54 @@ static void *fifo_to_buffer(void *arg) {
|
||||
}
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
|
||||
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__)
|
||||
#define __RPI_CAVA_H__
|
||||
|
||||
/***************************************************************************************************
|
||||
* Includes
|
||||
**************************************************************************************************/
|
||||
#include <stdint.h>
|
||||
|
||||
/***************************************************************************************************
|
||||
* Preprocessor Constants and Macros
|
||||
**************************************************************************************************/
|
||||
|
||||
/***************************************************************************************************
|
||||
* Type and Contant Definitions
|
||||
**************************************************************************************************/
|
||||
|
||||
/***************************************************************************************************
|
||||
* Global Variables
|
||||
**************************************************************************************************/
|
||||
|
||||
/***************************************************************************************************
|
||||
* External Function Prototypes
|
||||
**************************************************************************************************/
|
||||
|
||||
/**
|
||||
* \brief Start artnet node module
|
||||
**/
|
||||
void setup_cava();
|
||||
|
||||
int get_cava_buffer(uint16_t **buffer_dst);
|
||||
|
Loading…
Reference in New Issue
Block a user