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