diff options
| author | Takamichi Horikawa <takamichiho@gmail.com> | 2017-07-17 00:38:13 +0900 | 
|---|---|---|
| committer | Takamichi Horikawa <takamichiho@gmail.com> | 2017-07-17 00:38:13 +0900 | 
| commit | e8e5747650626442f8f9940ad5bc37b21ca85ad9 (patch) | |
| tree | 1c6a0eae92cd834dfbd4fe6286d4bc24821e10ad /gtk | |
| parent | 44c20e41ddd0c394daf5aa45d88baa95334f04fc (diff) | |
soundout autoconf
Diffstat (limited to 'gtk')
| -rw-r--r-- | gtk/Makefile.am | 17 | ||||
| -rw-r--r-- | gtk/configure.ac | 23 | ||||
| -rw-r--r-- | gtk/soundout/alsaout.c | 152 | ||||
| -rw-r--r-- | gtk/soundout/alsaout.h | 9 | ||||
| -rw-r--r-- | gtk/soundout/jackout.c | 127 | ||||
| -rw-r--r-- | gtk/soundout/jackout.h | 9 | ||||
| -rw-r--r-- | gtk/soundout/ossout.c | 8 | ||||
| -rw-r--r-- | gtk/soundout/pulseout.c | 133 | ||||
| -rw-r--r-- | gtk/soundout/pulseout.h | 9 | ||||
| -rw-r--r-- | gtk/soundout/soundout.c | 14 | ||||
| -rw-r--r-- | gtk/soundout/soundout.h | 16 | 
11 files changed, 32 insertions, 485 deletions
| diff --git a/gtk/Makefile.am b/gtk/Makefile.am index 43a767d..2375b28 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -19,15 +19,22 @@ FMDSP_SRC=../fmdsp/fmdsp.c \            ../fmdsp/font_fmdsp_small.c \            ../fmdsp/fmdsp_platform_unix.c -SOUNDOUT_SRC=soundout/soundout.c \ -             soundout/pulseout.c \ -             soundout/jackout.c \ -             soundout/alsaout.c +SOUNDOUT_SRC=../soundout/soundout.c + +if ENABLE_JACK +SOUNDOUT_SRC+=../soundout/jackout.c +endif +if ENABLE_PULSE +SOUNDOUT_SRC+=../soundout/pulseout.c +endif +if ENABLE_ALSA +SOUNDOUT_SRC+=../soundout/alsaout.c +endif  #fmplayer_CFLAGS=$(CFLAGS)  #CFLAGS=  fmplayer_CPPFLAGS=-Wall -Wextra -pedantic \ -                  -I.. -Isoundout \ +                  -I.. -I../soundout \                    $(GTK3_CFLAGS) $(JACK_CFLAGS) $(PULSE_CFLAGS) $(ALSA_CFLAGS) $(SNDFILE_CFLAGS)  fmplayer_LDADD=$(GTK3_LIBS) $(JACK_LIBS) $(PULSE_LIBS) $(ALSA_LIBS) $(SNDFILE_LIBS) -lm -lpthread diff --git a/gtk/configure.ac b/gtk/configure.ac index 8a61ac1..fc79c8c 100644 --- a/gtk/configure.ac +++ b/gtk/configure.ac @@ -6,12 +6,29 @@ AC_PROG_RANLIB  AM_PROG_AR  AM_PROG_AS -PKG_CHECK_MODULES([JACK], [jack soxr]) -PKG_CHECK_MODULES([PULSE], [libpulse]) -PKG_CHECK_MODULES([ALSA], [alsa]) +PKG_CHECK_MODULES([JACK], [jack soxr], [jack_found=yes], [jack_found=no]) +PKG_CHECK_MODULES([PULSE], [libpulse], [pulse_found=yes], [pulse_found=no]) +PKG_CHECK_MODULES([ALSA], [alsa], [alsa_found=yes], [alsa_found=no])  PKG_CHECK_MODULES([GTK3], [gtk+-3.0 cairo])  PKG_CHECK_MODULES([SNDFILE], [sndfile]) +AS_IF([test "x$jack_found" = "xno" -a "x$pulse_found" = "xno" -a "x$alsa_found" = "xno"], [ +  AC_MSG_ERROR([No audio output backend found]) +]) + +AM_CONDITIONAL([ENABLE_JACK], [test "x$jack_found" = "xyes"]) +AS_IF([test "x$jack_found" = "xyes"], [ +  AC_DEFINE([ENABLE_JACK]) +]) +AM_CONDITIONAL([ENABLE_PULSE], [test "x$pulse_found" = "xyes"]) +AS_IF([test "x$pulse_found" = "xyes"], [ +  AC_DEFINE([ENABLE_PULSE]) +]) +AM_CONDITIONAL([ENABLE_ALSA], [test "x$alsa_found" = "xyes"]) +AS_IF([test "x$alsa_found" = "xyes"], [ +  AC_DEFINE([ENABLE_ALSA]) +]) +  AC_ARG_ENABLE([neon], AS_HELP_STRING([--enable-neon], [Enable NEON optimized functions for SSG sinc filtering and fmdsp palette lookup. Tested on Cortex-A53 (Raspberry PI 3)]))  AM_CONDITIONAL([ENABLE_NEON], [test "x$enable_neon" = "xyes"])  AS_IF([test "x$enable_neon" = "xyes"], [ diff --git a/gtk/soundout/alsaout.c b/gtk/soundout/alsaout.c deleted file mode 100644 index 5c5e667..0000000 --- a/gtk/soundout/alsaout.c +++ /dev/null @@ -1,152 +0,0 @@ -#include "alsaout.h" -#include <stdbool.h> -#include <stdatomic.h> -#include <stdlib.h> -#include <sys/eventfd.h> -#include <pthread.h> -#include <unistd.h> -#include <poll.h> -#include <asoundlib.h> - -enum { -  BUF_FRAMES = 1024, -}; - -struct alsaout_state { -  struct sound_state ss; -  sound_callback cbfunc; -  void *userptr; -  snd_pcm_t *apcm; -  int fd_event; -  int fds_space; -  struct pollfd *fds; -  bool paused; -  bool terminate; -  atomic_flag cb_flag; -  bool thread_valid; -  pthread_t alsa_thread; -  int16_t buf[BUF_FRAMES*2]; -}; - -static void *alsaout_thread(void *ptr) { -  struct alsaout_state *as = ptr; -  for (;;) { -    as->fds[0] = (struct pollfd) { -      .fd = as->fd_event, -      .events = POLLIN, -    }; -    int fd_cnt = 1; -    fd_cnt += snd_pcm_poll_descriptors( -        as->apcm, as->fds + 1, as->fds_space - 1 -    ); -    int err = poll(as->fds, fd_cnt, -1); -    if (err <= 0) { -      continue; -    } -    if (as->terminate) return 0; -    if (as->fds[0].revents) { -      uint64_t eventdata; -      read(as->fd_event, &eventdata, sizeof(eventdata)); -    } -    unsigned short event; -    if (snd_pcm_poll_descriptors_revents( -        as->apcm, as->fds + 1, fd_cnt - 1, &event) < 0) continue; -    if (!event) continue; -    snd_pcm_sframes_t frames = snd_pcm_avail_update(as->apcm); -    if (frames <= 0) continue; -    while (frames) { -      snd_pcm_sframes_t genframes = frames; -      if (genframes > BUF_FRAMES) genframes = BUF_FRAMES; -      while (atomic_flag_test_and_set_explicit( -          &as->cb_flag, memory_order_acquire)); -      if (as->paused) { -        atomic_flag_clear_explicit(&as->cb_flag, memory_order_release); -        break; -      } -      as->cbfunc(as->userptr, as->buf, genframes); -      atomic_flag_clear_explicit(&as->cb_flag, memory_order_release); -      frames -= genframes; -      if (snd_pcm_state(as->apcm) == SND_PCM_STATE_XRUN) { -        err = snd_pcm_prepare(as->apcm); -      } -      snd_pcm_sframes_t written = snd_pcm_writei(as->apcm, as->buf, genframes); -      if (written < 0) { -        snd_pcm_prepare(as->apcm); -      } -    } -  } -} - -static void alsaout_pause(struct sound_state *ss, int pause, int flush) { -  struct alsaout_state *as = (struct alsaout_state *)ss; -   -  while (atomic_flag_test_and_set_explicit( -      &as->cb_flag, memory_order_acquire)); -  as->paused = pause; -  snd_pcm_pause(as->apcm, pause); -  atomic_flag_clear_explicit(&as->cb_flag, memory_order_release); -  uint64_t event = 1; -  write(as->fd_event, &event, sizeof(event)); -} - -static void alsaout_free(struct sound_state *ss) { -  if (!ss) return; -  struct alsaout_state *as = (struct alsaout_state *)ss; -  if (as->thread_valid) { -    as->terminate = true; -    uint64_t event = 1; -    write(as->fd_event, &event, sizeof(event)); -    pthread_join(as->alsa_thread, 0); -  } -  if (as->fd_event != -1) { -    close(as->fd_event); -  } -  if (as->fds) free(as->fds); -  if (as->apcm) { -    snd_pcm_close(as->apcm); -  } -  free(as); -} - -struct sound_state *alsaout_init( -  const char *clientname, unsigned srate, -  sound_callback cbfunc, void *userptr) { -  (void)clientname; -  struct alsaout_state *as = malloc(sizeof(*as)); -  if (!as) goto err; -  *as = (struct alsaout_state) { -    .ss = { -      .pause = alsaout_pause, -      .free = alsaout_free, -      .apiname = "ALSA", -    }, -    .cbfunc = cbfunc, -    .userptr = userptr, -    .fd_event = -1, -    .cb_flag = ATOMIC_FLAG_INIT, -    .paused = true, -  }; -  if (snd_pcm_open(&as->apcm, "default", SND_PCM_STREAM_PLAYBACK, 0)) { -    goto err; -  } -  as->fd_event = eventfd(0, EFD_CLOEXEC); -  if (as->fd_event < 0) goto err; -  as->fds_space = snd_pcm_poll_descriptors_count(as->apcm) + 1; -  as->fds = malloc(sizeof(*as->fds) * as->fds_space); -  if (!as->fds) goto err; -  if (snd_pcm_set_params( -      as->apcm, -      SND_PCM_FORMAT_S16, SND_PCM_ACCESS_RW_INTERLEAVED, 2, srate, 1, -      1000*1000/60)) { -    goto err; -  } -  if (pthread_create(&as->alsa_thread, 0, alsaout_thread, as)) { -    goto err; -  } -  as->thread_valid = true; -  return as; - -err: -  alsaout_free(&as->ss); -  return 0; -} diff --git a/gtk/soundout/alsaout.h b/gtk/soundout/alsaout.h deleted file mode 100644 index cd79c27..0000000 --- a/gtk/soundout/alsaout.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef MYON_ALSAOUT_H_INCLUDED -#define MYON_ALSAOUT_H_INCLUDED - -#include "soundout.h" - -struct sound_state *alsaout_init(const char *clientname, unsigned srate, sound_callback cbfunc, void *userptr); - -#endif // MYON_ALSAOUT_H_INCLUDED - diff --git a/gtk/soundout/jackout.c b/gtk/soundout/jackout.c deleted file mode 100644 index 54e7f16..0000000 --- a/gtk/soundout/jackout.c +++ /dev/null @@ -1,127 +0,0 @@ -#include "jackout.h" - -#include <stdbool.h> -#include <stdlib.h> -#include <jack/jack.h> -#include <soxr.h> - -typedef jack_default_audio_sample_t sample_t; - -enum { -  RFRAMES = 1024, -  JFRAMES = 2048, -}; - -struct jackout_state { -  struct sound_state ss; -  sound_callback cbfunc; -  void *userptr; -  jack_client_t *jc; -  jack_port_t *jp[2]; -  soxr_t soxr; -  bool paused; -  int16_t rbuf[RFRAMES*2]; -  float jbuf[JFRAMES*2]; -}; - -static size_t soxr_cb(void *ptr, soxr_in_t *data, size_t nframes) { -  struct jackout_state *js = ptr; -  if (nframes > RFRAMES) nframes = RFRAMES; -  for (size_t i = 0; i < RFRAMES*2; i++) { -    js->rbuf[i] = 0; -  } -  js->cbfunc(js->userptr, js->rbuf, nframes); -  *data = js->rbuf; -  return nframes; -} - -static int jack_cb(jack_nframes_t nframes, void *arg) { -  struct jackout_state *js = arg; -  sample_t *out[2]; -  for (int i = 0; i < 2; i++) out[i] = jack_port_get_buffer(js->jp[i], nframes); -  jack_nframes_t outi = 0; -  while (nframes) { -    jack_nframes_t pframes = nframes < JFRAMES ? nframes : JFRAMES; -    pframes = soxr_output(js->soxr, js->jbuf, pframes); -    for (jack_nframes_t j = 0; j < pframes; j++) { -      out[0][outi] = js->jbuf[j*2+0]; -      out[1][outi] = js->jbuf[j*2+1]; -      outi++; -    } -    nframes -= pframes; -  } -  return 0; -} - -static void jackout_pause(struct sound_state *ss, int pause, int flush) { -  struct jackout_state *js = (struct jackout_state *)ss; -  // TODO -  if (js->paused && !pause) { -    if (flush) { -      soxr_clear(js->soxr); -      soxr_set_input_fn(js->soxr, soxr_cb, js, RFRAMES); -    } -    jack_activate(js->jc); -    jack_connect(js->jc, jack_port_name(js->jp[0]), "system:playback_1"); -    jack_connect(js->jc, jack_port_name(js->jp[1]), "system:playback_2"); -  } else if (!js->paused && pause) { -    jack_deactivate(js->jc); -  } -  js->paused = pause; -} - -static void jackout_free(struct sound_state *ss) { -  struct jackout_state *js = (struct jackout_state *)ss; -  if (js) { -    if (js->jc) { -      for (int i = 0; i < 2; i++) { -        if (js->jp[i]) jack_port_unregister(js->jc, js->jp[i]); -      } -      jack_client_close(js->jc); -    } -    if (js->soxr) soxr_delete(js->soxr); -    free(js); -  } -} - -struct sound_state *jackout_init( -  const char *clientname, unsigned srate, -  sound_callback cbfunc, void *userptr) { -  struct jackout_state *js = malloc(sizeof(*js)); -  if (!js) goto err; -  *js = (struct jackout_state){ -    .ss = { -      .pause = jackout_pause, -      .free = jackout_free, -      .apiname = "JACK Audio", -    }, -    .cbfunc = cbfunc, -    .userptr = userptr, -    .paused = true, -  }; -  js->jc = jack_client_open(clientname, 0, 0); -  if (!js->jc) goto err; -  for (int i = 0; i < 2; i++) { -    js->jp[i] = jack_port_register( -        js->jc, i ? "right" : "left", JACK_DEFAULT_AUDIO_TYPE, -        JackPortIsOutput | JackPortIsTerminal, 0); -    if (!js->jp[i]) goto err; -  } -  soxr_io_spec_t iospec = { -    .itype = SOXR_INT16_I, -    .otype = SOXR_FLOAT32_I, -    .scale = 1.0, -  }; -  js->soxr = soxr_create( -      srate, jack_get_sample_rate(js->jc), -      2, 0, &iospec, 0, 0 -  ); -  if (!js->soxr) goto err; -  soxr_set_input_fn(js->soxr, soxr_cb, js, RFRAMES); -  if (jack_set_process_callback(js->jc, jack_cb, js)) goto err; - -  return &js->ss; -err: -  jackout_free(&js->ss); -  return 0; -} diff --git a/gtk/soundout/jackout.h b/gtk/soundout/jackout.h deleted file mode 100644 index 4b72f2e..0000000 --- a/gtk/soundout/jackout.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef MYON_JACKOUT_H_INCLUDED -#define MYON_JACKOUT_H_INCLUDED - -#include "soundout.h" - -struct sound_state *jackout_init(const char *clientname, unsigned srate, sound_callback cbfunc, void *userptr); - -#endif // MYON_JACKOUT_H_INCLUDED - diff --git a/gtk/soundout/ossout.c b/gtk/soundout/ossout.c deleted file mode 100644 index 1083f20..0000000 --- a/gtk/soundout/ossout.c +++ /dev/null @@ -1,8 +0,0 @@ -#include <sys/stat.h> -#include <fcntl.h> - -struct ossout_state { -  struct sound_state ss; -}; - -struct sound_state *ossout_init( diff --git a/gtk/soundout/pulseout.c b/gtk/soundout/pulseout.c deleted file mode 100644 index 9dbcd6c..0000000 --- a/gtk/soundout/pulseout.c +++ /dev/null @@ -1,133 +0,0 @@ -#include "pulseout.h" - -#include <stdbool.h> -#include <stdlib.h> -#include <pulse/thread-mainloop.h> -#include <pulse/stream.h> - -struct pulseout_state { -  struct sound_state ss; -  bool paused; -  bool flush; -  unsigned srate; -  sound_callback cbfunc; -  void *userptr; -  pa_threaded_mainloop *pa_tm; -  pa_context *pa_c; -  pa_stream *pa_s; -  bool pa_status_changed; -}; - -static void pulseout_pause(struct sound_state *ss, int pause, int flush) { -  //return; -  struct pulseout_state *ps = (struct pulseout_state *)ss; -  if (ps->paused != !!pause) { -    if (pause) { -      pa_threaded_mainloop_lock(ps->pa_tm); -    } -    ps->paused = pause; -    if (!pause) { -      if (flush) ps->flush = true; -      pa_threaded_mainloop_unlock(ps->pa_tm); -    } -  } -} - -static void pulseout_free(struct sound_state *ss) { -  struct pulseout_state *ps = (struct pulseout_state *)ss; -  if (ps) { -    if (ps->pa_tm) { -      if (ps->paused) pa_threaded_mainloop_unlock(ps->pa_tm); -      pa_threaded_mainloop_stop(ps->pa_tm); -      if (ps->pa_s) { -        pa_stream_disconnect(ps->pa_s); -        pa_stream_unref(ps->pa_s); -      } -      if (ps->pa_c) pa_context_unref(ps->pa_c); -      pa_threaded_mainloop_free(ps->pa_tm); -    } -    free(ps); -  } -} - -static void pulseout_cb(pa_stream *p, size_t bytes, void *userdata) { -  struct pulseout_state *ps = userdata; -  int16_t *buf; -  pa_stream_begin_write(p, (void **)&buf, &bytes); -  size_t nframes = bytes / (2 * sizeof(int16_t)); -  if (!ps->paused) { -    ps->cbfunc(ps->userptr, buf, nframes); -  } else { -    for (size_t i = 0; i < nframes; i++) { -      buf[i*2+0] = 0; -      buf[i*2+1] = 0; -    } -  } -  pa_seek_mode_t smode = -      ps->flush ? PA_SEEK_RELATIVE_ON_READ : PA_SEEK_RELATIVE; -  pa_stream_write(p, buf, nframes * 2 * sizeof(int16_t), 0, 0, smode); -  ps->flush = false; -} - -static void pa_c_cb(pa_context *pa_c, void *userdata) { -  struct pulseout_state *ps = userdata; -  ps->pa_status_changed = true; -  pa_threaded_mainloop_signal(ps->pa_tm, 0); -} - -struct sound_state *pulseout_init( -  const char *clientname, unsigned srate, -  sound_callback cbfunc, void *userptr) { -  struct pulseout_state *ps = malloc(sizeof(*ps)); -  if (!ps) goto err; -  *ps = (struct pulseout_state){ -    .ss = { -      .pause = pulseout_pause, -      .free = pulseout_free, -      .apiname = "PulseAudio", -    }, -    .cbfunc = cbfunc, -    .userptr = userptr, -    .paused = false, -    .srate = srate, -  }; -  ps->pa_tm = pa_threaded_mainloop_new(); -  if (!ps->pa_tm) goto err; -  ps->pa_c = pa_context_new( -      pa_threaded_mainloop_get_api(ps->pa_tm), clientname -  ); -  if (!ps->pa_c) goto err; -  if (pa_context_connect(ps->pa_c, 0, 0, 0) < 0) goto err; -  pa_context_set_state_callback(ps->pa_c, pa_c_cb, ps); -  if (pa_threaded_mainloop_start(ps->pa_tm) < 0) goto err; -  pa_threaded_mainloop_lock(ps->pa_tm); -  ps->paused = true; -  for (;;) { -    while (!ps->pa_status_changed) { -      pa_threaded_mainloop_wait(ps->pa_tm); -    } -    ps->pa_status_changed = false; -    pa_context_state_t state = pa_context_get_state(ps->pa_c); -    if (state == PA_CONTEXT_CONNECTING || -        state == PA_CONTEXT_AUTHORIZING || -        state == PA_CONTEXT_SETTING_NAME) continue; -    else if (state == PA_CONTEXT_READY) break; -    else goto err; -  } -  pa_sample_spec ss = { -    .format = PA_SAMPLE_S16NE, -    .rate = ps->srate, -    .channels = 2, -  }; -  ps->pa_s = pa_stream_new( -      ps->pa_c, -      "stereoout", &ss, 0 -  ); -  if (!ps->pa_s) goto err; -  pa_stream_set_write_callback(ps->pa_s, pulseout_cb, ps); -  if (pa_stream_connect_playback(ps->pa_s, 0, 0, 0, 0, 0) < 0) goto err; -  return &ps->ss; -err: -  pulseout_free(&ps->ss); -  return 0; -} diff --git a/gtk/soundout/pulseout.h b/gtk/soundout/pulseout.h deleted file mode 100644 index d9fbb20..0000000 --- a/gtk/soundout/pulseout.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef MYON_PULSEOUT_H_INCLUDED -#define MYON_PULSEOUT_H_INCLUDED - -#include "soundout.h" - -struct sound_state *pulseout_init(const char *clientname, unsigned srate, sound_callback cbfunc, void *userptr); - -#endif // MYON_PULSEOUT_H_INCLUDED - diff --git a/gtk/soundout/soundout.c b/gtk/soundout/soundout.c deleted file mode 100644 index 56134be..0000000 --- a/gtk/soundout/soundout.c +++ /dev/null @@ -1,14 +0,0 @@ -#include "soundout.h" -#include "jackout.h" -#include "pulseout.h" -#include "alsaout.h" - -struct sound_state *sound_init(const char *clientname, unsigned srate, sound_callback cbfunc, void *userptr) { -  struct sound_state *ss = 0; -  //ss = jackout_init(clientname, srate, cbfunc, userptr); -  if (ss) return ss; -  //ss = pulseout_init(clientname, srate, cbfunc, userptr); -  if (ss) return ss; -  ss = alsaout_init(clientname, srate, cbfunc, userptr); -  return ss; -} diff --git a/gtk/soundout/soundout.h b/gtk/soundout/soundout.h deleted file mode 100644 index aea926f..0000000 --- a/gtk/soundout/soundout.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef MYON_SOUNDOUT_H_INCLUDED -#define MYON_SOUNDOUT_H_INCLUDED - -#include <stdint.h> - -typedef void (*sound_callback)(void *userptr, int16_t *buf, unsigned frames); - -struct sound_state { -  void (*pause)(struct sound_state *state, int pause, int flush); -  void (*free)(struct sound_state *state); -  const char *apiname; -}; - -struct sound_state *sound_init(const char *clientname, unsigned srate, sound_callback cbfunc, void *userptr); - -#endif // MYON_SOUNDOUT_H_INCLUDED | 
