mssndcard.c 9.59 KB
Newer Older
aymeric's avatar
aymeric committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/*
mediastreamer2 library - modular sound and video processing and streaming
Copyright (C) 2006  Simon MORLAT (simon.morlat@linphone.org)

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
17
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
aymeric's avatar
aymeric committed
18 19 20 21 22 23
*/

#ifdef HAVE_CONFIG_H
#include "mediastreamer-config.h"
#endif

Simon Morlat's avatar
Simon Morlat committed
24 25
#include "mediastreamer2/mssndcard.h"

aymeric's avatar
aymeric committed
26

27
MSSndCardManager * ms_snd_card_manager_new(void){
28
	MSSndCardManager *obj=(MSSndCardManager *)ms_new0(MSSndCardManager,1);
29
	obj->factory = NULL;
aymeric's avatar
aymeric committed
30
	obj->cards=NULL;
31
	obj->descs=NULL;
aymeric's avatar
aymeric committed
32 33 34
	return obj;
}

35
void ms_snd_card_manager_destroy(MSSndCardManager* scm){
aymeric's avatar
aymeric committed
36
	if (scm!=NULL){
37
		bctbx_list_t *elem;
38 39 40 41 42
		for(elem=scm->descs;elem!=NULL;elem=elem->next){
			MSSndCardDesc *desc = (MSSndCardDesc*)elem->data;
			if (desc->unload!=NULL)
				desc->unload(scm);
		}
43 44 45
		bctbx_list_for_each(scm->cards,(void (*)(void*))ms_snd_card_destroy);
		bctbx_list_free(scm->cards);
		bctbx_list_free(scm->descs);
aymeric's avatar
aymeric committed
46 47 48 49 50
	}
	ms_free(scm);
	scm=NULL;
}

51 52
MSFactory * ms_snd_card_get_factory(MSSndCard * c){
	return c->sndcardmanager->factory;
53 54
}

aymeric's avatar
aymeric committed
55
MSSndCard * ms_snd_card_manager_get_card(MSSndCardManager *m, const char *id){
56
	bctbx_list_t *elem;
aymeric's avatar
aymeric committed
57 58 59 60 61 62 63 64 65
	for (elem=m->cards;elem!=NULL;elem=elem->next){
		MSSndCard *card=(MSSndCard*)elem->data;
		if (id==NULL) return card;
		if (strcmp(ms_snd_card_get_string_id(card),id)==0)	return card;
	}
	if (id!=NULL) ms_warning("no card with id %s",id);
	return NULL;
}

Simon Morlat's avatar
Simon Morlat committed
66
static MSSndCard *get_card_with_cap(MSSndCardManager *m, const char *id, unsigned int caps){
67
	bctbx_list_t *elem;
aymeric's avatar
aymeric committed
68 69
	for (elem=m->cards;elem!=NULL;elem=elem->next){
		MSSndCard *card=(MSSndCard*)elem->data;
Simon Morlat's avatar
Simon Morlat committed
70
		if ((id== NULL || strcmp(ms_snd_card_get_string_id(card),id)==0) && (card->capabilities & caps) == caps)	return card;
aymeric's avatar
aymeric committed
71 72 73 74
	}
	return NULL;
}

Simon Morlat's avatar
Simon Morlat committed
75 76 77 78 79
MSSndCard * ms_snd_card_manager_get_playback_card(MSSndCardManager *m, const char *id){
	MSSndCard *ret;
	ret = get_card_with_cap(m, id, MS_SND_CARD_CAP_PLAYBACK);
	if (ret) return ret;
	if (id != NULL) ms_warning("No playback card with id %s",id);
80 81 82
	return NULL;
}

Simon Morlat's avatar
Simon Morlat committed
83 84 85 86 87
MSSndCard * ms_snd_card_manager_get_capture_card(MSSndCardManager *m, const char *id){
	MSSndCard *ret;
	ret = get_card_with_cap(m, id, MS_SND_CARD_CAP_CAPTURE);
	if (ret) return ret;
	if (id != NULL) ms_warning("No capture card with id %s",id);
88 89 90
	return NULL;
}

Simon Morlat's avatar
Simon Morlat committed
91 92 93 94 95 96 97 98 99 100 101 102 103
MSSndCard * ms_snd_card_manager_get_default_card(MSSndCardManager *m){
	/*return the first card that has the capture+playback capability */
	return get_card_with_cap(m, NULL, MS_SND_CARD_CAP_PLAYBACK | MS_SND_CARD_CAP_CAPTURE);
}

MSSndCard * ms_snd_card_manager_get_default_capture_card(MSSndCardManager *m){
	return get_card_with_cap(m, NULL, MS_SND_CARD_CAP_CAPTURE);
}

MSSndCard * ms_snd_card_manager_get_default_playback_card(MSSndCardManager *m){
	return get_card_with_cap(m, NULL, MS_SND_CARD_CAP_PLAYBACK);
}

104
const bctbx_list_t * ms_snd_card_manager_get_list(MSSndCardManager *m){
aymeric's avatar
aymeric committed
105 106 107
	return m->cards;
}

108
void ms_snd_card_set_manager(MSSndCardManager*m, MSSndCard *c){
109
	if (c->sndcardmanager == NULL) c->sndcardmanager = m;
110 111
}

Simon Morlat's avatar
Simon Morlat committed
112 113 114 115 116 117 118
static const char *cap_to_string(unsigned int cap){
	if ((cap & MS_SND_CARD_CAP_CAPTURE) && (cap & MS_SND_CARD_CAP_PLAYBACK)) return "capture, playback";
	if (cap & MS_SND_CARD_CAP_CAPTURE) return "capture";
	if (cap & MS_SND_CARD_CAP_PLAYBACK) return "playback";
	return "none";
}

aymeric's avatar
aymeric committed
119
void ms_snd_card_manager_add_card(MSSndCardManager *m, MSSndCard *c){
120
	ms_snd_card_set_manager(m,c);
Simon Morlat's avatar
Simon Morlat committed
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);
aymeric's avatar
aymeric committed
123 124
}

125 126 127 128 129 130
void ms_snd_card_manager_prepend_card(MSSndCardManager *m, MSSndCard *c){
	ms_snd_card_set_manager(m,c);
	ms_message("Card '%s' prepended with capabilities [%s]",ms_snd_card_get_string_id(c), cap_to_string(c->capabilities));
	m->cards=bctbx_list_prepend(m->cards,c);
}

131 132 133 134
void ms_snd_card_manager_prepend_cards(MSSndCardManager *m, bctbx_list_t *l) {
	bctbx_list_t *elem;
	bctbx_list_t *lcopy = bctbx_list_copy(l);
	if (m->cards != NULL) m->cards = bctbx_list_concat(lcopy, m->cards);
135
	else m->cards = lcopy;
136 137
	for (elem = l; elem != NULL; elem = elem->next) {
		MSSndCard *card = (MSSndCard *)elem->data;
138
		ms_snd_card_set_manager(m, card);
139 140 141 142
		ms_message("Card '%s' added", ms_snd_card_get_string_id(card));
	}
}

143
static void card_detect(MSSndCardManager *m, MSSndCardDesc *desc){
aymeric's avatar
aymeric committed
144 145 146 147
	if (desc->detect!=NULL)
		desc->detect(m);
}

148
void ms_snd_card_manager_register_desc(MSSndCardManager *m, MSSndCardDesc *desc){
149 150
	if (bctbx_list_find(m->descs, desc) == NULL){
		m->descs=bctbx_list_append(m->descs,desc);
151 152
		card_detect(m,desc);
	}
153 154 155
}

void ms_snd_card_manager_reload(MSSndCardManager *m){
156 157 158
	bctbx_list_t *elem;
	bctbx_list_for_each(m->cards,(void (*)(void*))ms_snd_card_destroy);
	bctbx_list_free(m->cards);
159 160 161 162 163
	m->cards=NULL;
	for(elem=m->descs;elem!=NULL;elem=elem->next)
		card_detect(m,(MSSndCardDesc*)elem->data);
}

aymeric's avatar
aymeric committed
164 165 166 167 168 169 170 171
MSSndCard * ms_snd_card_dup(MSSndCard *card){
	MSSndCard *obj=NULL;
	if (card->desc->duplicate!=NULL)
		obj=card->desc->duplicate(card);
	return obj;
}

MSSndCard * ms_snd_card_new(MSSndCardDesc *desc){
172 173 174 175
	return ms_snd_card_new_with_name(desc,NULL);
}

MSSndCard * ms_snd_card_new_with_name(MSSndCardDesc *desc,const char* name) {
Simon Morlat's avatar
Simon Morlat committed
176
	MSSndCard *obj=(MSSndCard *)ms_new0(MSSndCard,1);
177
	obj->sndcardmanager = NULL;
aymeric's avatar
aymeric committed
178
	obj->desc=desc;
179
	obj->name=name?ms_strdup(name):NULL;
aymeric's avatar
aymeric committed
180 181 182
	obj->data=NULL;
	obj->id=NULL;
	obj->capabilities=MS_SND_CARD_CAP_CAPTURE|MS_SND_CARD_CAP_PLAYBACK;
183
	obj->streamType=MS_SND_CARD_STREAM_VOICE;
aymeric's avatar
aymeric committed
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
	if (desc->init!=NULL)
		desc->init(obj);
	return obj;
}

const char *ms_snd_card_get_driver_type(const MSSndCard *obj){
	return obj->desc->driver_type;
}

const char *ms_snd_card_get_name(const MSSndCard *obj){
	return obj->name;
}

unsigned int ms_snd_card_get_capabilities(const MSSndCard *obj){
	return obj->capabilities;
}

Simon Morlat's avatar
Simon Morlat committed
201 202 203 204
MS2_PUBLIC int ms_snd_card_get_minimal_latency(MSSndCard *obj){
	return obj->latency;
}

aymeric's avatar
aymeric committed
205 206 207 208 209 210 211 212
const char *ms_snd_card_get_string_id(MSSndCard *obj){
	if (obj->id==NULL)	obj->id=ms_strdup_printf("%s: %s",obj->desc->driver_type,obj->name);
	return obj->id;
}

void ms_snd_card_set_level(MSSndCard *obj, MSSndCardMixerElem e, int percent){
	if (obj->desc->set_level!=NULL)
		obj->desc->set_level(obj,e,percent);
213
	else ms_warning("ms_snd_card_set_level: unimplemented by %s wrapper",obj->desc->driver_type);
aymeric's avatar
aymeric committed
214 215 216 217 218 219
}

int ms_snd_card_get_level(MSSndCard *obj, MSSndCardMixerElem e){
	if (obj->desc->get_level!=NULL)
		return obj->desc->get_level(obj,e);
	else {
220
		ms_warning("ms_snd_card_get_level: unimplemented by %s wrapper",obj->desc->driver_type);
aymeric's avatar
aymeric committed
221 222 223 224 225 226 227 228 229 230
		return -1;
	}
}

void ms_snd_card_set_capture(MSSndCard *obj, MSSndCardCapture c){
	if (obj->desc->set_capture!=NULL)
		obj->desc->set_capture(obj,c);
	else ms_warning("ms_snd_card_set_capture: unimplemented by %s wrapper",obj->desc->driver_type);
}

231
int ms_snd_card_set_control(MSSndCard *obj, MSSndCardControlElem e, int val)
232 233
{
	if (obj->desc->set_control!=NULL)
234 235 236 237 238
		return obj->desc->set_control(obj,e,val);
	else {
		ms_warning("ms_snd_card_set_control: unimplemented by %s wrapper",obj->desc->driver_type);
		return -1;
	}
239 240 241 242 243 244 245 246 247 248 249 250
}

int ms_snd_card_get_control(MSSndCard *obj, MSSndCardControlElem e)
{
	if (obj->desc->get_control!=NULL)
		return obj->desc->get_control(obj,e);
	else {
		ms_warning("ms_snd_card_get_control: unimplemented by %s wrapper",obj->desc->driver_type);
		return -1;
	}
}

aymeric's avatar
aymeric committed
251 252 253 254 255 256 257 258 259 260 261 262 263 264
struct _MSFilter * ms_snd_card_create_reader(MSSndCard *obj){
	if (obj->desc->create_reader!=NULL)
		return obj->desc->create_reader(obj);
	else ms_warning("ms_snd_card_create_reader: unimplemented by %s wrapper",obj->desc->driver_type);
	return NULL;
}

struct _MSFilter * ms_snd_card_create_writer(MSSndCard *obj){
	if (obj->desc->create_writer!=NULL)
		return obj->desc->create_writer(obj);
	else ms_warning("ms_snd_card_create_writer: unimplemented by %s wrapper",obj->desc->driver_type);
	return NULL;
}

265 266
void ms_snd_card_set_usage_hint(MSSndCard *obj, bool_t is_going_to_be_used){
	if (obj->desc->usage_hint!=NULL)
Ghislain MARY's avatar
Ghislain MARY committed
267
		obj->desc->usage_hint(obj, is_going_to_be_used);
268 269
}

aymeric's avatar
aymeric committed
270 271 272 273 274 275 276
void ms_snd_card_destroy(MSSndCard *obj){
	if (obj->desc->uninit!=NULL) obj->desc->uninit(obj);
	if (obj->name!=NULL) ms_free(obj->name);
	if (obj->id!=NULL)	ms_free(obj->id);
	ms_free(obj);
}

jehan's avatar
jehan committed
277 278 279 280 281
int ms_snd_card_get_preferred_sample_rate(const MSSndCard *obj) {
	return obj->preferred_sample_rate;
}

int ms_snd_card_set_preferred_sample_rate(MSSndCard *obj,int rate) {
282
	obj->preferred_sample_rate=rate;
jehan's avatar
jehan committed
283 284 285
	return 0;
}

286 287 288 289 290 291 292 293
void ms_snd_card_set_stream_type(MSSndCard *obj, MSSndCardStreamType type) {
	obj->streamType = type;
}

MSSndCardStreamType ms_snd_card_get_stream_type(MSSndCard *obj) {
	return obj->streamType;
}

aymeric's avatar
aymeric committed
294 295 296 297 298 299
#ifdef __linux
#ifndef __ALSA_ENABLED__
MSSndCard * ms_alsa_card_new_custom(const char *pcmdev, const char *mixdev){
	ms_warning("Alsa support not available in this build of mediastreamer2");
	return NULL;
}
300 301 302 303

void ms_alsa_card_set_forced_sample_rate(int samplerate){
	ms_warning("Alsa support not available in this build of mediastreamer2");
}
aymeric's avatar
aymeric committed
304 305
#endif
#endif
306

Ghislain MARY's avatar
Ghislain MARY committed
307 308 309
#ifdef _MSC_VER
#pragma warning(disable : 4996)
#else
310
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
Ghislain MARY's avatar
Ghislain MARY committed
311
#endif
312 313 314 315 316

MSSndCardManager* ms_snd_card_manager_get(void) {
	return ms_factory_get_snd_card_manager(ms_factory_get_fallback());
}