$NetBSD$

* Part of patchset to build chromium on NetBSD
* Based on OpenBSD's chromium patches, and
  pkgsrc's qt5-qtwebengine patches

--- media/audio/sndio/sndio_input.cc.orig	2024-11-16 19:58:04.857013994 +0000
+++ media/audio/sndio/sndio_input.cc
@@ -0,0 +1,200 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/logging.h"
+#include "media/base/audio_timestamp_helper.h"
+#include "media/audio/sndio/audio_manager_sndio.h"
+#include "media/audio/audio_manager.h"
+#include "media/audio/sndio/sndio_input.h"
+
+namespace media {
+
+static const SampleFormat kSampleFormat = kSampleFormatS16;
+
+void SndioAudioInputStream::OnMoveCallback(void *arg, int delta)
+{
+  SndioAudioInputStream* self = static_cast<SndioAudioInputStream*>(arg);
+
+  self->hw_delay += delta;
+}
+
+void *SndioAudioInputStream::ThreadEntry(void *arg) {
+  SndioAudioInputStream* self = static_cast<SndioAudioInputStream*>(arg);
+
+  self->ThreadLoop();
+  return NULL;
+}
+
+SndioAudioInputStream::SndioAudioInputStream(AudioManagerBase* manager,
+                                             const std::string& device_name,
+                                             const AudioParameters& params)
+    : manager(manager),
+      params(params),
+      audio_bus(AudioBus::Create(params)),
+      state(kClosed) {
+}
+
+SndioAudioInputStream::~SndioAudioInputStream() {
+  if (state != kClosed)
+    Close();
+}
+
+AudioInputStream::OpenOutcome SndioAudioInputStream::Open() {
+  struct sio_par par;
+  int sig;
+
+  if (state != kClosed)
+    return OpenOutcome::kFailed;
+
+  if (params.format() != AudioParameters::AUDIO_PCM_LINEAR &&
+      params.format() != AudioParameters::AUDIO_PCM_LOW_LATENCY) {
+    LOG(WARNING) << "Unsupported audio format.";
+    return OpenOutcome::kFailed;
+  }
+
+  sio_initpar(&par);
+  par.rate = params.sample_rate();
+  par.rchan = params.channels();
+  par.bits = SampleFormatToBitsPerChannel(kSampleFormat);
+  par.bps = par.bits / 8;
+  par.sig = sig = par.bits != 8 ? 1 : 0;
+  par.le = SIO_LE_NATIVE;
+  par.appbufsz = params.frames_per_buffer();
+
+  hdl = sio_open(SIO_DEVANY, SIO_REC, 0);
+
+  if (hdl == NULL) {
+    LOG(ERROR) << "Couldn't open audio device.";
+    return OpenOutcome::kFailed;
+  }
+
+  if (!sio_setpar(hdl, &par) || !sio_getpar(hdl, &par)) {
+    LOG(ERROR) << "Couldn't set audio parameters.";
+    goto bad_close;
+  }
+
+  if (par.rate  != (unsigned int)params.sample_rate() ||
+      par.rchan != (unsigned int)params.channels() ||
+      par.bits  != (unsigned int)SampleFormatToBitsPerChannel(kSampleFormat) ||
+      par.sig   != (unsigned int)sig ||
+      (par.bps > 1 && par.le != SIO_LE_NATIVE) ||
+      (par.bits != par.bps * 8)) {
+    LOG(ERROR) << "Unsupported audio parameters.";
+    goto bad_close;
+  }
+  state = kStopped;
+  buffer = new char[audio_bus->frames() * params.GetBytesPerFrame(kSampleFormat)];
+  sio_onmove(hdl, &OnMoveCallback, this);
+  return OpenOutcome::kSuccess;
+bad_close:
+  sio_close(hdl);
+  return OpenOutcome::kFailed;
+}
+
+void SndioAudioInputStream::Start(AudioInputCallback* cb) {
+
+  StartAgc();
+
+  state = kRunning;
+  hw_delay = 0;
+  callback = cb;
+  sio_start(hdl);
+  if (pthread_create(&thread, NULL, &ThreadEntry, this) != 0) {
+    LOG(ERROR) << "Failed to create real-time thread for recording.";
+    sio_stop(hdl);
+    state = kStopped;
+  }
+}
+
+void SndioAudioInputStream::Stop() {
+
+  if (state == kStopped)
+    return;
+
+  state = kStopWait;
+  pthread_join(thread, NULL);
+  sio_stop(hdl);
+  state = kStopped;
+
+  StopAgc();
+}
+
+void SndioAudioInputStream::Close() {
+
+  if (state == kClosed)
+    goto release;
+
+  if (state == kRunning)
+    Stop();
+
+  state = kClosed;
+  delete [] buffer;
+  sio_close(hdl);
+
+release:
+  manager->ReleaseInputStream(this);
+}
+
+double SndioAudioInputStream::GetMaxVolume() {
+  // Not supported
+  return 0.0;
+}
+
+void SndioAudioInputStream::SetVolume(double volume) {
+  // Not supported. Do nothing.
+}
+
+double SndioAudioInputStream::GetVolume() {
+  // Not supported.
+  return 0.0;
+}
+
+bool SndioAudioInputStream::IsMuted() {
+  // Not supported.
+  return false;
+}
+
+void SndioAudioInputStream::SetOutputDeviceForAec(
+    const std::string& output_device_id) {
+  // Not supported.
+}
+
+void SndioAudioInputStream::ThreadLoop(void) {
+  size_t todo, n;
+  char *data;
+  unsigned int nframes;
+  double normalized_volume = 0.0;
+
+  nframes = audio_bus->frames();
+
+  while (state == kRunning && !sio_eof(hdl)) {
+
+    GetAgcVolume(&normalized_volume);
+
+    // read one block
+    todo = nframes * params.GetBytesPerFrame(kSampleFormat);
+    data = buffer;
+    while (todo > 0) {
+      n = sio_read(hdl, data, todo);
+      if (n == 0)
+        return;	// unrecoverable I/O error
+      todo -= n;
+      data += n;
+    }
+    hw_delay -= nframes;
+
+    // convert frames count to TimeDelta
+    const base::TimeDelta delay = AudioTimestampHelper::FramesToTime(hw_delay,
+      params.sample_rate());
+
+    // push into bus
+    audio_bus->FromInterleaved<SignedInt16SampleTypeTraits>(reinterpret_cast<int16_t*>(buffer), nframes);
+
+
+    // invoke callback
+    callback->OnData(audio_bus.get(), base::TimeTicks::Now() - delay, 1., {});
+  }
+}
+
+}  // namespace media
