ohmu
·
2026-10-15
1extern "C" {
2#include "sound.h"
3#include "common/strutil.h"
4}
5#include <MediaAddOn.h>
6#include <MediaNode.h>
7#include <MediaRoster.h>
8#include <ParameterWeb.h>
9
10const char* ffDetectSound([[maybe_unused]] FFSoundOptions* options, FFlist* devices /* List of FFSoundDevice */) {
11 BMediaRoster* roster = BMediaRoster::Roster();
12 media_node mediaNode;
13 live_node_info liveInfo;
14 dormant_node_info dormantInfo;
15
16 if (roster->GetAudioOutput(&mediaNode) != B_OK) {
17 return nullptr;
18 }
19
20 FFSoundDevice* device = FF_LIST_ADD(FFSoundDevice, *devices);
21 ffStrbufInit(&device->identifier);
22 if (roster->GetDormantNodeFor(mediaNode, &dormantInfo) == B_OK) {
23 ffStrbufAppendS(&device->identifier, dormantInfo.name);
24 }
25 ffStrbufInit(&device->name);
26 if (roster->GetLiveNodeInfo(mediaNode, &liveInfo) == B_OK) {
27 ffStrbufAppendS(&device->name, liveInfo.name);
28 ffStrbufTrimRightSpace(&device->name);
29 }
30 ffStrbufInitStatic(&device->platformApi, "MediaKit");
31 // We'll check the Mixer actually
32 device->volume = 0;
33 device->type = (FFSoundType) (FF_SOUND_TYPE_ACTIVE | FF_SOUND_TYPE_MAIN);
34
35 roster->ReleaseNode(mediaNode);
36
37 media_node mixer;
38 if (roster->GetAudioMixer(&mixer) != B_OK) {
39 return nullptr;
40 }
41
42 BParameterWeb* web;
43 status_t status = roster->GetParameterWebFor(mixer, &web);
44 roster->ReleaseNode(mixer); // the web is all we need :-)
45 if (status != B_OK) {
46 return nullptr;
47 }
48
49 BContinuousParameter* gain = nullptr;
50 BParameter* mute = nullptr;
51 BParameter* parameter;
52 for (int32 index = 0; (parameter = web->ParameterAt(index)) != nullptr; index++) {
53 // assume the mute preceding master gain control
54 if (ffStrEquals(parameter->Kind(), B_MUTE)) {
55 mute = parameter;
56 }
57
58 if (ffStrEquals(parameter->Kind(), B_MASTER_GAIN)) {
59 // Can not use dynamic_cast due to fno-rtti
60 // gain = dynamic_cast<BContinuousParameter *>(parameter);
61 gain = (BContinuousParameter*) (parameter);
62 break;
63 }
64 }
65
66 if (gain == nullptr) {
67 return nullptr;
68 }
69
70 bigtime_t when;
71 size_t size;
72
73 if (mute) {
74 int32 isMute = false;
75 size = sizeof(isMute);
76 if (mute->GetValue(&isMute, &size, &when) == B_OK && isMute) {
77 return nullptr;
78 }
79 }
80
81 float volume = 0.0;
82 size = sizeof(volume);
83 if (gain->GetValue(&volume, &size, &when) == B_OK) {
84 device->volume = (uint8_t) (100 * (volume - gain->MinValue()) / (gain->MaxValue() - gain->MinValue()));
85 }
86
87 return nullptr;
88}