1 // AMixer.cc, Petr Hlavka, 2004
6 #include <alsa/asoundlib.h>
11 static bool mixerChangeIndicator
= false;
12 static bool mixerReinitIndicator
= false;
13 static int mixerCallback(snd_mixer_t
*ctl
, unsigned int mask
,
14 snd_mixer_elem_t
*elem
);
15 static int itemCallback(snd_mixer_elem_t
*elem
, unsigned int mask
);
18 AMixer::AMixer(const char *card
) {
22 cardName
= new char[std::strlen(card
)];
23 std::strcpy(cardName
, card
);
24 for (int i
= 0; i
< MIXER_ITEMS
; i
++)
27 if ((err
= snd_mixer_open(&mixerHandle
, 0)) < 0) {
28 error("snd_mixer_open error", err
);
33 if ((err
= snd_mixer_attach(mixerHandle
, card
)) < 0) {
34 error("snd_mixer_attach error", err
);
35 snd_mixer_close(mixerHandle
);
40 if ((err
= snd_mixer_selem_register(mixerHandle
, NULL
, NULL
)) < 0) {
41 error("snd_mixer_selem_register error", err
);
42 snd_mixer_close(mixerHandle
);
47 if ((err
= snd_mixer_load(mixerHandle
)) < 0) {
48 error("snd_mixer_load error", err
);
49 snd_mixer_close(mixerHandle
);
55 snd_mixer_set_callback(mixerHandle
, (snd_mixer_callback_t
) &mixerCallback
);
62 snd_mixer_free(mixerHandle
);
63 snd_mixer_detach(mixerHandle
, cardName
);
65 snd_mixer_close(mixerHandle
);
70 bool AMixer::opened() {
71 return (mixerHandle
!= NULL
);
75 void AMixer::error(const char *errorString
, int errorCode
) {
76 std::cerr
<< cardName
<< ": " << errorString
<< ": " << snd_strerror(errorCode
) << std::endl
;
80 void AMixer::handleEvents() {
81 snd_mixer_handle_events(mixerHandle
);
85 AItem
*AMixer::attachItem(unsigned int itemNumber
, const char *itemName
) {
86 if (itemNumber
>= MIXER_ITEMS
|| !itemName
)
89 // item was already created, so deregister callback and free it first
90 if (mixerItems
[itemNumber
]) {
91 snd_mixer_elem_set_callback(mixerItems
[itemNumber
]->aElem
, NULL
);
92 delete mixerItems
[itemNumber
];
95 // try to find item by name, register callback, return success
96 snd_mixer_elem_t
*elem
;
97 for (elem
= snd_mixer_first_elem(mixerHandle
); elem
; elem
= snd_mixer_elem_next(elem
)) {
98 if (snd_mixer_selem_is_active(elem
) &&
99 snd_mixer_elem_get_type(elem
) == SND_MIXER_ELEM_SIMPLE
&&
100 std::strcmp(snd_mixer_selem_get_name(elem
), itemName
) == 0) {
101 snd_mixer_elem_set_callback(elem
, (snd_mixer_elem_callback_t
) &itemCallback
);
102 return (mixerItems
[itemNumber
] = new AItem(this, elem
));
110 bool AMixer::itemOK(unsigned int itemNumber
) {
111 return (itemNumber
< MIXER_ITEMS
&& mixerItems
[itemNumber
]);
115 int AMixer::itemGetVolume(unsigned int itemNumber
) {
116 if (itemNumber
>= MIXER_ITEMS
|| !mixerItems
[itemNumber
])
119 return ((int) mixerItems
[itemNumber
]->getVolumePerc());
123 void AMixer::itemSetVolume(unsigned int itemNumber
, unsigned int volume
) {
124 if (itemNumber
< MIXER_ITEMS
&& mixerItems
[itemNumber
])
125 mixerItems
[itemNumber
]->setVolumePerc(volume
);
129 int AMixer::itemIsMuted(unsigned int itemNumber
) {
130 if (itemNumber
>= MIXER_ITEMS
|| !mixerItems
[itemNumber
])
133 return ((bool) mixerItems
[itemNumber
]->isMuted());
137 void AMixer::itemToggleMute(unsigned int itemNumber
) {
138 if (itemNumber
< MIXER_ITEMS
&& mixerItems
[itemNumber
]) {
139 if (itemIsMuted(itemNumber
))
140 mixerItems
[itemNumber
]->unmute();
142 mixerItems
[itemNumber
]->mute();
147 // return true if mixer elm sent callback and this callback wasn't picked up yet
148 bool AMixer::mixerElemsChanged() {
149 if (mixerChangeIndicator
) {
150 mixerChangeIndicator
= false;
159 // return true if mixer sent callback and this callback wasn't picked up yet
160 bool AMixer::mixerChanged() {
161 if (mixerReinitIndicator
) {
162 mixerReinitIndicator
= false;
171 // this function should be called after mixer callback, reInit all items
172 void AMixer::reInit() {
173 for (int i
= 0; i
< MIXER_ITEMS
; i
++)
174 this->attachItem(i
, mixerItems
[i
]->name
);
178 int mixerCallback(snd_mixer_t
*ctl
, unsigned int mask
,
179 snd_mixer_elem_t
*elem
) {
180 mixerReinitIndicator
= true;
186 int itemCallback(snd_mixer_elem_t
*elem
, unsigned int mask
) {
187 mixerChangeIndicator
= true;
193 char* AMixer::convertIDToCard(const char* cardId
) {
194 static char card
[32] = "";
195 int i
= snd_card_get_index(cardId
);
197 if (i
>= 0 && i
< 32)
198 std::snprintf(card
, 32, "hw:%i", i
);