mssndcard.c 7.75 KB
Newer Older
aymeric's avatar
aymeric committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/*
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
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

#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
static MSSndCardManager *scm=NULL;

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

void ms_snd_card_manager_destroy(void){
	if (scm!=NULL){
37 38 39 40 41 42
		MSList *elem;
		for(elem=scm->descs;elem!=NULL;elem=elem->next){
			MSSndCardDesc *desc = (MSSndCardDesc*)elem->data;
			if (desc->unload!=NULL)
				desc->unload(scm);
		}
aymeric's avatar
aymeric committed
43 44
		ms_list_for_each(scm->cards,(void (*)(void*))ms_snd_card_destroy);
		ms_list_free(scm->cards);
45
		ms_list_free(scm->descs);
aymeric's avatar
aymeric committed
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
	}
	ms_free(scm);
	scm=NULL;
}

MSSndCardManager * ms_snd_card_manager_get(void){
	if (scm==NULL) scm=create_manager();
	return scm;
}

MSSndCard * ms_snd_card_manager_get_card(MSSndCardManager *m, const char *id){
	MSList *elem;
	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;
}

MSSndCard * ms_snd_card_manager_get_default_card(MSSndCardManager *m){
	/*return the first card that has the capture+playback capability */
	MSList *elem;
	for (elem=m->cards;elem!=NULL;elem=elem->next){
		MSSndCard *card=(MSSndCard*)elem->data;
smorlat's avatar
smorlat committed
72 73
		if ((card->capabilities & MS_SND_CARD_CAP_CAPTURE )
			&& (card->capabilities & MS_SND_CARD_CAP_PLAYBACK))
aymeric's avatar
aymeric committed
74 75 76 77 78
			return card;
	}
	return NULL;
}

79 80 81 82
MSSndCard * ms_snd_card_manager_get_default_capture_card(MSSndCardManager *m){
	MSList *elem;
	for (elem=m->cards;elem!=NULL;elem=elem->next){
		MSSndCard *card=(MSSndCard*)elem->data;
smorlat's avatar
smorlat committed
83
		if (card->capabilities & MS_SND_CARD_CAP_CAPTURE)
84 85 86 87 88 89 90 91 92
			return card;
	}
	return NULL;
}

MSSndCard * ms_snd_card_manager_get_default_playback_card(MSSndCardManager *m){
	MSList *elem;
	for (elem=m->cards;elem!=NULL;elem=elem->next){
		MSSndCard *card=(MSSndCard*)elem->data;
smorlat's avatar
smorlat committed
93
		if (card->capabilities & MS_SND_CARD_CAP_PLAYBACK)
94 95 96 97 98
			return card;
	}
	return NULL;
}

aymeric's avatar
aymeric committed
99 100 101 102 103
const MSList * ms_snd_card_manager_get_list(MSSndCardManager *m){
	return m->cards;
}

void ms_snd_card_manager_add_card(MSSndCardManager *m, MSSndCard *c){
104
	ms_message("Card '%s' added",ms_snd_card_get_string_id(c));
aymeric's avatar
aymeric committed
105 106 107
	m->cards=ms_list_append(m->cards,c);
}

108 109 110
void ms_snd_card_manager_prepend_cards(MSSndCardManager *m, MSList *l) {
	MSList *elem;
	MSList *lcopy = ms_list_copy(l);
111 112
	if (m->cards != NULL) m->cards = ms_list_concat(lcopy, m->cards);
	else m->cards = lcopy;
113 114 115 116 117 118
	for (elem = l; elem != NULL; elem = elem->next) {
		MSSndCard *card = (MSSndCard *)elem->data;
		ms_message("Card '%s' added", ms_snd_card_get_string_id(card));
	}
}

119
static void card_detect(MSSndCardManager *m, MSSndCardDesc *desc){
aymeric's avatar
aymeric committed
120 121 122 123
	if (desc->detect!=NULL)
		desc->detect(m);
}

124 125 126 127 128 129 130 131 132 133 134 135 136 137
void ms_snd_card_manager_register_desc(MSSndCardManager *m, MSSndCardDesc *desc){
	m->descs=ms_list_append(m->descs,desc);
	card_detect(m,desc);
}

void ms_snd_card_manager_reload(MSSndCardManager *m){
	MSList *elem;
	ms_list_for_each(m->cards,(void (*)(void*))ms_snd_card_destroy);
	ms_list_free(m->cards);
	m->cards=NULL;
	for(elem=m->descs;elem!=NULL;elem=elem->next)
		card_detect(m,(MSSndCardDesc*)elem->data);
}

aymeric's avatar
aymeric committed
138 139 140 141 142 143 144 145
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){
jehan's avatar
jehan committed
146 147 148 149
	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
150
	MSSndCard *obj=(MSSndCard *)ms_new0(MSSndCard,1);
aymeric's avatar
aymeric committed
151
	obj->desc=desc;
jehan's avatar
jehan committed
152
	obj->name=name?ms_strdup(name):NULL;
aymeric's avatar
aymeric committed
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
	obj->data=NULL;
	obj->id=NULL;
	obj->capabilities=MS_SND_CARD_CAP_CAPTURE|MS_SND_CARD_CAP_PLAYBACK;
	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
173 174 175 176
MS2_PUBLIC int ms_snd_card_get_minimal_latency(MSSndCard *obj){
	return obj->latency;
}

aymeric's avatar
aymeric committed
177 178 179 180 181 182 183 184
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);
185
	else ms_warning("ms_snd_card_set_level: unimplemented by %s wrapper",obj->desc->driver_type);
aymeric's avatar
aymeric committed
186 187 188 189 190 191
}

int ms_snd_card_get_level(MSSndCard *obj, MSSndCardMixerElem e){
	if (obj->desc->get_level!=NULL)
		return obj->desc->get_level(obj,e);
	else {
192
		ms_warning("ms_snd_card_get_level: unimplemented by %s wrapper",obj->desc->driver_type);
aymeric's avatar
aymeric committed
193 194 195 196 197 198 199 200 201 202
		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);
}

203
int ms_snd_card_set_control(MSSndCard *obj, MSSndCardControlElem e, int val)
204 205
{
	if (obj->desc->set_control!=NULL)
206 207 208 209 210
		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;
	}
211 212 213 214 215 216 217 218 219 220 221 222
}

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
223 224 225 226 227 228 229 230 231 232 233 234 235 236
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;
}

237 238
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
239
		obj->desc->usage_hint(obj, is_going_to_be_used);
240 241
}

aymeric's avatar
aymeric committed
242 243 244 245 246 247 248
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
249 250 251 252 253
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) {
254
	obj->preferred_sample_rate=rate;
jehan's avatar
jehan committed
255 256 257
	return 0;
}

aymeric's avatar
aymeric committed
258 259 260 261 262 263
#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;
}
264 265 266 267

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
268 269
#endif
#endif