ohmu
·
2026-10-15
1#include "sound.h"
2#include "common/debug.h"
3#include "common/io.h"
4
5#include <fcntl.h>
6#include <stdint.h>
7#include <unistd.h>
8#include <sys/audioio.h>
9#include <sys/ioctl.h>
10
11const char* ffDetectSound(FFSoundOptions* options, FFlist* devices) {
12 int defaultDev;
13 {
14 char audiop[12];
15 ssize_t plen = readlink("/dev/audio", audiop, ARRAY_SIZE(audiop));
16 if (plen < (ssize_t) strlen("audioN")) {
17 FF_DEBUG("readlink(/dev/audio) failed");
18 return "readlink(/dev/audio) failed";
19 }
20 defaultDev = audiop[plen - 1] - '0';
21 if (defaultDev < 0 || defaultDev > 9) {
22 FF_DEBUG("Invalid audio device");
23 return "Invalid audio device";
24 }
25 }
26
27 char path[] = "/dev/audio0";
28
29 for (int idev = 0; idev < 9; ++idev) {
30 bool isMain = idev == defaultDev;
31 if ((options->soundType & FF_SOUND_TYPE_MAIN) && !isMain) {
32 continue;
33 }
34
35 path[strlen("/dev/audio")] = (char) ('0' + idev);
36 FF_AUTO_CLOSE_FD int fd = open(path, O_RDWR | O_CLOEXEC);
37 if (fd < 0) {
38 break;
39 }
40
41 audio_device_t ad;
42 if (ioctl(fd, AUDIO_GETDEV, &ad) < 0) {
43 continue;
44 }
45
46 audio_info_t ai;
47 if (ioctl(fd, AUDIO_GETINFO, &ai) < 0) {
48 continue;
49 }
50
51 FFSoundDevice* device = FF_LIST_ADD(FFSoundDevice, *devices);
52 ffStrbufInitS(&device->identifier, path);
53 ffStrbufInitS(&device->name, ad.name);
54 ffStrbufTrimRightSpace(&device->name);
55 ffStrbufInitF(&device->platformApi, "%s", "SunAudio");
56 device->volume = (uint8_t) ((ai.play.gain * 100 + AUDIO_MAX_GAIN / 2) / AUDIO_MAX_GAIN);
57 device->type = FF_SOUND_TYPE_ACTIVE | (isMain ? FF_SOUND_TYPE_MAIN : FF_SOUND_TYPE_NONE);
58 }
59
60 return nullptr;
61}