1 /*
2 mediastreamer2 library - modular sound and video processing and streaming
3 Copyright (C) 2006 Simon MORLAT (simon.morlat@linphone.org)
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
19
20 #ifdef HAVE_CONFIG_H
21 #include "mediastreamer-config.h"
22 #endif
23
24 #include "mediastreamer2/mssndcard.h"
25
26
ms_snd_card_manager_new(void)27 MSSndCardManager * ms_snd_card_manager_new(void){
28 MSSndCardManager *obj=(MSSndCardManager *)ms_new0(MSSndCardManager,1);
29 obj->factory = NULL;
30 obj->cards=NULL;
31 obj->descs=NULL;
32 return obj;
33 }
34
ms_snd_card_manager_destroy(MSSndCardManager * scm)35 void ms_snd_card_manager_destroy(MSSndCardManager* scm){
36 if (scm!=NULL){
37 bctbx_list_t *elem;
38 for(elem=scm->descs;elem!=NULL;elem=elem->next){
39 MSSndCardDesc *desc = (MSSndCardDesc*)elem->data;
40 if (desc->unload!=NULL)
41 desc->unload(scm);
42 }
43 bctbx_list_for_each(scm->cards,(void (*)(void*))ms_snd_card_destroy);
44 bctbx_list_free(scm->cards);
45 bctbx_list_free(scm->descs);
46 }
47 ms_free(scm);
48 scm=NULL;
49 }
50
ms_snd_card_get_factory(MSSndCard * c)51 MSFactory * ms_snd_card_get_factory(MSSndCard * c){
52 return c->sndcardmanager->factory;
53 }
54
ms_snd_card_manager_get_card(MSSndCardManager * m,const char * id)55 MSSndCard * ms_snd_card_manager_get_card(MSSndCardManager *m, const char *id){
56 bctbx_list_t *elem;
57 for (elem=m->cards;elem!=NULL;elem=elem->next){
58 MSSndCard *card=(MSSndCard*)elem->data;
59 if (id==NULL) return card;
60 if (strcmp(ms_snd_card_get_string_id(card),id)==0) return card;
61 }
62 if (id!=NULL) ms_warning("no card with id %s",id);
63 return NULL;
64 }
65
get_card_with_cap(MSSndCardManager * m,const char * id,unsigned int caps)66 static MSSndCard *get_card_with_cap(MSSndCardManager *m, const char *id, unsigned int caps){
67 bctbx_list_t *elem;
68 for (elem=m->cards;elem!=NULL;elem=elem->next){
69 MSSndCard *card=(MSSndCard*)elem->data;
70 if ((id== NULL || strcmp(ms_snd_card_get_string_id(card),id)==0) && (card->capabilities & caps) == caps) return card;
71 }
72 return NULL;
73 }
74
ms_snd_card_manager_get_playback_card(MSSndCardManager * m,const char * id)75 MSSndCard * ms_snd_card_manager_get_playback_card(MSSndCardManager *m, const char *id){
76 MSSndCard *ret;
77 ret = get_card_with_cap(m, id, MS_SND_CARD_CAP_PLAYBACK);
78 if (ret) return ret;
79 if (id != NULL) ms_warning("No playback card with id %s",id);
80 return NULL;
81 }
82
ms_snd_card_manager_get_capture_card(MSSndCardManager * m,const char * id)83 MSSndCard * ms_snd_card_manager_get_capture_card(MSSndCardManager *m, const char *id){
84 MSSndCard *ret;
85 ret = get_card_with_cap(m, id, MS_SND_CARD_CAP_CAPTURE);
86 if (ret) return ret;
87 if (id != NULL) ms_warning("No capture card with id %s",id);
88 return NULL;
89 }
90
ms_snd_card_manager_get_default_card(MSSndCardManager * m)91 MSSndCard * ms_snd_card_manager_get_default_card(MSSndCardManager *m){
92 /*return the first card that has the capture+playback capability */
93 return get_card_with_cap(m, NULL, MS_SND_CARD_CAP_PLAYBACK | MS_SND_CARD_CAP_CAPTURE);
94 }
95
ms_snd_card_manager_get_default_capture_card(MSSndCardManager * m)96 MSSndCard * ms_snd_card_manager_get_default_capture_card(MSSndCardManager *m){
97 return get_card_with_cap(m, NULL, MS_SND_CARD_CAP_CAPTURE);
98 }
99
ms_snd_card_manager_get_default_playback_card(MSSndCardManager * m)100 MSSndCard * ms_snd_card_manager_get_default_playback_card(MSSndCardManager *m){
101 return get_card_with_cap(m, NULL, MS_SND_CARD_CAP_PLAYBACK);
102 }
103
ms_snd_card_manager_get_list(MSSndCardManager * m)104 const bctbx_list_t * ms_snd_card_manager_get_list(MSSndCardManager *m){
105 return m->cards;
106 }
107
ms_snd_card_set_manager(MSSndCardManager * m,MSSndCard * c)108 void ms_snd_card_set_manager(MSSndCardManager*m, MSSndCard *c){
109 if (c->sndcardmanager == NULL) c->sndcardmanager = m;
110 }
111
cap_to_string(unsigned int cap)112 static const char *cap_to_string(unsigned int cap){
113 if ((cap & MS_SND_CARD_CAP_CAPTURE) && (cap & MS_SND_CARD_CAP_PLAYBACK)) return "capture, playback";
114 if (cap & MS_SND_CARD_CAP_CAPTURE) return "capture";
115 if (cap & MS_SND_CARD_CAP_PLAYBACK) return "playback";
116 return "none";
117 }
118
ms_snd_card_manager_add_card(MSSndCardManager * m,MSSndCard * c)119 void ms_snd_card_manager_add_card(MSSndCardManager *m, MSSndCard *c){
120 ms_snd_card_set_manager(m,c);
121 ms_message("Card '%s' added with capabilities [%s]",ms_snd_card_get_string_id(c), cap_to_string(c->capabilities));
122 m->cards=bctbx_list_append(m->cards,c);
123 }
124
ms_snd_card_manager_prepend_cards(MSSndCardManager * m,bctbx_list_t * l)125 void ms_snd_card_manager_prepend_cards(MSSndCardManager *m, bctbx_list_t *l) {
126 bctbx_list_t *elem;
127 bctbx_list_t *lcopy = bctbx_list_copy(l);
128 if (m->cards != NULL) m->cards = bctbx_list_concat(lcopy, m->cards);
129 else m->cards = lcopy;
130 for (elem = l; elem != NULL; elem = elem->next) {
131 MSSndCard *card = (MSSndCard *)elem->data;
132 ms_snd_card_set_manager(m, card);
133 ms_message("Card '%s' added", ms_snd_card_get_string_id(card));
134 }
135 }
136
card_detect(MSSndCardManager * m,MSSndCardDesc * desc)137 static void card_detect(MSSndCardManager *m, MSSndCardDesc *desc){
138 if (desc->detect!=NULL)
139 desc->detect(m);
140 }
141
ms_snd_card_manager_register_desc(MSSndCardManager * m,MSSndCardDesc * desc)142 void ms_snd_card_manager_register_desc(MSSndCardManager *m, MSSndCardDesc *desc){
143 if (bctbx_list_find(m->descs, desc) == NULL){
144 m->descs=bctbx_list_append(m->descs,desc);
145 card_detect(m,desc);
146 }
147 }
148
ms_snd_card_manager_reload(MSSndCardManager * m)149 void ms_snd_card_manager_reload(MSSndCardManager *m){
150 bctbx_list_t *elem;
151 bctbx_list_for_each(m->cards,(void (*)(void*))ms_snd_card_destroy);
152 bctbx_list_free(m->cards);
153 m->cards=NULL;
154 for(elem=m->descs;elem!=NULL;elem=elem->next)
155 card_detect(m,(MSSndCardDesc*)elem->data);
156 }
157
ms_snd_card_dup(MSSndCard * card)158 MSSndCard * ms_snd_card_dup(MSSndCard *card){
159 MSSndCard *obj=NULL;
160 if (card->desc->duplicate!=NULL)
161 obj=card->desc->duplicate(card);
162 return obj;
163 }
164
ms_snd_card_new(MSSndCardDesc * desc)165 MSSndCard * ms_snd_card_new(MSSndCardDesc *desc){
166 return ms_snd_card_new_with_name(desc,NULL);
167 }
168
ms_snd_card_new_with_name(MSSndCardDesc * desc,const char * name)169 MSSndCard * ms_snd_card_new_with_name(MSSndCardDesc *desc,const char* name) {
170 MSSndCard *obj=(MSSndCard *)ms_new0(MSSndCard,1);
171 obj->sndcardmanager = NULL;
172 obj->desc=desc;
173 obj->name=name?ms_strdup(name):NULL;
174 obj->data=NULL;
175 obj->id=NULL;
176 obj->capabilities=MS_SND_CARD_CAP_CAPTURE|MS_SND_CARD_CAP_PLAYBACK;
177 if (desc->init!=NULL)
178 desc->init(obj);
179 return obj;
180 }
181
ms_snd_card_get_driver_type(const MSSndCard * obj)182 const char *ms_snd_card_get_driver_type(const MSSndCard *obj){
183 return obj->desc->driver_type;
184 }
185
ms_snd_card_get_name(const MSSndCard * obj)186 const char *ms_snd_card_get_name(const MSSndCard *obj){
187 return obj->name;
188 }
189
ms_snd_card_get_capabilities(const MSSndCard * obj)190 unsigned int ms_snd_card_get_capabilities(const MSSndCard *obj){
191 return obj->capabilities;
192 }
193
ms_snd_card_get_minimal_latency(MSSndCard * obj)194 MS2_PUBLIC int ms_snd_card_get_minimal_latency(MSSndCard *obj){
195 return obj->latency;
196 }
197
ms_snd_card_get_string_id(MSSndCard * obj)198 const char *ms_snd_card_get_string_id(MSSndCard *obj){
199 if (obj->id==NULL) obj->id=ms_strdup_printf("%s: %s",obj->desc->driver_type,obj->name);
200 return obj->id;
201 }
202
ms_snd_card_set_level(MSSndCard * obj,MSSndCardMixerElem e,int percent)203 void ms_snd_card_set_level(MSSndCard *obj, MSSndCardMixerElem e, int percent){
204 if (obj->desc->set_level!=NULL)
205 obj->desc->set_level(obj,e,percent);
206 else ms_warning("ms_snd_card_set_level: unimplemented by %s wrapper",obj->desc->driver_type);
207 }
208
ms_snd_card_get_level(MSSndCard * obj,MSSndCardMixerElem e)209 int ms_snd_card_get_level(MSSndCard *obj, MSSndCardMixerElem e){
210 if (obj->desc->get_level!=NULL)
211 return obj->desc->get_level(obj,e);
212 else {
213 ms_warning("ms_snd_card_get_level: unimplemented by %s wrapper",obj->desc->driver_type);
214 return -1;
215 }
216 }
217
ms_snd_card_set_capture(MSSndCard * obj,MSSndCardCapture c)218 void ms_snd_card_set_capture(MSSndCard *obj, MSSndCardCapture c){
219 if (obj->desc->set_capture!=NULL)
220 obj->desc->set_capture(obj,c);
221 else ms_warning("ms_snd_card_set_capture: unimplemented by %s wrapper",obj->desc->driver_type);
222 }
223
ms_snd_card_set_control(MSSndCard * obj,MSSndCardControlElem e,int val)224 int ms_snd_card_set_control(MSSndCard *obj, MSSndCardControlElem e, int val)
225 {
226 if (obj->desc->set_control!=NULL)
227 return obj->desc->set_control(obj,e,val);
228 else {
229 ms_warning("ms_snd_card_set_control: unimplemented by %s wrapper",obj->desc->driver_type);
230 return -1;
231 }
232 }
233
ms_snd_card_get_control(MSSndCard * obj,MSSndCardControlElem e)234 int ms_snd_card_get_control(MSSndCard *obj, MSSndCardControlElem e)
235 {
236 if (obj->desc->get_control!=NULL)
237 return obj->desc->get_control(obj,e);
238 else {
239 ms_warning("ms_snd_card_get_control: unimplemented by %s wrapper",obj->desc->driver_type);
240 return -1;
241 }
242 }
243
ms_snd_card_create_reader(MSSndCard * obj)244 struct _MSFilter * ms_snd_card_create_reader(MSSndCard *obj){
245 if (obj->desc->create_reader!=NULL)
246 return obj->desc->create_reader(obj);
247 else ms_warning("ms_snd_card_create_reader: unimplemented by %s wrapper",obj->desc->driver_type);
248 return NULL;
249 }
250
ms_snd_card_create_writer(MSSndCard * obj)251 struct _MSFilter * ms_snd_card_create_writer(MSSndCard *obj){
252 if (obj->desc->create_writer!=NULL)
253 return obj->desc->create_writer(obj);
254 else ms_warning("ms_snd_card_create_writer: unimplemented by %s wrapper",obj->desc->driver_type);
255 return NULL;
256 }
257
ms_snd_card_set_usage_hint(MSSndCard * obj,bool_t is_going_to_be_used)258 void ms_snd_card_set_usage_hint(MSSndCard *obj, bool_t is_going_to_be_used){
259 if (obj->desc->usage_hint!=NULL)
260 obj->desc->usage_hint(obj, is_going_to_be_used);
261 }
262
ms_snd_card_destroy(MSSndCard * obj)263 void ms_snd_card_destroy(MSSndCard *obj){
264 if (obj->desc->uninit!=NULL) obj->desc->uninit(obj);
265 if (obj->name!=NULL) ms_free(obj->name);
266 if (obj->id!=NULL) ms_free(obj->id);
267 ms_free(obj);
268 }
269
ms_snd_card_get_preferred_sample_rate(const MSSndCard * obj)270 int ms_snd_card_get_preferred_sample_rate(const MSSndCard *obj) {
271 return obj->preferred_sample_rate;
272 }
273
ms_snd_card_set_preferred_sample_rate(MSSndCard * obj,int rate)274 int ms_snd_card_set_preferred_sample_rate(MSSndCard *obj,int rate) {
275 obj->preferred_sample_rate=rate;
276 return 0;
277 }
278
279 #ifdef __linux
280 #ifndef __ALSA_ENABLED__
ms_alsa_card_new_custom(const char * pcmdev,const char * mixdev)281 MSSndCard * ms_alsa_card_new_custom(const char *pcmdev, const char *mixdev){
282 ms_warning("Alsa support not available in this build of mediastreamer2");
283 return NULL;
284 }
285
ms_alsa_card_set_forced_sample_rate(int samplerate)286 void ms_alsa_card_set_forced_sample_rate(int samplerate){
287 ms_warning("Alsa support not available in this build of mediastreamer2");
288 }
289 #endif
290 #endif
291
292 #ifdef _MSC_VER
293 #pragma warning(disable : 4996)
294 #else
295 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
296 #endif
297
ms_snd_card_manager_get(void)298 MSSndCardManager* ms_snd_card_manager_get(void) {
299 return ms_factory_get_snd_card_manager(ms_factory_get_fallback());
300 }
301
302