-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathSndControl.cpp
More file actions
208 lines (181 loc) · 5.57 KB
/
Copy pathSndControl.cpp
File metadata and controls
208 lines (181 loc) · 5.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
/*! \file SndControl.cpp
*! \brief ALSA sound card control element C++ wrappers.
* 20210810,12,0902,03,04,06,12 - Philippe.Bekaert@uhasselt.be */
#include <iostream>
#include "SndControl.h"
#include "SndCard.h"
snd_hctl_elem_t* SndControl::Find(const class SndCard* card,
const std::string& name,
Interface iface,
unsigned index)
{
snd_ctl_elem_id_t *id;
snd_ctl_elem_id_alloca(&id);
snd_ctl_elem_id_set_name(id, name.c_str());
snd_ctl_elem_id_set_interface(id, (snd_ctl_elem_iface_t)iface);
snd_ctl_elem_id_set_index(id, index);
return Find(card, id);
}
snd_hctl_elem_t* SndControl::FindFromAsciiId(const class SndCard* card,
const std::string& asciiId)
{
snd_ctl_elem_id_t *id;
snd_ctl_elem_id_alloca(&id);
if (snd_ctl_ascii_elem_id_parse(id, asciiId.c_str()) < 0)
throw std::runtime_error("Failed to parse control element ASCII identifier '"
+ asciiId + "'.\n");
return Find(card, id);
}
snd_hctl_elem_t* SndControl::Find(const class SndCard* card,
snd_ctl_elem_id_t* id)
{
snd_hctl_elem_t* elem = snd_hctl_find_elem(card->hctl, id);
if (!elem) {
const std::string name = std::string(snd_ctl_elem_id_get_name(id));
snd_ctl_elem_iface_t iface = snd_ctl_elem_id_get_interface(id);
unsigned index = snd_ctl_elem_id_get_index(id);
throw std::runtime_error("No "
+ std::string(snd_ctl_elem_iface_name(iface))
+ " control element '"
+ std::string(name)
+ "' index " + std::to_string(index)
+ " found on card '"
+ std::string(card->getName()) + "'\n");
}
return elem;
}
SndControl* SndControl::Create(const class SndCard* card,
snd_hctl_elem_t* elem)
{
// get value type
snd_ctl_elem_info_t *info;
snd_ctl_elem_info_alloca(&info);
SndCheckErr(snd_hctl_elem_info(elem, info), "hctl_elem_info");
snd_ctl_elem_type_t type = snd_ctl_elem_info_get_type(info);
switch (type) {
case SND_CTL_ELEM_TYPE_BOOLEAN :
return new SndBoolControl(card, elem);
case SND_CTL_ELEM_TYPE_INTEGER :
return new SndIntControl(card, elem);
case SND_CTL_ELEM_TYPE_INTEGER64 :
return new SndInt64Control(card, elem);
case SND_CTL_ELEM_TYPE_ENUMERATED:
return new SndEnumControl(card, elem);
case SND_CTL_ELEM_TYPE_BYTES :
return new SndBytesControl(card, elem);
case SND_CTL_ELEM_TYPE_IEC958 :
return new SndIec958Control(card, elem);
default:
throw std::runtime_error("SndControl '"
+ std::string(snd_hctl_elem_get_name(elem))
+ "' on card '"
+ std::string(card->getName())
+ "' has unrecognized type "
+ std::to_string(type) + ".\n");
};
}
int SndControl::_elem_cb(snd_hctl_elem_t *elem, unsigned int mask)
{
SndControl* c = (SndControl*) snd_hctl_elem_get_callback_private(elem);
try {
c->onElemEvent(mask);
} catch (const std::runtime_error& e) {
std::cerr << e.what() << "\n";
} catch (...) {}
return 0;
}
SndControl::SndControl(const class SndCard* _card,
snd_hctl_elem_t* _elem)
: card(_card), elem(_elem)
{
name = std::string(snd_hctl_elem_get_name(elem));
// get value type and count
snd_ctl_elem_info_malloc(&info);
SndCheckErr(snd_hctl_elem_info(elem, info), "hctl_elem_info");
type = snd_ctl_elem_info_get_type(info);
count = snd_ctl_elem_info_get_count(info);
}
SndControl::~SndControl()
{
snd_hctl_elem_set_callback(elem, nullptr);
snd_ctl_elem_info_free(info);
}
void SndControl::checkChannel(unsigned i) const
{
if (i >= count) {
throw std::runtime_error("SndControl '" + name + "' on card '"
+ getCardName() + "' channel index "
+ std::to_string(i) + " out of range ("
+ std::to_string(count) + " channels available).\n");
}
}
const std::string SndControl::getCardName(void) const
{
return card->getName();
}
const std::string SndControl::getAsciiId(void) const
{
snd_ctl_elem_id_t* id;
snd_ctl_elem_id_alloca(&id);
getId(id);
return std::string(snd_ctl_ascii_elem_id_get(id));
}
int SndControl::getdBRange(long* min, long* max) const
{
snd_ctl_elem_id_t* id;
snd_ctl_elem_id_alloca(&id);
getId(id);
return snd_ctl_get_dB_range(*card, id, min, max);
}
int SndControl::convertTodB(long volume, long* db_gain) const
{
snd_ctl_elem_id_t* id;
snd_ctl_elem_id_alloca(&id);
getId(id);
return snd_ctl_convert_to_dB(*card, id, volume, db_gain);
}
int SndControl::convertFromdB(long db_gain, long* volume, int xdir) const
{
snd_ctl_elem_id_t* id;
snd_ctl_elem_id_alloca(&id);
getId(id);
return snd_ctl_convert_from_dB(*card, id, db_gain, volume, xdir);
}
bool SndControl::try_lock(void)
{
snd_ctl_elem_id_t* id;
snd_ctl_elem_id_alloca(&id);
getId(id);
int rc = snd_ctl_elem_lock(*card, id);
if (rc != 0 && rc != EBUSY)
SndCheckErr(rc, "ctl_elem_lock");
return rc == 0;
}
void SndControl::unlock(void)
{
snd_ctl_elem_id_t* id;
snd_ctl_elem_id_alloca(&id);
getId(id);
SndCheckErr(snd_ctl_elem_unlock(*card, id), "ctl_elem_unlock");
}
#ifdef NEVER
//#include <stdio.h>
//#include <sys/types.h>
void SndControl::ValueLocker::lock(void)
{
// pthread_mutex_t* pmtx = ctl->rmtx.native_handle();
if (!ctl->rmtx.try_lock()) {
// fprintf(stderr, "%s: thread %d waiting for lock held by %d.\n",
// ctl->name.c_str(), gettid(), pmtx->__data.__owner);
ctl->rmtx.lock();
// fprintf(stderr, "%s: thread %d locked.\n",
// ctl->getName().c_str(), gettid());
}
}
void SndControl::ValueLocker::unlock(void)
{
ctl->rmtx.unlock();
// fprintf(stderr, "%.3f %s: %s thread %d unlocked.\n",
// GetTime(), ctl->getName().c_str(), where, gettid());
}
#endif /*NEVER*/