components/desktop/firefox/patches/firefox28-90-cubeb.patch
changeset 5255 cea0e462549a
equal deleted inserted replaced
5252:947514442d05 5255:cea0e462549a
       
     1 For SunAudio audio playback. We need to investigate whether we care about
       
     2 this or whether we are just going to support PulseAudio.
       
     3 
       
     4 --- mozilla-esr31/media/libcubeb/src/cubeb.c.orig	2015-06-04 17:42:52.252769663 -0700
       
     5 +++ mozilla-esr31/media/libcubeb/src/cubeb.c	2015-06-04 17:42:52.260965308 -0700
       
     6 @@ -54,6 +54,9 @@
       
     7  #if defined(USE_AUDIOTRACK)
       
     8  int audiotrack_init(cubeb ** context, char const * context_name);
       
     9  #endif
       
    10 +#if defined(USE_SUN)
       
    11 +int sunaudio_init(cubeb ** context, char const * context_name);
       
    12 +#endif
       
    13  
       
    14  int
       
    15  validate_stream_params(cubeb_stream_params stream_params)
       
    16 @@ -120,6 +123,9 @@
       
    17  #if defined(USE_AUDIOTRACK)
       
    18      audiotrack_init,
       
    19  #endif
       
    20 +#if defined(USE_SUN)
       
    21 +    sunaudio_init,
       
    22 +#endif
       
    23    };
       
    24    int i;
       
    25  
       
    26 --- mozilla-esr31/media/libcubeb/src/cubeb_sun.c.orig	1969-12-31 16:00:00.000000000 -0800
       
    27 +++ mozilla-esr31/media/libcubeb/src/cubeb_sun.c	2015-06-04 17:42:52.261184916 -0700
       
    28 @@ -0,0 +1,500 @@
       
    29 +/*
       
    30 + * Copyright (c) 2013 Ginn Chen <[email protected]>
       
    31 + *
       
    32 + * This program is made available under an ISC-style license.  See the
       
    33 + * accompanying file LICENSE for details.
       
    34 + */
       
    35 +#include <poll.h>
       
    36 +#include <pthread.h>
       
    37 +#include <stdlib.h>
       
    38 +#include <stdio.h>
       
    39 +#include <errno.h>
       
    40 +#include <fcntl.h>
       
    41 +#include <sys/audio.h>
       
    42 +#include <sys/stat.h>
       
    43 +#include <unistd.h>
       
    44 +#include <sys/stropts.h>
       
    45 +#include "cubeb/cubeb.h"
       
    46 +#include "cubeb-internal.h"
       
    47 +
       
    48 +/* Macros copied from audio_oss.h */
       
    49 +/*
       
    50 + * CDDL HEADER START
       
    51 + *
       
    52 + * The contents of this file are subject to the terms of the
       
    53 + * Common Development and Distribution License (the "License").
       
    54 + * You may not use this file except in compliance with the License.
       
    55 + *
       
    56 + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
       
    57 + * or http://www.opensolaris.org/os/licensing.
       
    58 + * See the License for the specific language governing permissions
       
    59 + * and limitations under the License.
       
    60 + *
       
    61 + * When distributing Covered Code, include this CDDL HEADER in each
       
    62 + * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
       
    63 + * If applicable, add the following below this CDDL HEADER, with the
       
    64 + * fields enclosed by brackets "[]" replaced with your own identifying
       
    65 + * information: Portions Copyright [yyyy] [name of copyright owner]
       
    66 + *
       
    67 + * CDDL HEADER END
       
    68 + */
       
    69 +/*
       
    70 + * Copyright (C) 4Front Technologies 1996-2008.
       
    71 + *
       
    72 + * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
       
    73 + * Use is subject to license terms.
       
    74 + */
       
    75 +#define OSSIOCPARM_MASK 0x1fff          /* parameters must be < 8192 bytes */
       
    76 +#define OSSIOC_VOID     0x00000000      /* no parameters */
       
    77 +#define OSSIOC_OUT      0x20000000      /* copy out parameters */
       
    78 +#define OSSIOC_IN       0x40000000      /* copy in parameters */
       
    79 +#define OSSIOC_INOUT    (OSSIOC_IN|OSSIOC_OUT)
       
    80 +#define OSSIOC_SZ(t)    ((sizeof (t) & OSSIOCPARM_MASK) << 16)
       
    81 +#define __OSSIO(x, y)           ((int)(OSSIOC_VOID|(x<<8)|y))
       
    82 +#define __OSSIOR(x, y, t)       ((int)(OSSIOC_OUT|OSSIOC_SZ(t)|(x<<8)|y))
       
    83 +#define __OSSIOWR(x, y, t)      ((int)(OSSIOC_INOUT|OSSIOC_SZ(t)|(x<<8)|y))
       
    84 +#define SNDCTL_DSP_SPEED        __OSSIOWR('P', 2, int)
       
    85 +#define SNDCTL_DSP_CHANNELS     __OSSIOWR('P', 6, int)
       
    86 +#define SNDCTL_DSP_SETFMT       __OSSIOWR('P', 5, int)  /* Selects ONE fmt */
       
    87 +#define SNDCTL_DSP_GETODELAY    __OSSIOR('P', 23, int)
       
    88 +#define SNDCTL_DSP_HALT_OUTPUT  __OSSIO('P', 34)
       
    89 +#define AFMT_S16_LE     0x00000010
       
    90 +#define AFMT_S16_BE     0x00000020
       
    91 +
       
    92 +#if defined(WORDS_BIGENDIAN) || defined(__BIG_ENDIAN__)
       
    93 +#define AFMT_S16_NE    AFMT_S16_BE
       
    94 +#else
       
    95 +#define AFMT_S16_NE    AFMT_S16_LE
       
    96 +#endif
       
    97 +
       
    98 +#define DEFAULT_AUDIO_DEVICE "/dev/audio"
       
    99 +#define DEFAULT_DSP_DEVICE   "/dev/dsp"
       
   100 +
       
   101 +#define BUF_SIZE_MS 10
       
   102 +
       
   103 +#if defined(CUBEB_SUNAUDIO_DEBUG)
       
   104 +#define DPR(...) fprintf(stderr, __VA_ARGS__);
       
   105 +#else
       
   106 +#define DPR(...) do {} while(0)
       
   107 +#endif
       
   108 +
       
   109 +static struct cubeb_ops const sunaudio_ops;
       
   110 +
       
   111 +struct cubeb {
       
   112 +  struct cubeb_ops const * ops;
       
   113 +};
       
   114 +
       
   115 +struct cubeb_stream {
       
   116 +  cubeb * context;
       
   117 +  pthread_t th;			  /* to run real-time audio i/o */
       
   118 +  pthread_mutex_t mutex;	  /* protects fd and frm_played */
       
   119 +  int fd;			  /* link us to sunaudio */
       
   120 +  int active;			  /* cubec_start() called */
       
   121 +  int conv;			  /* need float->s16 conversion */
       
   122 +  int using_oss;
       
   123 +  unsigned char *buf;		  /* data is prepared here */
       
   124 +  unsigned int rate;
       
   125 +  unsigned int n_channles;
       
   126 +  unsigned int bytes_per_ch;
       
   127 +  unsigned int n_frm;
       
   128 +  unsigned int buffer_size;
       
   129 +  int64_t frm_played;
       
   130 +  cubeb_data_callback data_cb;    /* cb to preapare data */
       
   131 +  cubeb_state_callback state_cb;  /* cb to notify about state changes */
       
   132 +  void *arg;			  /* user arg to {data,state}_cb */
       
   133 +};
       
   134 +
       
   135 +static void
       
   136 +float_to_s16(void *ptr, long nsamp)
       
   137 +{
       
   138 +  int16_t *dst = ptr;
       
   139 +  float *src = ptr;
       
   140 +
       
   141 +  while (nsamp-- > 0)
       
   142 +    *(dst++) = *(src++) * 32767;
       
   143 +}
       
   144 +
       
   145 +static void *
       
   146 +sunaudio_mainloop(void *arg)
       
   147 +{
       
   148 +  struct cubeb_stream *s = arg;
       
   149 +  int state;
       
   150 +
       
   151 +  DPR("sunaudio_mainloop()\n");
       
   152 +
       
   153 +  s->state_cb(s, s->arg, CUBEB_STATE_STARTED);
       
   154 +
       
   155 +  pthread_mutex_lock(&s->mutex);
       
   156 +  DPR("sunaudio_mainloop(), started\n");
       
   157 +
       
   158 +  for (;;) {
       
   159 +    if (!s->active) {
       
   160 +      DPR("sunaudio_mainloop() stopped\n");
       
   161 +      state = CUBEB_STATE_STOPPED;
       
   162 +      break;
       
   163 +    }
       
   164 +
       
   165 +    if (!s->using_oss) {
       
   166 +      audio_info_t info;
       
   167 +      ioctl(s->fd, AUDIO_GETINFO, &info);
       
   168 +      if (s->frm_played > info.play.samples + 3 * s->n_frm) {
       
   169 +        pthread_mutex_unlock(&s->mutex);
       
   170 +        struct timespec ts = {0, 10000}; // 10 ms
       
   171 +        nanosleep(&ts, NULL);
       
   172 +        pthread_mutex_lock(&s->mutex);
       
   173 +        continue;
       
   174 +      }
       
   175 +    }
       
   176 +
       
   177 +    pthread_mutex_unlock(&s->mutex);
       
   178 +    unsigned int got = s->data_cb(s, s->arg, s->buf, s->n_frm);
       
   179 +    DPR("sunaudio_mainloop() ask %d got %d\n", s->n_frm, got);
       
   180 +    pthread_mutex_lock(&s->mutex);
       
   181 +
       
   182 +    if (got < 0) {
       
   183 +      DPR("sunaudio_mainloop() cb err\n");
       
   184 +      state = CUBEB_STATE_ERROR;
       
   185 +      break;
       
   186 +    }
       
   187 +
       
   188 +    if (s->conv) {
       
   189 +      float_to_s16(s->buf, got * s->n_channles);
       
   190 +    }
       
   191 +
       
   192 +    unsigned int avail = got * 2 * s->n_channles; // coverted to s16
       
   193 +    unsigned int pos = 0;
       
   194 +
       
   195 +    while (avail > 0 && s->active) {
       
   196 +      int written = write(s->fd, s->buf + pos, avail);
       
   197 +      if (written == -1) {
       
   198 +        if (errno != EINTR && errno != EWOULDBLOCK) {
       
   199 +          DPR("sunaudio_mainloop() write err\n");
       
   200 +          state = CUBEB_STATE_ERROR;
       
   201 +          break;
       
   202 +        }
       
   203 +        pthread_mutex_unlock(&s->mutex);
       
   204 +        struct timespec ts = {0, 10000}; // 10 ms
       
   205 +        nanosleep(&ts, NULL);
       
   206 +        pthread_mutex_lock(&s->mutex);
       
   207 +      } else {
       
   208 +        pos += written;
       
   209 +        DPR("sunaudio_mainloop() write %d pos %d\n", written, pos);
       
   210 +        s->frm_played += written / 2 / s->n_channles;
       
   211 +        avail -= written;
       
   212 +      }
       
   213 +    }
       
   214 +
       
   215 +    if ((got  < s->n_frm)) {
       
   216 +      DPR("sunaudio_mainloop() drained\n");
       
   217 +      state = CUBEB_STATE_DRAINED;
       
   218 +      break;
       
   219 +    }
       
   220 +  }
       
   221 +
       
   222 +  pthread_mutex_unlock(&s->mutex);
       
   223 +  s->state_cb(s, s->arg, state);
       
   224 +
       
   225 +  return NULL;
       
   226 +}
       
   227 +
       
   228 +/*static*/ int
       
   229 +sunaudio_init(cubeb **context, char const *context_name)
       
   230 +{
       
   231 +  DPR("sunaudio_init(%s)\n", context_name);
       
   232 +  *context = malloc(sizeof(*context));
       
   233 +  (*context)->ops = &sunaudio_ops;
       
   234 +  (void)context_name;
       
   235 +  return CUBEB_OK;
       
   236 +}
       
   237 +
       
   238 +static char const *
       
   239 +sunaudio_get_backend_id(cubeb *context)
       
   240 +{
       
   241 +  return "sunaudio";
       
   242 +}
       
   243 +
       
   244 +static void
       
   245 +sunaudio_destroy(cubeb *context)
       
   246 +{
       
   247 +  DPR("sunaudio_destroy()\n");
       
   248 +  free(context);
       
   249 +}
       
   250 +
       
   251 +static int
       
   252 +sunaudio_stream_init(cubeb *context,
       
   253 +                  cubeb_stream **stream,
       
   254 +                  char const *stream_name,
       
   255 +                  cubeb_stream_params stream_params, unsigned int latency,
       
   256 +                  cubeb_data_callback data_callback,
       
   257 +                  cubeb_state_callback state_callback,
       
   258 +                  void *user_ptr)
       
   259 +{
       
   260 +  struct cubeb_stream *s;
       
   261 +  DPR("sunaudio_stream_init(%s)\n", stream_name);
       
   262 +  size_t size;
       
   263 +
       
   264 +  s = malloc(sizeof(struct cubeb_stream));
       
   265 +  if (s == NULL)
       
   266 +    return CUBEB_ERROR;
       
   267 +  s->context = context;
       
   268 +
       
   269 +  // If UTAUDIODEV is set, use it with Sun Audio interface
       
   270 +  char * sa_device_name = getenv("UTAUDIODEV");
       
   271 +  char * dsp_device_name = NULL;
       
   272 +  if (!sa_device_name) {
       
   273 +    dsp_device_name = getenv("AUDIODSP");
       
   274 +    if (!dsp_device_name) {
       
   275 +      dsp_device_name = DEFAULT_DSP_DEVICE;
       
   276 +    }
       
   277 +    sa_device_name = getenv("AUDIODEV");
       
   278 +    if (!sa_device_name) {
       
   279 +      sa_device_name = DEFAULT_AUDIO_DEVICE;
       
   280 +    }
       
   281 +  }
       
   282 +
       
   283 +  s->using_oss = 0;
       
   284 +  // Try to use OSS if available
       
   285 +  if (dsp_device_name) {
       
   286 +    s->fd = open(dsp_device_name, O_WRONLY | O_NONBLOCK);
       
   287 +    if (s->fd >= 0) {
       
   288 +      s->using_oss = 1;
       
   289 +    }
       
   290 +  }
       
   291 +
       
   292 +  // Try Sun Audio
       
   293 +  if (!s->using_oss) {
       
   294 +    s->fd = open(sa_device_name, O_WRONLY | O_NONBLOCK);
       
   295 +  }
       
   296 +
       
   297 +  if (s->fd < 0) {
       
   298 +    free(s);
       
   299 +    DPR("sunaudio_stream_init(), open() failed\n");
       
   300 +    return CUBEB_ERROR;
       
   301 +  }
       
   302 +
       
   303 +  if (s->using_oss) {
       
   304 +    if (ioctl(s->fd, SNDCTL_DSP_SPEED, &stream_params.rate) < 0) {
       
   305 +      DPR("ioctl SNDCTL_DSP_SPEED failed.\n");
       
   306 +      close(s->fd);
       
   307 +      free(s);
       
   308 +      return CUBEB_ERROR_INVALID_FORMAT;
       
   309 +    }
       
   310 +
       
   311 +    if (ioctl(s->fd, SNDCTL_DSP_CHANNELS, &stream_params.channels) < 0) {
       
   312 +      DPR("ioctl SNDCTL_DSP_CHANNELS failed.\n");
       
   313 +      close(s->fd);
       
   314 +      free(s);
       
   315 +      return CUBEB_ERROR_INVALID_FORMAT;
       
   316 +    }
       
   317 +
       
   318 +    int format = AFMT_S16_NE;
       
   319 +    if (ioctl(s->fd, SNDCTL_DSP_SETFMT, &format) < 0) {
       
   320 +      DPR("ioctl SNDCTL_DSP_SETFMT failed.\n");
       
   321 +      close(s->fd);
       
   322 +      free(s);
       
   323 +      return CUBEB_ERROR_INVALID_FORMAT;
       
   324 +    }
       
   325 +  } else {
       
   326 +    audio_info_t audio_info;
       
   327 +    AUDIO_INITINFO(&audio_info)
       
   328 +    audio_info.play.sample_rate = stream_params.rate;
       
   329 +    audio_info.play.channels = stream_params.channels;
       
   330 +    audio_info.play.encoding = AUDIO_ENCODING_LINEAR;
       
   331 +    audio_info.play.precision = 16;
       
   332 +    if (ioctl(s->fd, AUDIO_SETINFO, &audio_info) == -1) {
       
   333 +      DPR("ioctl AUDIO_SETINFO failed.\n");
       
   334 +      close(s->fd);
       
   335 +      free(s);
       
   336 +      return CUBEB_ERROR_INVALID_FORMAT;
       
   337 +    }
       
   338 +  }
       
   339 +
       
   340 +  s->conv = 0;
       
   341 +  switch (stream_params.format) {
       
   342 +    case CUBEB_SAMPLE_S16NE:
       
   343 +      s->bytes_per_ch = 2;
       
   344 +      break;
       
   345 +    case CUBEB_SAMPLE_FLOAT32NE:
       
   346 +      s->bytes_per_ch = 4;
       
   347 +      s->conv = 1;
       
   348 +      break;
       
   349 +    default:
       
   350 +      DPR("sunaudio_stream_init() unsupported format\n");
       
   351 +      close(s->fd);
       
   352 +      free(s);
       
   353 +      return CUBEB_ERROR_INVALID_FORMAT;
       
   354 +  }
       
   355 +
       
   356 +  s->active = 0;
       
   357 +  s->rate = stream_params.rate;
       
   358 +  s->n_channles = stream_params.channels;
       
   359 +  s->data_cb = data_callback;
       
   360 +  s->state_cb = state_callback;
       
   361 +  s->arg = user_ptr;
       
   362 +  if (pthread_mutex_init(&s->mutex, NULL) != 0) {
       
   363 +    free(s);
       
   364 +    return CUBEB_ERROR;
       
   365 +  }
       
   366 +  s->frm_played = 0;
       
   367 +  s->n_frm = s->rate * BUF_SIZE_MS / 1000;
       
   368 +  s->buffer_size = s->bytes_per_ch * s->n_channles * s->n_frm;
       
   369 +  s->buf = malloc(s->buffer_size);
       
   370 +  if (s->buf == NULL) {
       
   371 +    close(s->fd);
       
   372 +    free(s);
       
   373 +    return CUBEB_ERROR;
       
   374 +  }
       
   375 +
       
   376 +  *stream = s;
       
   377 +  DPR("sunaudio_stream_init() end, ok\n");
       
   378 +  return CUBEB_OK;
       
   379 +}
       
   380 +
       
   381 +static void
       
   382 +sunaudio_stream_destroy(cubeb_stream *s)
       
   383 +{
       
   384 +  DPR("sunaudio_stream_destroy()\n");
       
   385 +  if (s->fd > 0) {
       
   386 +    // Flush buffer
       
   387 +    if (s->using_oss) {
       
   388 +      ioctl(s->fd, SNDCTL_DSP_HALT_OUTPUT);
       
   389 +    } else {
       
   390 +      ioctl(s->fd, I_FLUSH);
       
   391 +    }
       
   392 +    close(s->fd);
       
   393 +  }
       
   394 +  free(s->buf);
       
   395 +  free(s);
       
   396 +}
       
   397 +
       
   398 +static int
       
   399 +sunaudio_stream_start(cubeb_stream *s)
       
   400 +{
       
   401 +  int err;
       
   402 +
       
   403 +  DPR("sunaudio_stream_start()\n");
       
   404 +  s->active = 1;
       
   405 +  err = pthread_create(&s->th, NULL, sunaudio_mainloop, s);
       
   406 +  if (err) {
       
   407 +    s->active = 0;
       
   408 +    return CUBEB_ERROR;
       
   409 +  }
       
   410 +  return CUBEB_OK;
       
   411 +}
       
   412 +
       
   413 +static int
       
   414 +sunaudio_stream_stop(cubeb_stream *s)
       
   415 +{
       
   416 +  void *dummy;
       
   417 +
       
   418 +  DPR("sunaudio_stream_stop()\n");
       
   419 +  if (s->active) {
       
   420 +    s->active = 0;
       
   421 +    pthread_join(s->th, &dummy);
       
   422 +  }
       
   423 +  return CUBEB_OK;
       
   424 +}
       
   425 +
       
   426 +static int
       
   427 +sunaudio_stream_get_position(cubeb_stream *s, uint64_t *p)
       
   428 +{
       
   429 +  int rv = CUBEB_OK;
       
   430 +  pthread_mutex_lock(&s->mutex);
       
   431 +  if (s->active && s->fd > 0) {
       
   432 +    if (s->using_oss) {
       
   433 +      int delay;
       
   434 +      ioctl(s->fd, SNDCTL_DSP_GETODELAY, &delay);
       
   435 +      int64_t t = s->frm_played - delay / s->n_channles / 2;
       
   436 +      if (t < 0) {
       
   437 +        *p = 0;
       
   438 +      } else {
       
   439 +        *p = t;
       
   440 +      }
       
   441 +    } else {
       
   442 +      audio_info_t info;
       
   443 +      ioctl(s->fd, AUDIO_GETINFO, &info);
       
   444 +      *p = info.play.samples;
       
   445 +    }
       
   446 +    DPR("sunaudio_stream_get_position() %lld\n", *p);
       
   447 +  } else {
       
   448 +    rv = CUBEB_ERROR;
       
   449 +  }
       
   450 +  pthread_mutex_unlock(&s->mutex);
       
   451 +  return rv;
       
   452 +}
       
   453 +
       
   454 +static int
       
   455 +sunaudio_get_max_channel_count(cubeb * ctx, uint32_t * max_channels)
       
   456 +{
       
   457 +  if (!ctx || !max_channels)
       
   458 +    return CUBEB_ERROR;
       
   459 +
       
   460 +  *max_channels = 2;
       
   461 +
       
   462 +  return CUBEB_OK;
       
   463 +}
       
   464 +
       
   465 +static int
       
   466 +sunaudio_get_preferred_sample_rate(cubeb * ctx, uint32_t * rate)
       
   467 +{
       
   468 +  if (!ctx || !rate)
       
   469 +    return CUBEB_ERROR;
       
   470 +
       
   471 +  // XXX Not yet implemented.
       
   472 +  *rate = 44100;
       
   473 +
       
   474 +  return CUBEB_OK;
       
   475 +}
       
   476 +
       
   477 +static int
       
   478 +sunaudio_get_min_latency(cubeb * ctx, cubeb_stream_params params, uint32_t * latency_ms)
       
   479 +{
       
   480 +  if (!ctx || !latency_ms)
       
   481 +    return CUBEB_ERROR;
       
   482 +
       
   483 +  // XXX Not yet implemented.
       
   484 +  *latency_ms = 20;
       
   485 +
       
   486 +  return CUBEB_OK;
       
   487 +}
       
   488 +
       
   489 +static int
       
   490 +sunaudio_stream_get_latency(cubeb_stream * s, uint32_t * latency)
       
   491 +{
       
   492 +  if (!s || !latency)
       
   493 +    return CUBEB_ERROR;
       
   494 +
       
   495 +  int rv = CUBEB_OK;
       
   496 +  pthread_mutex_lock(&s->mutex);
       
   497 +  if (s->active && s->fd > 0) {
       
   498 +    if (s->using_oss) {
       
   499 +      int delay;
       
   500 +      ioctl(s->fd, SNDCTL_DSP_GETODELAY, &delay);
       
   501 +      *latency = delay / s->n_channles / 2 / s->rate;
       
   502 +    } else {
       
   503 +      audio_info_t info;
       
   504 +      ioctl(s->fd, AUDIO_GETINFO, &info);
       
   505 +      *latency = (s->frm_played - info.play.samples) / s->rate;
       
   506 +    }
       
   507 +    DPR("sunaudio_stream_get_position() %lld\n", *p);
       
   508 +  } else {
       
   509 +    rv = CUBEB_ERROR;
       
   510 +  }
       
   511 +  pthread_mutex_unlock(&s->mutex);
       
   512 +  return rv;
       
   513 +}
       
   514 +
       
   515 +static struct cubeb_ops const sunaudio_ops = {
       
   516 +  .init = sunaudio_init,
       
   517 +  .get_backend_id = sunaudio_get_backend_id,
       
   518 +  .destroy = sunaudio_destroy,
       
   519 +  .get_preferred_sample_rate = sunaudio_get_preferred_sample_rate,
       
   520 +  .stream_init = sunaudio_stream_init,
       
   521 +  .stream_destroy = sunaudio_stream_destroy,
       
   522 +  .stream_start = sunaudio_stream_start,
       
   523 +  .stream_stop = sunaudio_stream_stop,
       
   524 +  .stream_get_position = sunaudio_stream_get_position,
       
   525 +  .get_max_channel_count = sunaudio_get_max_channel_count,
       
   526 +  .get_min_latency = sunaudio_get_min_latency,
       
   527 +  .stream_get_latency = sunaudio_stream_get_latency
       
   528 +};
       
   529 --- mozilla-esr31/media/libcubeb/src/moz.build.orig	2015-06-04 17:42:52.255965962 -0700
       
   530 +++ mozilla-esr31/media/libcubeb/src/moz.build	2015-06-04 17:42:52.261292681 -0700
       
   531 @@ -30,6 +30,12 @@
       
   532      ]
       
   533      DEFINES['USE_SNDIO'] = True
       
   534  
       
   535 +if CONFIG['OS_ARCH'] == 'SunOS':
       
   536 +    SOURCES += [
       
   537 +        'cubeb_sun.c',
       
   538 +    ]
       
   539 +    DEFINES['USE_SUN'] = True
       
   540 +
       
   541  if CONFIG['OS_TARGET'] == 'Darwin':
       
   542      SOURCES += [
       
   543          'cubeb_audiounit.c',