pkgsrc-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: pkg/51125 (firefox 46.0.1 doesn't build in NetBSD-current with oss option)



The following reply was made to PR pkg/51125; it has been noted by GNATS.

From: Roy Bixler <rcbixler%nyx.net@localhost>
To: gnats-bugs%NetBSD.org@localhost
Cc: 
Subject: Re: pkg/51125 (firefox 46.0.1 doesn't build in NetBSD-current with
 oss option)
Date: Sun, 8 May 2016 18:28:47 -0600

 --fdj2RfSjLxBAspz7
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 
 On Sun, May 08, 2016 at 10:36:38PM +0000, wiz%NetBSD.org@localhost wrote:
 > Synopsis: firefox 46.0.1 doesn't build in NetBSD-current with oss option
 > 
 > Responsible-Changed-From-To: pkg-manager->ryoon
 > Responsible-Changed-By: wiz%NetBSD.org@localhost
 > Responsible-Changed-When: Sun, 08 May 2016 22:36:38 +0000
 > Responsible-Changed-Why:
 > Over to maintainer.
 
 Courtesy of Ian Leroux, attached patch from Onno van der Linden does
 the trick. I put it in the patches subdirectory, run "make mps", "make
 clean" and then "make install" works.  The resulting binary seems to
 work fine, including with video and sound.
 
 -- 
 Roy Bixler <rcbixler%nyx.net@localhost>
 "The fundamental principle of science, the definition almost, is this: the
 sole test of the validity of any idea is experiment."
 -- Richard P. Feynman
 
 --fdj2RfSjLxBAspz7
 Content-Type: text/x-csrc; charset=iso-8859-1
 Content-Disposition: attachment; filename="patch-media_libcubeb_src_cubeb__oss.c"
 Content-Transfer-Encoding: 8bit
 
 diff --git media/libcubeb/src/cubeb_oss.c media/libcubeb/src/cubeb_oss.c
 new file mode 100644
 index 0000000..5e38e27
 --- /dev/null
 +++ media/libcubeb/src/cubeb_oss.c
 @@ -0,0 +1,412 @@
 +/*
 + * Copyright © 2014 Mozilla Foundation
 + *
 + * This program is made available under an ISC-style license.  See the
 + * accompanying file LICENSE for details.
 + */
 +#if defined(HAVE_SYS_SOUNDCARD_H)
 +#include <sys/soundcard.h>
 +#else
 +#include <soundcard.h>
 +#endif
 +#include <unistd.h>
 +#include <stdlib.h>
 +#include <sys/types.h>
 +#include <sys/stat.h>
 +#include <fcntl.h>
 +#include <sys/ioctl.h>
 +#include <errno.h>
 +#include <pthread.h>
 +#include <stdio.h>
 +#include <assert.h>
 +
 +#include "cubeb/cubeb.h"
 +#include "cubeb-internal.h"
 +
 +#ifndef CUBEB_OSS_DEFAULT_OUTPUT
 +#define CUBEB_OSS_DEFAULT_OUTPUT "/dev/dsp"
 +#endif
 +
 +#define OSS_BUFFER_SIZE 1024
 +
 +struct cubeb {
 +  struct cubeb_ops const * ops;
 +};
 +
 +struct cubeb_stream {
 +  cubeb * context;
 +
 +  cubeb_data_callback data_callback;
 +  cubeb_state_callback state_callback;
 +  void * user_ptr;
 +  float volume;
 +  float panning;
 +
 +  pthread_mutex_t state_mutex;
 +  pthread_cond_t state_cond;
 +
 +  int running;
 +  int stopped;
 +  int floating;
 +
 +  /* These two vars are needed to support old versions of OSS */
 +  unsigned int position_bytes;
 +  unsigned int last_position_bytes;
 +
 +  uint64_t written_frags; /* The number of fragments written to /dev/dsp */
 +  uint64_t missed_frags; /* fragments output with stopped stream */
 +
 +  cubeb_stream_params params;
 +  int fd;
 +  pthread_t th;
 +};
 +
 +static struct cubeb_ops const oss_ops;
 +
 +int oss_init(cubeb ** context, char const * context_name)
 +{
 +  cubeb* ctx = (cubeb*)malloc(sizeof(cubeb));
 +  ctx->ops = &oss_ops;
 +  *context = ctx;
 +  return CUBEB_OK;
 +}
 +
 +static void oss_destroy(cubeb *ctx)
 +{
 +  free(ctx);
 +}
 +
 +static char const * oss_get_backend_id(cubeb * context)
 +{
 +  static char oss_name[] = "oss";
 +  return oss_name;
 +}
 +
 +static int oss_get_max_channel_count(cubeb * ctx, uint32_t * max_channels)
 +{
 +  *max_channels = 2; /* Let's support only stereo for now */
 +  return CUBEB_OK;
 +}
 +
 +static int oss_get_min_latency(cubeb * context, cubeb_stream_params params,
 +                               uint32_t * latency_ms)
 +{
 +  /* 40ms is a big enough number to work ok */
 +  *latency_ms = 40;
 +  return CUBEB_OK;
 +}
 +
 +static int oss_get_preferred_sample_rate(cubeb *context, uint32_t * rate)
 +{
 +  /* 48000 seems a prefered choice for most audio devices
 +   * and a good choice for OSS */
 +  *rate = 48000;
 +  return CUBEB_OK;
 +}
 +
 +static void run_state_callback(cubeb_stream *stream, cubeb_state state)
 +{
 +  if (stream->state_callback) {
 +    stream->state_callback(stream, stream->user_ptr, state);
 +  }
 +}
 +
 +static long run_data_callback(cubeb_stream *stream, void *buffer, long nframes)
 +{
 +  long got = 0;
 +  pthread_mutex_lock(&stream->state_mutex);
 +  if (stream->data_callback && stream->running && !stream->stopped) {
 +    pthread_mutex_unlock(&stream->state_mutex);
 +    got = stream->data_callback(stream, stream->user_ptr, NULL, buffer, nframes);
 +  } else {
 +    pthread_mutex_unlock(&stream->state_mutex);
 +  }
 +  return got;
 +}
 +
 +static void apply_volume(int16_t* buffer, unsigned int n,
 +                         float volume, float panning)
 +{
 +  float left = volume;
 +  float right = volume;
 +  unsigned int i;
 +  int pan[2];
 +  if (panning<0) {
 +    right *= (1+panning);
 +  } else {
 +    left *= (1-panning);
 +  }
 +  pan[0] = 128.0*left;
 +  pan[1] = 128.0*right;
 +  for(i=0; i<n; i++){
 +    buffer[i] = ((int)buffer[i])*pan[i%2]/128;
 +  }
 +}
 +
 +static void *writer(void *stm)
 +{
 +  cubeb_stream* stream = (cubeb_stream*)stm;
 +  int16_t buffer[OSS_BUFFER_SIZE];
 +  float f_buffer[OSS_BUFFER_SIZE];
 +  int got;
 +  unsigned long i;
 +  while (stream->running) {
 +    pthread_mutex_lock(&stream->state_mutex);
 +    if (stream->stopped) {
 +      pthread_mutex_unlock(&stream->state_mutex);
 +      run_state_callback(stream, CUBEB_STATE_STOPPED);
 +      pthread_mutex_lock(&stream->state_mutex);
 +      while (stream->stopped) {
 +        pthread_cond_wait(&stream->state_cond, &stream->state_mutex);
 +      }
 +      pthread_mutex_unlock(&stream->state_mutex);
 +      run_state_callback(stream, CUBEB_STATE_STARTED);
 +      continue;
 +    }
 +    pthread_mutex_unlock(&stream->state_mutex);
 +    if (stream->floating) {
 +      got = run_data_callback(stream, f_buffer,
 +                              OSS_BUFFER_SIZE/stream->params.channels);
 +      for (i=0; i<((unsigned long)got)*stream->params.channels; i++) {
 +          buffer[i] = f_buffer[i]*32767.0;
 +      }
 +    } else {
 +      got = run_data_callback(stream, buffer,
 +                              OSS_BUFFER_SIZE/stream->params.channels);
 +    }
 +    apply_volume(buffer, got*stream->params.channels,
 +                         stream->volume, stream->panning);
 +    if (got<0) {
 +      run_state_callback(stream, CUBEB_STATE_ERROR);
 +      break;
 +    }
 +    if (!got) {
 +      run_state_callback(stream, CUBEB_STATE_DRAINED);
 +    }
 +    if (got) {
 +      size_t i = 0;
 +      size_t s = got*stream->params.channels*sizeof(int16_t);
 +      while (i < s) {
 +        ssize_t n = write(stream->fd, ((char*)buffer) + i, s - i);
 +        if (n<=0) {
 +          run_state_callback(stream, CUBEB_STATE_ERROR);
 +          break;
 +        }
 +        i+=n;
 +      }
 +      stream->written_frags+=got;
 +    }
 +  }
 +  return NULL;
 +}
 +
 +static void oss_try_set_latency(cubeb_stream* stream, unsigned int latency)
 +{
 +  unsigned int latency_bytes, n_frag;
 +  int frag;
 +  /* fragment size of 1024 is a good choice with good chances to be accepted */
 +  unsigned int frag_size=1024;
 +  unsigned int frag_log=10; /* 2^frag_log = frag_size */
 +  latency_bytes =
 +    latency*stream->params.rate*stream->params.channels*sizeof(uint16_t)/1000;
 +  n_frag = latency_bytes>>frag_log;
 +  frag = (n_frag<<16) | frag_log;
 +  /* Even if this fails we wish to continue, not checking for errors */
 +  ioctl(stream->fd, SNDCTL_DSP_SETFRAGMENT, &frag);
 +}
 +
 +static int oss_stream_init(cubeb * context, cubeb_stream ** stm,
 +                           char const * stream_name,
 +                           cubeb_devid input_device,
 +                           cubeb_stream_params * input_stream_params,
 +                           cubeb_devid output_device,
 +                           cubeb_stream_params * output_stream_params,
 +                           unsigned int latency,
 +                           cubeb_data_callback data_callback,
 +                           cubeb_state_callback state_callback, void * user_ptr)
 +{
 +  cubeb_stream* stream = (cubeb_stream*)malloc(sizeof(cubeb_stream));
 +  stream->context = context;
 +  stream->data_callback = data_callback;
 +  stream->state_callback = state_callback;
 +  stream->user_ptr = user_ptr;
 +
 +  assert(!input_stream_params && "not supported.");
 +  if (input_device || output_device) {
 +    /* Device selection not yet implemented. */
 +    return CUBEB_ERROR_DEVICE_UNAVAILABLE;
 +  }
 +
 +  if ((stream->fd = open(CUBEB_OSS_DEFAULT_OUTPUT, O_WRONLY)) == -1) {
 +    free(stream);
 +    return CUBEB_ERROR;
 +  }
 +#define SET(what, to) do { unsigned int i = to; \
 +    int j = ioctl(stream->fd, what, &i); \
 +    if (j == -1 || i != to) { \
 +      close(stream->fd); \
 +      free(stream); \
 +      return CUBEB_ERROR_INVALID_FORMAT; } } while (0)
 +
 +  stream->params = *output_stream_params;
 +  stream->volume = 1.0;
 +  stream->panning = 0.0;
 +
 +  oss_try_set_latency(stream, latency); 
 +
 +  stream->floating = 0;
 +  SET(SNDCTL_DSP_CHANNELS, output_stream_params->channels);
 +  SET(SNDCTL_DSP_SPEED, output_stream_params->rate);
 +  switch (output_stream_params->format) {
 +    case CUBEB_SAMPLE_S16LE:
 +      SET(SNDCTL_DSP_SETFMT, AFMT_S16_LE);
 +    break;
 +    case CUBEB_SAMPLE_S16BE:
 +      SET(SNDCTL_DSP_SETFMT, AFMT_S16_BE);
 +    break;
 +    case CUBEB_SAMPLE_FLOAT32LE:
 +      SET(SNDCTL_DSP_SETFMT, AFMT_S16_NE);
 +      stream->floating = 1;
 +    break;
 +    default:
 +      close(stream->fd);
 +      free(stream);
 +      return CUBEB_ERROR;
 +  }
 +
 +
 +  pthread_mutex_init(&stream->state_mutex, NULL);
 +  pthread_cond_init(&stream->state_cond, NULL);
 +
 +  stream->running = 1;
 +  stream->stopped = 1;
 +  stream->position_bytes = 0;
 +  stream->last_position_bytes = 0;
 +  stream->written_frags = 0;
 +  stream->missed_frags = 0;
 +
 +  pthread_create(&stream->th, NULL, writer, (void*)stream);
 +
 +  *stm = stream;
 +
 +  return CUBEB_OK;
 +}
 +
 +static void oss_stream_destroy(cubeb_stream * stream)
 +{
 +  pthread_mutex_lock(&stream->state_mutex);
 +
 +  stream->running = 0;
 +  stream->stopped = 0;
 +  pthread_cond_signal(&stream->state_cond);
 +
 +  pthread_mutex_unlock(&stream->state_mutex);
 +
 +  pthread_join(stream->th, NULL);
 +
 +  pthread_mutex_destroy(&stream->state_mutex);
 +  pthread_cond_destroy(&stream->state_cond);
 +  close(stream->fd);
 +  free(stream);
 +}
 +
 +static int oss_stream_get_latency(cubeb_stream * stream, uint32_t * latency)
 +{
 +  if (ioctl(stream->fd, SNDCTL_DSP_GETODELAY, latency)==-1) {
 +    return CUBEB_ERROR;
 +  }
 +  /* Convert latency from bytes to frames */
 +  *latency /= stream->params.channels*sizeof(int16_t);
 +  return CUBEB_OK;
 +}
 +
 +
 +static int oss_stream_current_optr(cubeb_stream * stream, uint64_t * position)
 +{
 +  count_info ci;
 +  /* Unfortunately, this ioctl is only available in OSS 4.x */
 +#ifdef SNDCTL_DSP_CURRENT_OPTR
 +  oss_count_t count;
 +  if (ioctl(stream->fd, SNDCTL_DSP_CURRENT_OPTR, &count) != -1) {
 +    *position = count.samples;// + count.fifo_samples;
 +    return CUBEB_OK;
 +  }
 +#endif
 +  /* Fall back to this ioctl in case the previous one fails */
 +  if (ioctl(stream->fd, SNDCTL_DSP_GETOPTR, &ci) == -1) {
 +    return CUBEB_ERROR;
 +  }
 +  /* ci.bytes is only 32 bit and will start to wrap after arithmetic overflow */
 +  stream->position_bytes += ci.bytes - stream->last_position_bytes;
 +  stream->last_position_bytes = ci.bytes;
 +  *position = stream->position_bytes/stream->params.channels/sizeof(int16_t);
 +  return CUBEB_OK;
 +}
 +
 +static int oss_stream_get_position(cubeb_stream * stream, uint64_t * position)
 +{
 +  if ( oss_stream_current_optr(stream, position) == CUBEB_OK ){
 +    *position -= stream->missed_frags;
 +    return CUBEB_OK;
 +  }
 +  /* If no correct method to get position works we resort to this */
 +  *position = stream->written_frags;
 +  return CUBEB_OK;
 +}
 +
 +
 +static int oss_stream_start(cubeb_stream * stream)
 +{
 +  pthread_mutex_lock(&stream->state_mutex);
 +  if (stream->stopped) {
 +    uint64_t ptr;
 +    oss_stream_current_optr(stream, &ptr);
 +    stream->missed_frags = ptr - stream->written_frags;
 +    stream->stopped = 0;
 +    pthread_cond_signal(&stream->state_cond);
 +  }
 +  pthread_mutex_unlock(&stream->state_mutex);
 +  return CUBEB_OK;
 +}
 +
 +static int oss_stream_stop(cubeb_stream * stream)
 +{
 +  pthread_mutex_lock(&stream->state_mutex);
 +  stream->stopped = 1;
 +  pthread_mutex_unlock(&stream->state_mutex);
 +  return CUBEB_OK;
 +}
 +
 +int oss_stream_set_panning(cubeb_stream * stream, float panning)
 +{
 +  if (stream->params.channels == 2) {
 +    stream->panning=panning;
 +  }
 +  return CUBEB_OK;
 +}
 +
 +int oss_stream_set_volume(cubeb_stream * stream, float volume)
 +{
 +  stream->volume=volume;
 +  return CUBEB_OK;
 +}
 +
 +static struct cubeb_ops const oss_ops = {
 +  .init = oss_init,
 +  .get_backend_id = oss_get_backend_id,
 +  .get_max_channel_count = oss_get_max_channel_count,
 +  .get_min_latency = oss_get_min_latency,
 +  .get_preferred_sample_rate = oss_get_preferred_sample_rate,
 +  .destroy = oss_destroy,
 +  .stream_init = oss_stream_init,
 +  .stream_destroy = oss_stream_destroy,
 +  .stream_start = oss_stream_start,
 +  .stream_stop = oss_stream_stop,
 +  .stream_get_position = oss_stream_get_position,
 +  .stream_get_latency = oss_stream_get_latency,
 +  .stream_set_volume = oss_stream_set_volume,
 +  .stream_set_panning = oss_stream_set_panning,
 +  .stream_get_current_device = NULL,
 +  .stream_device_destroy = NULL,
 +  .stream_register_device_changed_callback = NULL
 +};
 
 --fdj2RfSjLxBAspz7--
 


Home | Main Index | Thread Index | Old Index