Merge pull request #244 from dnalor/input-shmem

Input shmem
master
karl 7 years ago committed by GitHub
commit 45478b2f27
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 11
      README.md
  2. 14
      cava.c
  3. 13
      config.c
  4. 18
      configure.ac
  5. 5
      example_files/config
  6. 91
      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 ALSA-loopback device (Tricky)](#from-alsa-loopback-device-tricky)
- [From mpd's fifo output](#from-mpds-fifo-output) - [From mpd's fifo output](#from-mpds-fifo-output)
- [sndio](#sndio) - [sndio](#sndio)
- [squeezelite](#squeezelite)
- [Running via ssh](#running-via-ssh) - [Running via ssh](#running-via-ssh)
- [Font notes](#font-notes) - [Font notes](#font-notes)
- [In ttys](#in-ttys) - [In ttys](#in-ttys)
@ -245,7 +246,15 @@ $ sndiod -dd -s default -m mon -s monitor
$ AUDIODEVICE=snd/0.monitor cava $ 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 Running via ssh
--------------- ---------------

@ -63,6 +63,10 @@
#include "input/sndio.c" #include "input/sndio.c"
#endif #endif
#ifdef SHMEM
#include "input/shmem.c"
#endif
#include <iniparser.h> #include <iniparser.h>
#include "config.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 #ifdef SNDIO
strcat(supportedInput,", 'sndio'"); strcat(supportedInput,", 'sndio'");
#endif #endif
#ifdef SHMEM
strcat(supportedInput,", 'shmem'");
#endif
//fft: planning to rock //fft: planning to rock
fftw_complex outl[M / 2 + 1]; 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 #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) { if (p.highcf > audio.rate / 2) {
cleanup(); cleanup();
fprintf(stderr, fprintf(stderr,

@ -160,6 +160,13 @@ if (strcmp(inputMethod, "sndio") == 0) {
return false; return false;
#endif #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) { if (p->im == 0) {
write_errorf(error, "input method '%s' is not supported, supported methods are: %s\n", write_errorf(error, "input method '%s' is not supported, supported methods are: %s\n",
inputMethod, supportedInput); inputMethod, supportedInput);
@ -480,6 +487,12 @@ if (strcmp(inputMethod, "sndio") == 0) {
p->audio_source = (char *)iniparser_getstring(ini, "input:source", SIO_DEVANY); p->audio_source = (char *)iniparser_getstring(ini, "input:source", SIO_DEVANY);
} }
#endif #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); return validate_config(supportedInput, params, error);
//iniparser_freedict(ini); //iniparser_freedict(ini);

@ -167,6 +167,24 @@ AS_IF([test "x$enable_legacy_iniparser" = "xyes"], [
CPPFLAGS="$CPPFLAGS -DLEGACYINIPARSER" 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 ############################
dnl Set font directory dnl Set font directory
dnl ############################ dnl ############################

@ -37,7 +37,7 @@
[input] [input]
# Audio capturing method. Possible methods are: 'pulse', 'alsa', 'fifo' or 'sndio'. # Audio capturing method. Possible methods are: 'pulse', 'alsa', 'fifo', 'sndio' or 'shmem'
# Defaults to 'pulse', 'alsa' or 'fifo', in that order, dependent on what support cava was built with. # Defaults to 'pulse', 'alsa' or 'fifo', in that order, dependent on what support cava was built with.
# #
# All input methods uses the same config variable 'source' # All input methods uses the same config variable 'source'
@ -48,6 +48,7 @@
# #
# For alsa 'source' will be the capture device. # For alsa 'source' will be the capture device.
# For fifo 'source' will be the path to fifo-file. # For fifo 'source' will be the path to fifo-file.
# For shmem 'source' will be /squeezelite-AA:BB:CC:DD:EE:FF where 'AA:BB:CC:DD:EE:FF' will be squeezelite's MAC address
; method = pulse ; method = pulse
; source = auto ; source = auto
@ -57,6 +58,8 @@
; method = fifo ; method = fifo
; source = /tmp/mpd.fifo ; source = /tmp/mpd.fifo
; method = shmem
; source = /squeezelite-AA:BB:CC:DD:EE:FF
[output] [output]

@ -0,0 +1,91 @@
#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;
#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);
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 = 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