shmem input added

master
dnalor 7 years ago
parent c3d75c1d92
commit 5af0090d7b
  1. 11
      README.md
  2. 14
      cava.c
  3. 13
      config.c
  4. 18
      configure.ac
  5. 112
      input/shmem.c

@ -40,6 +40,7 @@ thanks to [anko](https://github.com/anko) for the gif, here is the [recipe]( htt
- [From ALSA-loopback device (Tricky)](#from-alsa-loopback-device-tricky)
- [From mpd's fifo output](#from-mpds-fifo-output)
- [sndio](#sndio)
- [squeezelite](#squeezelite)
- [Running via ssh](#running-via-ssh)
- [Font notes](#font-notes)
- [In ttys](#in-ttys)
@ -245,7 +246,15 @@ $ sndiod -dd -s default -m mon -s monitor
$ AUDIODEVICE=snd/0.monitor cava
```
### squeezelite
[squeezelite](https://en.wikipedia.org/wiki/Squeezelite) is one of several software clients available for the Logitech Media Server. Squeezelite can export it's audio data as shared memory, which is what this input module uses.
Configure C.A.V.A. with the `--enable-shmem` option, then adapt your config:
```
method = shmem
source = /squeezelite-AA:BB:CC:DD:EE:FF
```
where `AA:BB:CC:DD:EE:FF` is squeezelite's MAC address (check the LMS Web GUI (Settings>Information) if unsure).
Note: squeezelite must be started with the `-v` flag to enable visualizer support.
Running via ssh
---------------

@ -63,6 +63,10 @@
#include "input/sndio.c"
#endif
#ifdef SHMEM
#include "input/shmem.c"
#endif
#include <iniparser.h>
#include "config.h"
@ -327,6 +331,9 @@ as of 0.4.0 all options are specified in config file, see in '/home/username/.co
#ifdef SNDIO
strcat(supportedInput,", 'sndio'");
#endif
#ifdef SHMEM
strcat(supportedInput,", 'shmem'");
#endif
//fft: planning to rock
fftw_complex outl[M / 2 + 1];
@ -441,6 +448,13 @@ as of 0.4.0 all options are specified in config file, see in '/home/username/.co
}
#endif
#ifdef SHMEM
if (p.im == 5) {
thr_id = pthread_create(&p_thread, NULL, input_shmem, (void*)&audio);
audio.rate = 44100;
}
#endif
if (p.highcf > audio.rate / 2) {
cleanup();
fprintf(stderr,

@ -160,6 +160,13 @@ if (strcmp(inputMethod, "sndio") == 0) {
return false;
#endif
}
if (strcmp(inputMethod, "shmem") == 0) {
p->im = 5;
#ifndef SHMEM
write_errorf(error, "cava was built without shmem support\n");
return false;
#endif
}
if (p->im == 0) {
write_errorf(error, "input method '%s' is not supported, supported methods are: %s\n",
inputMethod, supportedInput);
@ -480,6 +487,12 @@ if (strcmp(inputMethod, "sndio") == 0) {
p->audio_source = (char *)iniparser_getstring(ini, "input:source", SIO_DEVANY);
}
#endif
#ifdef SHMEM
if (strcmp(inputMethod, "shmem") == 0) {
p->im = 5;
p->audio_source = (char *)iniparser_getstring(ini, "input:source", "/squeezelite-00:00:00:00:00:00");
}
#endif
return validate_config(supportedInput, params, error);
//iniparser_freedict(ini);

@ -167,6 +167,24 @@ AS_IF([test "x$enable_legacy_iniparser" = "xyes"], [
CPPFLAGS="$CPPFLAGS -DLEGACYINIPARSER"
])
dnl ############################
dnl checking if shared memory input is enabled
dnl ############################
AC_ARG_ENABLE([shmem],
AS_HELP_STRING([--enable-shmem],
[enable shared memory input (e.g. for squeezelite)])
)
AS_IF([test "x$enable_shmem" = "xyes"], [
dnl enabling shared memory input
AC_MSG_NOTICE([enabling shared memory input])
CPPFLAGS="$CPPFLAGS -DSHMEM"
LIBS="$LIBS -lrt"
])
dnl ############################
dnl Set font directory
dnl ############################

@ -0,0 +1,112 @@
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
typedef unsigned int u32_t;
typedef short s16_t;
// #define BUFSIZE 1024
#define BUFSIZE 2048
int rc;
/*
struct audio_data {
int audio_out_r[2048];
int audio_out_l[2048];
int format;
unsigned int rate ;
char *source; //alsa device, fifo path or pulse source
int im; //input mode alsa, fifo or pulse
int channels;
int terminate; // shared variable used to terminate audio thread
char error_message[1024];
};
*/
#define VIS_BUF_SIZE 16384
#define VB_OFFSET 8192+4096
typedef struct {
pthread_rwlock_t rwlock;
u32_t buf_size;
u32_t buf_index;
bool running;
u32_t rate;
time_t updated;
s16_t buffer[VIS_BUF_SIZE];
} vis_t;
//input: SHMEM
void* input_shmem(void* data)
{
struct audio_data *audio = (struct audio_data *)data;
vis_t *mmap_area;
int fd; /* file descriptor to mmaped area */
int mmap_count = sizeof( vis_t);
/*
struct timespec req = { .tv_sec = 0, .tv_nsec = 10000000 };
int16_t buf[BUFSIZE / 2];
int bytes = 0;
int t = 0;
*/
int n = 0;
int i;
printf("input_shmem: source: %s", audio->source);
fd = shm_open(audio->source, O_RDWR, 0666);
if (fd < 0 ) {
printf("Could not open source '%s': %s\n", audio->source, strerror( errno ) );
exit(EXIT_FAILURE);
} else {
mmap_area = mmap(NULL, sizeof( vis_t), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if ((intptr_t)mmap_area == -1) {
printf("mmap failed - check if squeezelite is running with visualization enabled\n");
exit(EXIT_FAILURE);
}
}
printf("bufs: %u / run: %u / rate: %u\n",mmap_area->buf_size, mmap_area->running, mmap_area->rate);
audio->rate = mmap_area->rate;
while (1) {
// for (i = 0; i < BUFSIZE; i += 2) { // BUFSIZE / 2
for (i = VB_OFFSET; i < BUFSIZE+VB_OFFSET; i += 2) {
if (audio->channels == 1) {
audio->audio_out_l[n] = (mmap_area->buffer[i] + mmap_area->buffer[i + 1]) / 2;
} else if (audio->channels == 2) {
audio->audio_out_l[n] = mmap_area->buffer[i];
audio->audio_out_r[n] = mmap_area->buffer[i + 1];
}
n++;
if (n == 2048 - 1) n = 0;
}
if (audio->terminate == 1) {
break;
}
}
// cleanup
if ( fd > 0 ) {
if ( close( fd ) != 0 ) {
printf("Could not close file descriptor %d: %s", fd, strerror( errno ) );
}
} else {
printf("Wrong file descriptor %d", fd );
}
if ( munmap( mmap_area, mmap_count ) != 0 ) {
printf("Could not munmap() area %p+%d. %s", mmap_area, mmap_count, strerror( errno ) );
}
return 0;
}
Loading…
Cancel
Save