pkgsrc-Changes archive

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

CVS commit: pkgsrc/www/firefox



Module Name:    pkgsrc
Committed By:   nia
Date:           Thu Jun 13 22:05:24 UTC 2019

Modified Files:
        pkgsrc/www/firefox: Makefile distinfo
        pkgsrc/www/firefox/patches: patch-aa patch-media_libcubeb_src_cubeb.c
            patch-media_libcubeb_src_moz.build patch-media_libcubeb_update.sh
Added Files:
        pkgsrc/www/firefox/files: cubeb_sun.c

Log Message:
firefox: Add sun audio backend and make it a default where supported.

This replaces the OSS backend with something that passes the unit tests,
supports additional channels, and supports recording. It will be included
with future versions of Firefox.

Tested with:

* YouTube audio-video sync test
* about:support device detection
* WebRTC microphone recording (using an USB microphone)

Note: you can select an audio backend using the about:config variable
media.cubeb.backend. This can be set to options such as sun/pulse/oss.

Let me know if you still need to use the oss backend. It's very
incomplete, buggy, and FreeBSD has already removed it - ideally we
should eventually.

Bump PKGREVISION.


To generate a diff of this commit:
cvs rdiff -u -r1.384 -r1.385 pkgsrc/www/firefox/Makefile
cvs rdiff -u -r1.357 -r1.358 pkgsrc/www/firefox/distinfo
cvs rdiff -u -r0 -r1.1 pkgsrc/www/firefox/files/cubeb_sun.c
cvs rdiff -u -r1.62 -r1.63 pkgsrc/www/firefox/patches/patch-aa
cvs rdiff -u -r1.9 -r1.10 \
    pkgsrc/www/firefox/patches/patch-media_libcubeb_src_cubeb.c
cvs rdiff -u -r1.17 -r1.18 \
    pkgsrc/www/firefox/patches/patch-media_libcubeb_src_moz.build
cvs rdiff -u -r1.5 -r1.6 \
    pkgsrc/www/firefox/patches/patch-media_libcubeb_update.sh

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: pkgsrc/www/firefox/Makefile
diff -u pkgsrc/www/firefox/Makefile:1.384 pkgsrc/www/firefox/Makefile:1.385
--- pkgsrc/www/firefox/Makefile:1.384   Wed Jun 12 18:33:27 2019
+++ pkgsrc/www/firefox/Makefile Thu Jun 13 22:05:24 2019
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.384 2019/06/12 18:33:27 ryoon Exp $
+# $NetBSD: Makefile,v 1.385 2019/06/13 22:05:24 nia Exp $
 
 FIREFOX_VER=           ${MOZ_BRANCH}${MOZ_BRANCH_MINOR}
 MOZ_BRANCH=            67.0
@@ -6,6 +6,7 @@ MOZ_BRANCH_MINOR=       .2
 
 DISTNAME=      firefox-${FIREFOX_VER}.source
 PKGNAME=       ${DISTNAME:S/.source//:S/b/beta/:S/esr//}
+PKGREVISION=   1
 CATEGORIES=    www
 MASTER_SITES+= ${MASTER_SITE_MOZILLA:=firefox/releases/${FIREFOX_VER}/source/}
 EXTRACT_SUFX=  .tar.xz
@@ -68,6 +69,7 @@ MOZILLA_NAME= Browser
 .endif
 
 post-extract:
+       ${CP} ${FILESDIR}/cubeb_sun.c ${WRKSRC}/media/libcubeb/src/cubeb_sun.c
        mv ${WRKSRC}/gfx/ycbcr/yuv_row_arm.s ${WRKSRC}/gfx/ycbcr/yuv_row_arm.S
 # XXX Hack taken from lang/rust.
 # patch(1) in NetBSD does not handle .cargo-checksum.json like long width file.

Index: pkgsrc/www/firefox/distinfo
diff -u pkgsrc/www/firefox/distinfo:1.357 pkgsrc/www/firefox/distinfo:1.358
--- pkgsrc/www/firefox/distinfo:1.357   Wed Jun 12 18:33:27 2019
+++ pkgsrc/www/firefox/distinfo Thu Jun 13 22:05:24 2019
@@ -1,10 +1,10 @@
-$NetBSD: distinfo,v 1.357 2019/06/12 18:33:27 ryoon Exp $
+$NetBSD: distinfo,v 1.358 2019/06/13 22:05:24 nia Exp $
 
 SHA1 (firefox-67.0.2.source.tar.xz) = 3d59fe567f9f2d1c0767ef2ea595b738a7e53c89
 RMD160 (firefox-67.0.2.source.tar.xz) = b5182bb4493aaf54fb64f7da6710c3d0092d8c85
 SHA512 (firefox-67.0.2.source.tar.xz) = 14da0aa23571c83dfd4cf1b33027434425c99c4b8838d335cfbd93ef60ad936cd7e7f60ad84be688f434371c9b49142e1020df63ac3e65f78b6595f5a8c19590
 Size (firefox-67.0.2.source.tar.xz) = 283090748 bytes
-SHA1 (patch-aa) = c3e9fdbf6d66d527affc13f4045d28fe05707f7b
+SHA1 (patch-aa) = 1f292aae7d37bd480ba834324b737bfebee52503
 SHA1 (patch-browser_app_profile_firefox.js) = 2ea08bf7030853fe9aff3c43c69266c07f0b0b14
 SHA1 (patch-build_moz.configure_old.configure) = 91bab1cbbe02332ec076b49b6e598730202fbc99
 SHA1 (patch-dom_base_nsAttrName.h) = ac7ba441a3b27df2855cf2673eea36b1cb44ad49
@@ -24,11 +24,11 @@ SHA1 (patch-js_src_threading_posix_Threa
 SHA1 (patch-js_src_util_NativeStack.cpp) = 2c6f844d38343f40ebbc8fd665279256e4ae6d35
 SHA1 (patch-js_xpconnect_src_XPCMaps.cpp) = edca32214a2643eb6c89eac75f6e4200616e2c87
 SHA1 (patch-media_libcubeb_gtest_moz.build) = ea6dcc7ceeb76ce1fb9d508cf43080a2eef3a9e4
-SHA1 (patch-media_libcubeb_src_cubeb.c) = 4fe5512c89fa9e0dd64573d2784e5e0f7fd4d866
+SHA1 (patch-media_libcubeb_src_cubeb.c) = e3446562ed16ec9643df42ee0b9c46ee91f22913
 SHA1 (patch-media_libcubeb_src_cubeb__alsa.c) = f359a66a22f11142d05746e15894d998d3e3bf5a
 SHA1 (patch-media_libcubeb_src_cubeb__oss.c) = 103f751d5a7bc14a81a6ed43e1afc722bc092f7e
-SHA1 (patch-media_libcubeb_src_moz.build) = 10f8355e3b3c6d35cca99f3717246e8658860737
-SHA1 (patch-media_libcubeb_update.sh) = cddb5849fa2972e961e4891bc8a79a650df06d8d
+SHA1 (patch-media_libcubeb_src_moz.build) = dcca90cb5132442877712cd7b1f4e832c93d2655
+SHA1 (patch-media_libcubeb_update.sh) = 4508319d8534a0cc983e4767c2142169af9e5033
 SHA1 (patch-media_libpng_pngpriv.h) = c8084332560017cd7c9b519b61d125fa28af0dbc
 SHA1 (patch-python_mozbuild_mozbuild_action_check__binary.py) = 8103ca9f95fe98a4461c97abcd4cafd5ae5294f0
 SHA1 (patch-servo_components_style_build__gecko.rs) = dacdcb69de1c8409bda20b11afbfa49624005c72

Index: pkgsrc/www/firefox/patches/patch-aa
diff -u pkgsrc/www/firefox/patches/patch-aa:1.62 pkgsrc/www/firefox/patches/patch-aa:1.63
--- pkgsrc/www/firefox/patches/patch-aa:1.62    Sat Jun  1 19:11:28 2019
+++ pkgsrc/www/firefox/patches/patch-aa Thu Jun 13 22:05:24 2019
@@ -1,23 +1,27 @@
-$NetBSD: patch-aa,v 1.62 2019/06/01 19:11:28 maya Exp $
+$NetBSD: patch-aa,v 1.63 2019/06/13 22:05:24 nia Exp $
 
 * Add OSS audio support
+* Add Sun audio support
 * Disable libav-fft on SunOS (relocation errors)
 
---- old-configure.in.orig      2019-03-07 16:53:39.000000000 +0000
+--- old-configure.in.orig      2019-05-29 15:39:16.000000000 +0000
 +++ old-configure.in
-@@ -2130,6 +2130,67 @@ MOZ_WEBM_ENCODER=1
+@@ -2043,6 +2043,71 @@ MOZ_WEBM_ENCODER=1
  AC_DEFINE(MOZ_WEBM_ENCODER)
  AC_SUBST(MOZ_WEBM_ENCODER)
  
 +dnl ==================================
-+dnl = Check OSS availability
++dnl = Check OSS/sunaudio availability
 +dnl ==================================
 +
-+dnl If using Linux, Solaris or BSDs, ensure that OSS is available
++dnl If using Linux, Solaris or BSDs, ensure that OSS/sunaudio is available
 +case "$OS_TARGET" in
-+Linux|SunOS|DragonFly|FreeBSD|NetBSD|GNU/kFreeBSD)
++Linux|DragonFly|FreeBSD|GNU/kFreeBSD)
 +    MOZ_OSS=1
 +    ;;
++SunOS|NetBSD)
++    MOZ_SUNAUDIO=1
++    ;;
 +esac
 +
 +MOZ_ARG_WITH_STRING(oss,
@@ -66,6 +70,7 @@ $NetBSD: patch-aa,v 1.62 2019/06/01 19:1
 +CFLAGS=$_SAVE_CFLAGS
 +LIBS=$_SAVE_LIBS
 +
++AC_SUBST(MOZ_SUNAUDIO)
 +AC_SUBST(MOZ_OSS)
 +AC_SUBST_LIST(MOZ_OSS_CFLAGS)
 +AC_SUBST_LIST(MOZ_OSS_LIBS)

Index: pkgsrc/www/firefox/patches/patch-media_libcubeb_src_cubeb.c
diff -u pkgsrc/www/firefox/patches/patch-media_libcubeb_src_cubeb.c:1.9 pkgsrc/www/firefox/patches/patch-media_libcubeb_src_cubeb.c:1.10
--- pkgsrc/www/firefox/patches/patch-media_libcubeb_src_cubeb.c:1.9     Sun Nov  4 04:46:57 2018
+++ pkgsrc/www/firefox/patches/patch-media_libcubeb_src_cubeb.c Thu Jun 13 22:05:24 2019
@@ -1,10 +1,21 @@
-$NetBSD: patch-media_libcubeb_src_cubeb.c,v 1.9 2018/11/04 04:46:57 ryoon Exp $
+$NetBSD: patch-media_libcubeb_src_cubeb.c,v 1.10 2019/06/13 22:05:24 nia Exp $
 
 * Support OSS audio
+* Support Sun audio
 
---- media/libcubeb/src/cubeb.c.orig    2018-10-18 20:06:09.000000000 +0000
+--- media/libcubeb/src/cubeb.c.orig    2019-06-09 08:15:58.000000000 +0000
 +++ media/libcubeb/src/cubeb.c
-@@ -60,6 +60,9 @@ int audiotrack_init(cubeb ** context, ch
+@@ -51,6 +51,9 @@ int wasapi_init(cubeb ** context, char c
+ #if defined(USE_SNDIO)
+ int sndio_init(cubeb ** context, char const * context_name);
+ #endif
++#if defined(USE_SUN)
++int sun_init(cubeb ** context, char const * context_name);
++#endif
+ #if defined(USE_OPENSL)
+ int opensl_init(cubeb ** context, char const * context_name);
+ #endif
+@@ -60,6 +63,9 @@ int audiotrack_init(cubeb ** context, ch
  #if defined(USE_KAI)
  int kai_init(cubeb ** context, char const * context_name);
  #endif
@@ -14,7 +25,7 @@ $NetBSD: patch-media_libcubeb_src_cubeb.
  
  static int
  validate_stream_params(cubeb_stream_params * input_stream_params,
-@@ -160,6 +163,10 @@ cubeb_init(cubeb ** context, char const 
+@@ -160,6 +166,10 @@ cubeb_init(cubeb ** context, char const 
  #if defined(USE_KAI)
        init_oneshot = kai_init;
  #endif
@@ -25,7 +36,17 @@ $NetBSD: patch-media_libcubeb_src_cubeb.
      } else {
        /* Already set */
      }
-@@ -204,6 +211,9 @@ cubeb_init(cubeb ** context, char const 
+@@ -195,6 +205,9 @@ cubeb_init(cubeb ** context, char const 
+ #if defined(USE_SNDIO)
+     sndio_init,
+ #endif
++#if defined(USE_SUN)
++    sun_init,
++#endif
+ #if defined(USE_OPENSL)
+     opensl_init,
+ #endif
+@@ -204,6 +217,9 @@ cubeb_init(cubeb ** context, char const 
  #if defined(USE_KAI)
      kai_init,
  #endif

Index: pkgsrc/www/firefox/patches/patch-media_libcubeb_src_moz.build
diff -u pkgsrc/www/firefox/patches/patch-media_libcubeb_src_moz.build:1.17 pkgsrc/www/firefox/patches/patch-media_libcubeb_src_moz.build:1.18
--- pkgsrc/www/firefox/patches/patch-media_libcubeb_src_moz.build:1.17  Sun Nov  4 04:46:57 2018
+++ pkgsrc/www/firefox/patches/patch-media_libcubeb_src_moz.build       Thu Jun 13 22:05:24 2019
@@ -1,10 +1,11 @@
-$NetBSD: patch-media_libcubeb_src_moz.build,v 1.17 2018/11/04 04:46:57 ryoon Exp $
+$NetBSD: patch-media_libcubeb_src_moz.build,v 1.18 2019/06/13 22:05:24 nia Exp $
 
 * Add OSS audio support
+* Add Sun audio support
 
---- media/libcubeb/src/moz.build.orig  2018-10-18 20:06:09.000000000 +0000
+--- media/libcubeb/src/moz.build.orig  2019-05-29 15:39:06.000000000 +0000
 +++ media/libcubeb/src/moz.build
-@@ -23,6 +23,12 @@ if CONFIG['MOZ_ALSA']:
+@@ -23,6 +23,18 @@ if CONFIG['MOZ_ALSA']:
      ]
      DEFINES['USE_ALSA'] = True
  
@@ -14,10 +15,16 @@ $NetBSD: patch-media_libcubeb_src_moz.bu
 +    ]
 +    DEFINES['USE_OSS'] = True
 +
++if CONFIG['MOZ_SUNAUDIO']:
++    SOURCES += [
++        'cubeb_sun.c',
++    ]
++    DEFINES['USE_SUN'] = True
++
  if CONFIG['MOZ_PULSEAUDIO'] or CONFIG['MOZ_JACK']:
      SOURCES += [
          'cubeb_resampler.cpp',
-@@ -89,6 +95,7 @@ FINAL_LIBRARY = 'gkmedias'
+@@ -89,6 +101,7 @@ FINAL_LIBRARY = 'gkmedias'
  
  CFLAGS += CONFIG['MOZ_ALSA_CFLAGS']
  CFLAGS += CONFIG['MOZ_JACK_CFLAGS']

Index: pkgsrc/www/firefox/patches/patch-media_libcubeb_update.sh
diff -u pkgsrc/www/firefox/patches/patch-media_libcubeb_update.sh:1.5 pkgsrc/www/firefox/patches/patch-media_libcubeb_update.sh:1.6
--- pkgsrc/www/firefox/patches/patch-media_libcubeb_update.sh:1.5       Sun Nov  4 00:38:45 2018
+++ pkgsrc/www/firefox/patches/patch-media_libcubeb_update.sh   Thu Jun 13 22:05:24 2019
@@ -1,12 +1,13 @@
-$NetBSD: patch-media_libcubeb_update.sh,v 1.5 2018/11/04 00:38:45 ryoon Exp $
+$NetBSD: patch-media_libcubeb_update.sh,v 1.6 2019/06/13 22:05:24 nia Exp $
 
---- media/libcubeb/update.sh.orig      2018-10-18 20:06:09.000000000 +0000
+--- media/libcubeb/update.sh.orig      2019-05-29 15:39:11.000000000 +0000
 +++ media/libcubeb/update.sh
-@@ -20,6 +20,7 @@ cp $1/src/cubeb_log.h src
+@@ -25,6 +25,8 @@ cp $1/src/cubeb_log.h src
  cp $1/src/cubeb_mixer.cpp src
  cp $1/src/cubeb_mixer.h src
  cp $1/src/cubeb_opensl.c src
 +cp $1/src/cubeb_oss.c src
++cp $1/src/cubeb_sun.c src
  cp $1/src/cubeb-jni.cpp src
  cp $1/src/cubeb-jni.h src
  cp $1/src/android/cubeb-output-latency.h src/android

Added files:

Index: pkgsrc/www/firefox/files/cubeb_sun.c
diff -u /dev/null pkgsrc/www/firefox/files/cubeb_sun.c:1.1
--- /dev/null   Thu Jun 13 22:05:24 2019
+++ pkgsrc/www/firefox/files/cubeb_sun.c        Thu Jun 13 22:05:24 2019
@@ -0,0 +1,752 @@
+/*
+ * Copyright © 2019 Nia Alarie
+ *
+ * This program is made available under an ISC-style license.  See the
+ * accompanying file LICENSE for details.
+ */
+#include <sys/audioio.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include "cubeb/cubeb.h"
+#include "cubeb-internal.h"
+
+#define BYTES_TO_FRAMES(bytes, channels) \
+  (bytes / (channels * sizeof(int16_t)))
+
+#define FRAMES_TO_BYTES(frames, channels) \
+  (frames * (channels * sizeof(int16_t)))
+
+/* Default to 4 + 1 for the default device. */
+#ifndef SUN_DEVICE_COUNT
+#define SUN_DEVICE_COUNT (5)
+#endif
+
+/* Supported well by most hardware. */
+#ifndef SUN_PREFER_RATE
+#define SUN_PREFER_RATE (48000)
+#endif
+
+/* Standard acceptable minimum. */
+#ifndef SUN_LATENCY_MS
+#define SUN_LATENCY_MS (40)
+#endif
+
+#ifndef SUN_DEFAULT_DEVICE
+#define SUN_DEFAULT_DEVICE "/dev/audio"
+#endif
+
+#ifndef SUN_POLL_TIMEOUT
+#define SUN_POLL_TIMEOUT (1000)
+#endif
+
+#ifndef SUN_BUFFER_FRAMES
+#define SUN_BUFFER_FRAMES (256)
+#endif
+
+/*
+ * Supported on NetBSD regardless of hardware.
+ */
+
+#ifndef SUN_MAX_CHANNELS
+# ifdef __NetBSD__
+#  define SUN_MAX_CHANNELS (12)
+# else
+#  define SUN_MAX_CHANNELS (2)
+# endif
+#endif
+
+#ifndef SUN_MIN_RATE
+#define SUN_MIN_RATE (1000)
+#endif
+
+#ifndef SUN_MAX_RATE
+#define SUN_MAX_RATE (192000)
+#endif
+
+static struct cubeb_ops const sun_ops;
+
+struct cubeb {
+  struct cubeb_ops const * ops;
+};
+
+struct cubeb_stream {
+  struct cubeb * context;
+  void * user_ptr;
+  pthread_t thread;
+  pthread_mutex_t mutex; /* protects running, volume, frames_written */
+  int floating;
+  int running;
+  int play_fd;
+  int record_fd;
+  float volume;
+  struct audio_info p_info; /* info for the play fd */
+  struct audio_info r_info; /* info for the record fd */
+  cubeb_data_callback data_cb;
+  cubeb_state_callback state_cb;
+  int16_t * play_buf;
+  int16_t * record_buf;
+  float * f_play_buf;
+  float * f_record_buf;
+  char input_name[32];
+  char output_name[32];
+  uint64_t frames_written;
+  uint64_t blocks_written;
+};
+
+int
+sun_init(cubeb ** context, char const * context_name)
+{
+  cubeb * c;
+
+  (void)context_name;
+  if ((c = calloc(1, sizeof(cubeb))) == NULL) {
+    return CUBEB_ERROR;
+  }
+  c->ops = &sun_ops;
+  *context = c;
+  return CUBEB_OK;
+}
+
+static void
+sun_destroy(cubeb * context)
+{
+  free(context);
+}
+
+static char const *
+sun_get_backend_id(cubeb * context)
+{
+  return "sun";
+}
+
+static int
+sun_get_preferred_sample_rate(cubeb * context, uint32_t * rate)
+{
+  (void)context;
+
+  *rate = SUN_PREFER_RATE;
+  return CUBEB_OK;
+}
+
+static int
+sun_get_max_channel_count(cubeb * context, uint32_t * max_channels)
+{
+  (void)context;
+
+  *max_channels = SUN_MAX_CHANNELS;
+  return CUBEB_OK;
+}
+
+static int
+sun_get_min_latency(cubeb * context, cubeb_stream_params params,
+                    uint32_t * latency_frames)
+{
+  (void)context;
+
+  *latency_frames = SUN_LATENCY_MS * params.rate / 1000;
+  return CUBEB_OK;
+}
+
+static int
+sun_get_hwinfo(const char * device, struct audio_info * format,
+               int * props, struct audio_device * dev)
+{
+  int fd = -1;
+
+  if ((fd = open(device, O_RDONLY)) == -1) {
+    goto error;
+  }
+#ifdef AUDIO_GETFORMAT
+  if (ioctl(fd, AUDIO_GETFORMAT, format) != 0) {
+    goto error;
+  }
+#endif
+#ifdef AUDIO_GETPROPS
+  if (ioctl(fd, AUDIO_GETPROPS, props) != 0) {
+    goto error;
+  }
+#endif
+  if (ioctl(fd, AUDIO_GETDEV, dev) != 0) {
+    goto error;
+  }
+  close(fd);
+  return CUBEB_OK;
+error:
+  if (fd != -1) {
+    close(fd);
+  }
+  return CUBEB_ERROR;
+}
+
+/*
+ * XXX: PR kern/54264
+ */
+static int
+sun_prinfo_verify_sanity(struct audio_prinfo * prinfo)
+{
+   return prinfo->precision >= 8 && prinfo->precision <= 32 &&
+     prinfo->channels >= 1 && prinfo->channels < SUN_MAX_CHANNELS &&
+     prinfo->sample_rate < SUN_MAX_RATE && prinfo->sample_rate > SUN_MIN_RATE;
+}
+
+static int
+sun_enumerate_devices(cubeb * context, cubeb_device_type type,
+                      cubeb_device_collection * collection)
+{
+  unsigned i;
+  cubeb_device_info device = {0};
+  char dev[16] = SUN_DEFAULT_DEVICE;
+  char dev_friendly[64];
+  struct audio_info hwfmt;
+  struct audio_device hwname;
+  struct audio_prinfo *prinfo = NULL;
+  int hwprops;
+
+  collection->device = calloc(SUN_DEVICE_COUNT, sizeof(cubeb_device_info));
+  if (collection->device == NULL) {
+    return CUBEB_ERROR;
+  }
+  collection->count = 0;
+
+  for (i = 0; i < SUN_DEVICE_COUNT; ++i) {
+    if (i > 0) {
+      (void)snprintf(dev, sizeof(dev), "/dev/audio%u", i - 1);
+    }
+    if (sun_get_hwinfo(dev, &hwfmt, &hwprops, &hwname) != CUBEB_OK) {
+      continue;
+    }
+#ifdef AUDIO_GETPROPS
+    device.type = 0;
+    if ((hwprops & AUDIO_PROP_CAPTURE) != 0 &&
+        sun_prinfo_verify_sanity(&hwfmt.record)) {
+      /* the device supports recording, probably */
+      device.type |= CUBEB_DEVICE_TYPE_INPUT;
+    }
+    if ((hwprops & AUDIO_PROP_PLAYBACK) != 0 &&
+        sun_prinfo_verify_sanity(&hwfmt.play)) {
+      /* the device supports playback, probably */
+      device.type |= CUBEB_DEVICE_TYPE_OUTPUT;
+    }
+    switch (device.type) {
+    case 0:
+      /* device doesn't do input or output, aliens probably involved */
+      continue;
+    case CUBEB_DEVICE_TYPE_INPUT:
+      if ((type & CUBEB_DEVICE_TYPE_INPUT) == 0) {
+        /* this device is input only, not scanning for those, skip it */
+        continue;
+      }
+      break;
+    case CUBEB_DEVICE_TYPE_OUTPUT:
+      if ((type & CUBEB_DEVICE_TYPE_OUTPUT) == 0) {
+        /* this device is output only, not scanning for those, skip it */
+        continue;
+      }
+      break;
+    }
+    if ((type & CUBEB_DEVICE_TYPE_INPUT) != 0) {
+      prinfo = &hwfmt.record;
+    }
+    if ((type & CUBEB_DEVICE_TYPE_OUTPUT) != 0) {
+      prinfo = &hwfmt.play;
+    }
+#endif
+    if (i > 0) {
+      (void)snprintf(dev_friendly, sizeof(dev_friendly), "%s %s %s (%d)",
+                     hwname.name, hwname.version, hwname.config, i - 1);
+    } else {
+      (void)snprintf(dev_friendly, sizeof(dev_friendly), "%s %s %s (default)",
+                     hwname.name, hwname.version, hwname.config);
+    }
+    device.devid = (void *)(uintptr_t)i;
+    device.device_id = strdup(dev);
+    device.friendly_name = strdup(dev_friendly);
+    device.group_id = strdup(dev);
+    device.vendor_name = strdup(hwname.name);
+    device.type = type;
+    device.state = CUBEB_DEVICE_STATE_ENABLED;
+    device.preferred = (i == 0) ? CUBEB_DEVICE_PREF_ALL : CUBEB_DEVICE_PREF_NONE;
+#ifdef AUDIO_GETFORMAT
+    device.max_channels = prinfo->channels;
+    device.default_rate = prinfo->sample_rate;
+#else
+    device.max_channels = 2;
+    device.default_rate = SUN_PREFER_RATE;
+#endif
+    device.default_format = CUBEB_DEVICE_FMT_S16NE;
+    device.format = CUBEB_DEVICE_FMT_S16NE;
+    device.min_rate = SUN_MIN_RATE;
+    device.max_rate = SUN_MAX_RATE;
+    device.latency_lo = SUN_LATENCY_MS * SUN_MIN_RATE / 1000;
+    device.latency_hi = SUN_LATENCY_MS * SUN_MAX_RATE / 1000;
+    collection->device[collection->count++] = device;
+  }
+  return CUBEB_OK;
+}
+
+static int
+sun_device_collection_destroy(cubeb * context,
+                              cubeb_device_collection * collection)
+{
+  unsigned i;
+
+  for (i = 0; i < collection->count; ++i) {
+    free((char *)collection->device[i].device_id);
+    free((char *)collection->device[i].friendly_name);
+    free((char *)collection->device[i].group_id);
+    free((char *)collection->device[i].vendor_name);
+  }
+  free(collection->device);
+  return CUBEB_OK;
+}
+
+static int
+sun_copy_params(int fd, cubeb_stream * stream, cubeb_stream_params * params,
+                struct audio_info * info, struct audio_prinfo * prinfo)
+{
+  prinfo->channels = params->channels;
+  prinfo->sample_rate = params->rate;
+  prinfo->precision = 16;
+#ifdef AUDIO_ENCODING_SLINEAR_LE
+  switch (params->format) {
+  case CUBEB_SAMPLE_S16LE:
+    prinfo->encoding = AUDIO_ENCODING_SLINEAR_LE;
+    break;
+  case CUBEB_SAMPLE_S16BE:
+    prinfo->encoding = AUDIO_ENCODING_SLINEAR_BE;
+    break;
+  case CUBEB_SAMPLE_FLOAT32NE:
+    stream->floating = 1;
+    prinfo->encoding = AUDIO_ENCODING_SLINEAR;
+    break;
+  default:
+    LOG("Unsupported format");
+    return CUBEB_ERROR_INVALID_FORMAT;
+  }
+#else
+  switch (params->format) {
+  case CUBEB_SAMPLE_S16NE:
+    prinfo->encoding = AUDIO_ENCODING_LINEAR;
+    break;
+  case CUBEB_SAMPLE_FLOAT32NE:
+    stream->floating = 1;
+    prinfo->encoding = AUDIO_ENCODING_LINEAR;
+    break;
+  default:
+    LOG("Unsupported format");
+    return CUBEB_ERROR_INVALID_FORMAT;
+  }
+#endif
+  if (ioctl(fd, AUDIO_SETINFO, info) == -1) {
+    return CUBEB_ERROR;
+  }
+  if (ioctl(fd, AUDIO_GETINFO, info) == -1) {
+    return CUBEB_ERROR;
+  }
+  return CUBEB_OK;
+}
+
+static int
+sun_stream_stop(cubeb_stream * s)
+{
+  pthread_mutex_lock(&s->mutex);
+  if (s->running) {
+    s->running = 0;
+    pthread_mutex_unlock(&s->mutex);
+    pthread_join(s->thread, NULL);
+  } else {
+    pthread_mutex_unlock(&s->mutex);
+  }
+  return CUBEB_OK;
+}
+
+static void
+sun_stream_destroy(cubeb_stream * s)
+{
+  pthread_mutex_destroy(&s->mutex);
+  sun_stream_stop(s);
+  if (s->play_fd != -1) {
+    close(s->play_fd);
+  }
+  if (s->record_fd != -1) {
+    close(s->record_fd);
+  }
+  free(s->f_play_buf);
+  free(s->f_record_buf);
+  free(s->play_buf);
+  free(s->record_buf);
+  free(s);
+}
+
+static void
+sun_float_to_linear(float * in, int16_t * out,
+                    unsigned channels, long frames, float vol)
+{
+  unsigned i, sample_count = frames * channels;
+  float multiplier = vol * 0x8000;
+
+  for (i = 0; i < sample_count; ++i) {
+    int32_t sample = lrintf(in[i] * multiplier);
+    if (sample < -0x8000) {
+      out[i] = -0x8000;
+    } else if (sample > 0x7fff) {
+      out[i] = 0x7fff;
+    } else {
+      out[i] = sample;
+    }
+  }
+}
+
+static void
+sun_linear_to_float(int16_t * in, float * out,
+                    unsigned channels, long frames)
+{
+  unsigned i, sample_count = frames * channels;
+
+  for (i = 0; i < sample_count; ++i) {
+    out[i] = (1.0 / 0x8000) * in[i];
+  }
+}
+
+static void
+sun_linear_set_vol(int16_t * buf, unsigned channels, long frames, float vol)
+{
+  unsigned i, sample_count = frames * channels;
+  int32_t multiplier = vol * 0x8000;
+
+  for (i = 0; i < sample_count; ++i) {
+    buf[i] = (buf[i] * multiplier) >> 15;
+  }
+}
+
+static void *
+sun_io_routine(void * arg)
+{
+  cubeb_stream *s = arg;
+  cubeb_state state = CUBEB_STATE_STARTED;
+  size_t to_read = 0;
+  long to_write = 0;
+  size_t write_ofs = 0;
+  size_t read_ofs = 0;
+  int drain = 0;
+
+  s->state_cb(s, s->user_ptr, CUBEB_STATE_STARTED);
+  while (state != CUBEB_STATE_ERROR) {
+    pthread_mutex_lock(&s->mutex);
+    if (!s->running) {
+      pthread_mutex_unlock(&s->mutex);
+      state = CUBEB_STATE_STOPPED;
+      break;
+    }
+    pthread_mutex_unlock(&s->mutex);
+    if (s->floating) {
+      if (s->record_fd != -1) {
+        sun_linear_to_float(s->record_buf, s->f_record_buf,
+                            s->r_info.record.channels, SUN_BUFFER_FRAMES);
+      }
+      to_write = s->data_cb(s, s->user_ptr,
+                            s->f_record_buf, s->f_play_buf, SUN_BUFFER_FRAMES);
+      if (to_write == CUBEB_ERROR) {
+        state = CUBEB_STATE_ERROR;
+        break;
+      }
+      if (s->play_fd != -1) {
+        pthread_mutex_lock(&s->mutex);
+        sun_float_to_linear(s->f_play_buf, s->play_buf,
+                            s->p_info.play.channels, to_write, s->volume);
+        pthread_mutex_unlock(&s->mutex);
+      }
+    } else {
+      to_write = s->data_cb(s, s->user_ptr,
+                            s->record_buf, s->play_buf, SUN_BUFFER_FRAMES);
+      if (to_write == CUBEB_ERROR) {
+        state = CUBEB_STATE_ERROR;
+        break;
+      }
+      if (s->play_fd != -1) {
+        pthread_mutex_lock(&s->mutex);
+        sun_linear_set_vol(s->play_buf, s->p_info.play.channels, to_write, s->volume);
+        pthread_mutex_unlock(&s->mutex);
+      }
+    }
+    if (to_write < SUN_BUFFER_FRAMES) {
+      drain = 1;
+    }
+    to_write = s->play_fd != -1 ? to_write : 0;
+    to_read = s->record_fd != -1 ? SUN_BUFFER_FRAMES : 0;
+    write_ofs = 0;
+    read_ofs = 0;
+    while (to_write > 0 || to_read > 0) {
+      size_t bytes;
+      ssize_t n, frames;
+
+      if (to_write > 0) {
+        bytes = FRAMES_TO_BYTES(to_write, s->p_info.play.channels);
+        if ((n = write(s->play_fd, s->play_buf + write_ofs, bytes)) < 0) {
+          state = CUBEB_STATE_ERROR;
+          break;
+        }
+        frames = BYTES_TO_FRAMES(n, s->p_info.play.channels);
+        pthread_mutex_lock(&s->mutex);
+        s->frames_written += frames;
+        pthread_mutex_unlock(&s->mutex);
+        to_write -= frames;
+        write_ofs += frames;
+      }
+      if (to_read > 0) {
+        bytes = FRAMES_TO_BYTES(to_read, s->r_info.record.channels);
+        if ((n = read(s->record_fd, s->record_buf + read_ofs, bytes)) < 0) {
+          state = CUBEB_STATE_ERROR;
+          break;
+        }
+        frames = BYTES_TO_FRAMES(n, s->r_info.record.channels);
+        to_read -= frames;
+        read_ofs += frames;
+      }
+    }
+    if (drain && state != CUBEB_STATE_ERROR) {
+      state = CUBEB_STATE_DRAINED;
+      break;
+    }
+  }
+  s->state_cb(s, s->user_ptr, state);
+  return NULL;
+}
+
+static int
+sun_stream_init(cubeb * context,
+                cubeb_stream ** stream,
+                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 latency_frames,
+                cubeb_data_callback data_callback,
+                cubeb_state_callback state_callback,
+                void * user_ptr)
+{
+  int ret = CUBEB_OK;
+  cubeb_stream *s = NULL;
+
+  (void)stream_name;
+  if ((s = calloc(1, sizeof(cubeb_stream))) == NULL) {
+    ret = CUBEB_ERROR;
+    goto error;
+  }
+  s->record_fd = -1;
+  s->play_fd = -1;
+  if (input_device != 0) {
+    snprintf(s->input_name, sizeof(s->input_name),
+      "/dev/audio%zu", (uintptr_t)input_device - 1);
+  } else {
+    snprintf(s->input_name, sizeof(s->input_name), "%s", SUN_DEFAULT_DEVICE);
+  }
+  if (output_device != 0) {
+    snprintf(s->output_name, sizeof(s->output_name),
+      "/dev/audio%zu", (uintptr_t)output_device - 1);
+  } else {
+    snprintf(s->output_name, sizeof(s->output_name), "%s", SUN_DEFAULT_DEVICE);
+  }
+  if (input_stream_params != NULL) {
+    if (input_stream_params->prefs & CUBEB_STREAM_PREF_LOOPBACK) {
+      LOG("Loopback not supported");
+      ret = CUBEB_ERROR_NOT_SUPPORTED;
+      goto error;
+    }
+    if (s->record_fd == -1) {
+      if ((s->record_fd = open(s->input_name, O_RDONLY)) == -1) {
+        LOG("Audio device cannot be opened as read-only");
+        ret = CUBEB_ERROR_DEVICE_UNAVAILABLE;
+        goto error;
+      }
+    }
+    AUDIO_INITINFO(&s->r_info);
+#ifdef AUMODE_RECORD
+    s->r_info.mode = AUMODE_RECORD;
+#endif
+    if ((ret = sun_copy_params(s->record_fd, s, input_stream_params,
+                               &s->r_info, &s->r_info.record)) != CUBEB_OK) {
+      LOG("Setting record params failed");
+      goto error;
+    }
+  }
+  if (output_stream_params != NULL) {
+    if (output_stream_params->prefs & CUBEB_STREAM_PREF_LOOPBACK) {
+      LOG("Loopback not supported");
+      ret = CUBEB_ERROR_NOT_SUPPORTED;
+      goto error;
+    }
+    if (s->play_fd == -1) {
+      if ((s->play_fd = open(s->output_name, O_WRONLY)) == -1) {
+        LOG("Audio device cannot be opened as write-only");
+        ret = CUBEB_ERROR_DEVICE_UNAVAILABLE;
+        goto error;
+      }
+    }
+    AUDIO_INITINFO(&s->p_info);
+#ifdef AUMODE_PLAY
+    s->p_info.mode = AUMODE_PLAY;
+#endif
+    if ((ret = sun_copy_params(s->play_fd, s, output_stream_params,
+                               &s->p_info, &s->p_info.play)) != CUBEB_OK) {
+      LOG("Setting play params failed");
+      goto error;
+    }
+  }
+  s->context = context;
+  s->volume = 1.0;
+  s->state_cb = state_callback;
+  s->data_cb = data_callback;
+  s->user_ptr = user_ptr;
+  if (pthread_mutex_init(&s->mutex, NULL) != 0) {
+    LOG("Failed to create mutex");
+    goto error;
+  }
+  if (s->play_fd != -1 && (s->play_buf = calloc(SUN_BUFFER_FRAMES,
+      s->p_info.play.channels * sizeof(int16_t))) == NULL) {
+    ret = CUBEB_ERROR;
+    goto error;
+  }
+  if (s->record_fd != -1 && (s->record_buf = calloc(SUN_BUFFER_FRAMES,
+      s->r_info.record.channels * sizeof(int16_t))) == NULL) {
+    ret = CUBEB_ERROR;
+    goto error;
+  }
+  if (s->floating) {
+    if (s->play_fd != -1 && (s->f_play_buf = calloc(SUN_BUFFER_FRAMES,
+        s->p_info.play.channels * sizeof(float))) == NULL) {
+      ret = CUBEB_ERROR;
+      goto error;
+    }
+    if (s->record_fd != -1 && (s->f_record_buf = calloc(SUN_BUFFER_FRAMES,
+        s->r_info.record.channels * sizeof(float))) == NULL) {
+      ret = CUBEB_ERROR;
+      goto error;
+    }
+  }
+  *stream = s;
+  return CUBEB_OK;
+error:
+  if (s != NULL) {
+    sun_stream_destroy(s);
+  }
+  return ret;
+}
+
+static int
+sun_stream_start(cubeb_stream * s)
+{
+  s->running = 1;
+  if (pthread_create(&s->thread, NULL, sun_io_routine, s) != 0) {
+    LOG("Couldn't create thread");
+    return CUBEB_ERROR;
+  }
+  return CUBEB_OK;
+}
+
+static int
+sun_stream_get_position(cubeb_stream * s, uint64_t * position)
+{
+#ifdef AUDIO_GETOOFFS
+  struct audio_offset offset;
+
+  if (ioctl(s->play_fd, AUDIO_GETOOFFS, &offset) == -1) {
+    return CUBEB_ERROR;
+  }
+  s->blocks_written += offset.deltablks;
+  *position = BYTES_TO_FRAMES(s->blocks_written * s->p_info.blocksize,
+                              s->p_info.play.channels);
+  return CUBEB_OK;
+#else
+  pthread_mutex_lock(&s->mutex);
+  *position = s->frames_written;
+  pthread_mutex_unlock(&s->mutex);
+  return CUBEB_OK;
+#endif
+}
+
+static int
+sun_stream_get_latency(cubeb_stream * stream, uint32_t * latency)
+{
+#ifdef AUDIO_GETBUFINFO
+  struct audio_info info;
+
+  if (ioctl(stream->play_fd, AUDIO_GETBUFINFO, &info) == -1) {
+    return CUBEB_ERROR;
+  }
+
+  *latency = BYTES_TO_FRAMES(info.play.seek + info.blocksize / 2,
+                             info.play.channels);
+  return CUBEB_OK;
+#else
+  cubeb_stream_params params;
+
+  params.rate = stream->p_info.play.sample_rate;
+
+  return sun_get_min_latency(NULL, params, latency);
+#endif
+}
+
+static int
+sun_stream_set_volume(cubeb_stream * stream, float volume)
+{
+  pthread_mutex_lock(&stream->mutex);
+  stream->volume = volume;
+  pthread_mutex_unlock(&stream->mutex);
+  return CUBEB_OK;
+}
+
+static int
+sun_get_current_device(cubeb_stream * stream, cubeb_device ** const device)
+{
+  *device = calloc(1, sizeof(cubeb_device));
+  if (*device == NULL) {
+    return CUBEB_ERROR;
+  }
+  (*device)->input_name = stream->record_fd != -1 ?
+    strdup(stream->input_name) : NULL;
+  (*device)->output_name = stream->play_fd != -1 ?
+    strdup(stream->output_name) : NULL;
+  return CUBEB_OK;
+}
+
+static int
+sun_stream_device_destroy(cubeb_stream * stream, cubeb_device * device)
+{
+  (void)stream;
+  free(device->input_name);
+  free(device->output_name);
+  free(device);
+  return CUBEB_OK;
+}
+
+static struct cubeb_ops const sun_ops = {
+  .init = sun_init,
+  .get_backend_id = sun_get_backend_id,
+  .get_max_channel_count = sun_get_max_channel_count,
+  .get_min_latency = sun_get_min_latency,
+  .get_preferred_sample_rate = sun_get_preferred_sample_rate,
+  .enumerate_devices = sun_enumerate_devices,
+  .device_collection_destroy = sun_device_collection_destroy,
+  .destroy = sun_destroy,
+  .stream_init = sun_stream_init,
+  .stream_destroy = sun_stream_destroy,
+  .stream_start = sun_stream_start,
+  .stream_stop = sun_stream_stop,
+  .stream_reset_default_device = NULL,
+  .stream_get_position = sun_stream_get_position,
+  .stream_get_latency = sun_stream_get_latency,
+  .stream_set_volume = sun_stream_set_volume,
+  .stream_set_panning = NULL,
+  .stream_get_current_device = sun_get_current_device,
+  .stream_device_destroy = sun_stream_device_destroy,
+  .stream_register_device_changed_callback = NULL,
+  .register_device_collection_changed = NULL
+};



Home | Main Index | Thread Index | Old Index