Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/dom/media/gtest/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 10 kB image not shown  

Quelle  TestAudioDeviceEnumerator.cpp   Sprache: C

 
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#define ENABLE_SET_CUBEB_BACKEND 1
#include "CubebDeviceEnumerator.h"
#include "gtest/gtest-printers.h"
#include "gtest/gtest.h"
#include "mozilla/Attributes.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/media/MediaUtils.h"
#include "nsTArray.h"

#include "MockCubeb.h"

using namespace mozilla;
using AudioDeviceSet = CubebDeviceEnumerator::AudioDeviceSet;

const bool DEBUG_PRINTS = false;

enum DeviceOperation { ADD, REMOVE };

void TestEnumeration(MockCubeb* aMock, uint32_t aExpectedDeviceCount,
                     DeviceOperation aOperation, cubeb_device_type aType) {
  RefPtr<CubebDeviceEnumerator> enumerator =
      CubebDeviceEnumerator::GetInstance();

  RefPtr<const AudioDeviceSet> devices;

  if (aType == CUBEB_DEVICE_TYPE_INPUT) {
    devices = enumerator->EnumerateAudioInputDevices();
  }

  if (aType == CUBEB_DEVICE_TYPE_OUTPUT) {
    devices = enumerator->EnumerateAudioOutputDevices();
  }

  EXPECT_EQ(devices->Length(), aExpectedDeviceCount)
      << "Device count is correct when enumerating";

  if (DEBUG_PRINTS) {
    for (const auto& deviceInfo : *devices) {
      printf("=== Before removal\n");
      PrintDevice(deviceInfo);
    }
  }

  if (aOperation == DeviceOperation::REMOVE) {
    aMock->RemoveDevice(reinterpret_cast<cubeb_devid>(1));
  } else {
    aMock->AddDevice(DeviceTemplate(reinterpret_cast<cubeb_devid>(123), aType));
  }

  if (aType == CUBEB_DEVICE_TYPE_INPUT) {
    devices = enumerator->EnumerateAudioInputDevices();
  }

  if (aType == CUBEB_DEVICE_TYPE_OUTPUT) {
    devices = enumerator->EnumerateAudioOutputDevices();
  }

  uint32_t newExpectedDeviceCount = aOperation == DeviceOperation::REMOVE
                                        ? aExpectedDeviceCount - 1
                                        : aExpectedDeviceCount + 1;

  EXPECT_EQ(devices->Length(), newExpectedDeviceCount)
      << "Device count is correct when enumerating after operation";

  if (DEBUG_PRINTS) {
    for (const auto& deviceInfo : *devices) {
      printf("=== After removal\n");
      PrintDevice(deviceInfo);
    }
  }
}

#ifndef ANDROID
TEST(CubebDeviceEnumerator, EnumerateSimple)
{
  // It looks like we're leaking this object, but in fact it will be owned by
  // CubebUtils: `cubeb_destroy()` is called when `ForceSetCubebContext()` is
  // called again or when layout statics are shutdown, and we cast back to a
  // MockCubeb* and call the dtor.
  MockCubeb* mock = new MockCubeb();
  mozilla::CubebUtils::ForceSetCubebContext(mock->AsCubebContext());

  // We want to test whether CubebDeviceEnumerator works with and without a
  // backend that can notify of a device collection change via callback.
  // Additionally, we're testing that both adding and removing a device
  // invalidates the list correctly.
  bool supportsDeviceChangeCallback[2] = {truefalse};
  DeviceOperation operations[2] = {DeviceOperation::ADD,
                                   DeviceOperation::REMOVE};

  for (bool supports : supportsDeviceChangeCallback) {
    // Shutdown for `supports` to take effect
    CubebDeviceEnumerator::Shutdown();
    mock->SetSupportDeviceChangeCallback(supports);
    for (DeviceOperation op : operations) {
      uint32_t device_count = 4;

      cubeb_device_type deviceType = CUBEB_DEVICE_TYPE_INPUT;
      AddDevices(mock, device_count, deviceType);
      TestEnumeration(mock, device_count, op, deviceType);

      deviceType = CUBEB_DEVICE_TYPE_OUTPUT;
      AddDevices(mock, device_count, deviceType);
      TestEnumeration(mock, device_count, op, deviceType);
    }
  }
  // Shutdown to clean up the last `supports` effect
  CubebDeviceEnumerator::Shutdown();
}

TEST(CubebDeviceEnumerator, ZeroChannelDevices)
{
  MockCubeb* mock = new MockCubeb();
  mozilla::CubebUtils::ForceSetCubebContext(mock->AsCubebContext());

  // Create devices with different channel count, including 0-channel

  cubeb_device_info dev1 = DeviceTemplate(reinterpret_cast<cubeb_devid>(1),
                                          CUBEB_DEVICE_TYPE_INPUT, "dev 1");
  dev1.max_channels = 1;
  mock->AddDevice(dev1);

  cubeb_device_info dev2 = DeviceTemplate(reinterpret_cast<cubeb_devid>(2),
                                          CUBEB_DEVICE_TYPE_INPUT, "dev 2");
  dev2.max_channels = 0;
  mock->AddDevice(dev2);

  cubeb_device_info dev3 = DeviceTemplate(reinterpret_cast<cubeb_devid>(3),
                                          CUBEB_DEVICE_TYPE_OUTPUT, "dev 3");
  dev3.max_channels = 2;
  mock->AddDevice(dev3);

  cubeb_device_info dev4 = DeviceTemplate(reinterpret_cast<cubeb_devid>(4),
                                          CUBEB_DEVICE_TYPE_OUTPUT, "dev 4");
  dev4.max_channels = 0;
  mock->AddDevice(dev4);

  // Make sure the devices are added to cubeb.

  cubeb_device_collection inputCollection = {nullptr, 0};
  mock->EnumerateDevices(CUBEB_DEVICE_TYPE_INPUT, &inputCollection);
  EXPECT_EQ(inputCollection.count, 2U);
  EXPECT_EQ(inputCollection.device[0].devid, dev1.devid);
  EXPECT_EQ(inputCollection.device[1].devid, dev2.devid);
  mock->DestroyDeviceCollection(&inputCollection);
  EXPECT_EQ(inputCollection.count, 0U);

  cubeb_device_collection outputCollection = {nullptr, 0};
  mock->EnumerateDevices(CUBEB_DEVICE_TYPE_OUTPUT, &outputCollection);
  EXPECT_EQ(outputCollection.count, 2U);
  EXPECT_EQ(outputCollection.device[0].devid, dev3.devid);
  EXPECT_EQ(outputCollection.device[1].devid, dev4.devid);
  mock->DestroyDeviceCollection(&outputCollection);
  EXPECT_EQ(outputCollection.count, 0U);

  // Enumerate the devices. The result should exclude the 0-channel devices.

  RefPtr<CubebDeviceEnumerator> enumerator =
      CubebDeviceEnumerator::GetInstance();

  RefPtr<const AudioDeviceSet> inputDevices =
      enumerator->EnumerateAudioInputDevices();
  EXPECT_EQ(inputDevices->Length(), 1U);
  EXPECT_EQ(inputDevices->ElementAt(0)->DeviceID(), dev1.devid);
  EXPECT_EQ(inputDevices->ElementAt(0)->MaxChannels(), dev1.max_channels);

  RefPtr<const AudioDeviceSet> outputDevices =
      enumerator->EnumerateAudioOutputDevices();
  EXPECT_EQ(outputDevices->Length(), 1U);
  EXPECT_EQ(outputDevices->ElementAt(0)->DeviceID(), dev3.devid);
  EXPECT_EQ(outputDevices->ElementAt(0)->MaxChannels(), dev3.max_channels);
}

#else  // building for Android, which has no device enumeration support
TEST(CubebDeviceEnumerator, EnumerateAndroid)
{
  MockCubeb* mock = new MockCubeb();
  mozilla::CubebUtils::ForceSetCubebContext(mock->AsCubebContext());

  RefPtr<CubebDeviceEnumerator> enumerator =
      CubebDeviceEnumerator::GetInstance();

  RefPtr<const AudioDeviceSet> inputDevices =
      enumerator->EnumerateAudioInputDevices();
  EXPECT_EQ(inputDevices->Length(), 1u)
      << "Android always exposes a single input device.";
  EXPECT_EQ((*inputDevices)[0]->MaxChannels(), 1u) << "With a single channel.";
  EXPECT_EQ((*inputDevices)[0]->DeviceID(), nullptr)
      << "It's always the default input device.";
  EXPECT_TRUE((*inputDevices)[0]->Preferred())
      << "it's always the prefered input device.";

  RefPtr<const AudioDeviceSet> outputDevices =
      enumerator->EnumerateAudioOutputDevices();
  EXPECT_EQ(outputDevices->Length(), 1u)
      << "Android always exposes a single output device.";
  EXPECT_EQ((*outputDevices)[0]->MaxChannels(), 2u) << "With stereo channels.";
  EXPECT_EQ((*outputDevices)[0]->DeviceID(), nullptr)
      << "It's always the default output device.";
  EXPECT_TRUE((*outputDevices)[0]->Preferred())
      << "it's always the prefered output device.";
}
#endif

TEST(CubebDeviceEnumerator, ForceNullCubebContext)
{
  mozilla::CubebUtils::ForceSetCubebContext(nullptr);
  RefPtr<CubebDeviceEnumerator> enumerator =
      CubebDeviceEnumerator::GetInstance();

  RefPtr inputDevices = enumerator->EnumerateAudioInputDevices();
  EXPECT_EQ(inputDevices->Length(), 0u)
      << "Enumeration must fail, input device list must be empty.";

  RefPtr outputDevices = enumerator->EnumerateAudioOutputDevices();
  EXPECT_EQ(outputDevices->Length(), 0u)
      << "Enumeration must fail, output device list must be empty.";

  // Shutdown to clean up the null context effect
  CubebDeviceEnumerator::Shutdown();
}

TEST(CubebDeviceEnumerator, DeviceInfoFromName)
{
  MockCubeb* mock = new MockCubeb();
  mozilla::CubebUtils::ForceSetCubebContext(mock->AsCubebContext());

  cubeb_device_type deviceTypes[2] = {CUBEB_DEVICE_TYPE_INPUT,
                                      CUBEB_DEVICE_TYPE_OUTPUT};

  bool supportsDeviceChangeCallback[2] = {truefalse};
  for (bool supports : supportsDeviceChangeCallback) {
    // Shutdown for `supports` to take effect
    CubebDeviceEnumerator::Shutdown();
    mock->SetSupportDeviceChangeCallback(supports);
    for (cubeb_device_type& deviceType : deviceTypes) {
      cubeb_devid id_1 = reinterpret_cast<cubeb_devid>(1);
      mock->AddDevice(DeviceTemplate(id_1, deviceType, "device name 1"));
      cubeb_devid id_2 = reinterpret_cast<cubeb_devid>(2);
      nsCString device_name = "device name 2"_ns;
      mock->AddDevice(DeviceTemplate(id_2, deviceType, device_name.get()));
      cubeb_devid id_3 = reinterpret_cast<cubeb_devid>(3);
      mock->AddDevice(DeviceTemplate(id_3, deviceType, "device name 3"));

      RefPtr<CubebDeviceEnumerator> enumerator =
          CubebDeviceEnumerator::GetInstance();

      EnumeratorSide side = (deviceType == CUBEB_DEVICE_TYPE_INPUT)
                                ? EnumeratorSide::INPUT
                                : EnumeratorSide::OUTPUT;
      RefPtr<AudioDeviceInfo> devInfo = enumerator->DeviceInfoFromName(
          NS_ConvertUTF8toUTF16(device_name), side);
      EXPECT_TRUE(devInfo) << "the device exist";
      EXPECT_EQ(devInfo->Name(), NS_ConvertUTF8toUTF16(device_name))
          << "verify the device";

      mock->RemoveDevice(id_2);

      devInfo = enumerator->DeviceInfoFromName(
          NS_ConvertUTF8toUTF16(device_name), side);
      EXPECT_FALSE(devInfo) << "the device does not exist any more";
    }
  }
  // Shutdown for `supports` to take effect
  CubebDeviceEnumerator::Shutdown();
}
#undef ENABLE_SET_CUBEB_BACKEND

Messung V0.5
C=94 H=92 G=92

¤ Dauer der Verarbeitung: 0.12 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.