- Timestamp:
- Feb 21, 2009 2:21:59 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia-audiodev/audiodev.c
r2464 r2468 20 20 #include <pjmedia-audiodev/audiodev_imp.h> 21 21 #include <pj/errno.h> 22 #include <pj/log.h> 23 #include <pj/string.h> 24 25 #define THIS_FILE "audiodev.c" 26 27 /* Capability names */ 28 static struct cap_info 29 { 30 const char *name; 31 const char *info; 32 } cap_infos[] = 33 { 34 {"ext-fmt", "Extended/non-PCM format"}, 35 {"latency-in", "Input latency/buffer size setting"}, 36 {"latency-out", "Output latency/buffer size setting"}, 37 {"vol-in", "Input volume setting"}, 38 {"vol-out", "Output volume setting"}, 39 {"meter-in", "Input meter"}, 40 {"meter-out", "Output meter"}, 41 {"route-in", "Input routing"}, 42 {"route-out", "Output routing"}, 43 {"aec", "Accoustic echo cancellation"}, 44 {"aec-tail", "Tail length setting for AEC"}, 45 {"vad", "Voice activity detection"}, 46 {"cng", "Comfort noise generation"}, 47 {"plg", "Packet loss concealment"} 48 }; 49 22 50 23 51 /* 24 * The Device IDseen by application and driver is different.52 * The device index seen by application and driver is different. 25 53 * 26 * At application level, device ID is a 32bit value. The high 16bit contains 27 * the factory ID, and the low 16bit contains the device index in the 28 * specified factory. The device ID may also be -1 to denote default device. 29 * 30 * At driver level, device ID is a 16bit unsigned integer index. 54 * At application level, device index is index to global list of device. 55 * At driver level, device index is index to device list on that particular 56 * factory only. 31 57 */ 32 58 #define MAKE_DEV_ID(f_id, index) (((f_id & 0xFFFF) << 16) | (index & 0xFFFF)) … … 41 67 42 68 #define MAX_DRIVERS 16 69 #define MAX_DEVS 64 70 71 /* typedef for factory creation function */ 72 typedef pjmedia_aud_dev_factory* (*create_func_ptr)(pj_pool_factory*); 73 74 /* driver structure */ 75 struct driver 76 { 77 create_func_ptr create; /* Creation function. */ 78 pjmedia_aud_dev_factory *f; /* Factory instance. */ 79 char name[32]; /* Driver name */ 80 unsigned dev_cnt; /* Number of devices */ 81 unsigned start_idx; /* Start index in global list */ 82 }; 43 83 44 84 /* The audio subsystem */ 45 85 static struct aud_subsys 46 86 { 47 unsigned init_count; 48 pj_pool_factory *pf; 49 unsigned factory_cnt; 50 51 struct factory 52 { 53 pjmedia_aud_dev_factory* (*create)(pj_pool_factory*); 54 pjmedia_aud_dev_factory *f; 55 56 } factories[MAX_DRIVERS]; 87 unsigned init_count; /* How many times init() is called */ 88 pj_pool_factory *pf; /* The pool factory. */ 89 90 unsigned drv_cnt; /* Number of drivers. */ 91 struct driver drv[MAX_DRIVERS]; /* Array of drivers. */ 92 93 unsigned dev_cnt; /* Total number of devices. */ 94 pj_uint32_t dev_list[MAX_DEVS];/* Array of device IDs. */ 57 95 58 96 } aud_subsys; … … 74 112 75 113 aud_subsys.pf = pf; 76 aud_subsys.factory_cnt = 0; 77 78 aud_subsys.factories[aud_subsys.factory_cnt++].create = &pjmedia_pa_factory; 79 aud_subsys.factories[aud_subsys.factory_cnt++].create = &pjmedia_wmme_factory; 80 81 for (i=0; i<aud_subsys.factory_cnt; ++i) { 114 aud_subsys.drv_cnt = 0; 115 aud_subsys.dev_cnt = 0; 116 117 /* Register creation functions */ 118 aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_pa_factory; 119 aud_subsys.drv[aud_subsys.drv_cnt++].create = &pjmedia_wmme_factory; 120 121 /* Initialize each factory and build the device ID list */ 122 for (i=0; i<aud_subsys.drv_cnt; ++i) { 82 123 pjmedia_aud_dev_factory *f; 83 84 f = (*aud_subsys.factories[i].create)(pf); 124 pjmedia_aud_dev_info info; 125 unsigned j, dev_cnt; 126 127 /* Create the factory */ 128 f = (*aud_subsys.drv[i].create)(pf); 85 129 if (!f) 86 130 continue; 87 131 132 /* Call factory->init() */ 88 133 status = f->op->init(f); 89 134 if (status != PJ_SUCCESS) { … … 92 137 } 93 138 94 aud_subsys.factories[i].f = f; 95 aud_subsys.factories[i].f->internal.id = i; 96 } 97 98 return aud_subsys.factory_cnt ? PJ_SUCCESS : status; 139 /* Build device list */ 140 dev_cnt = f->op->get_dev_count(f); 141 if (dev_cnt == 0) { 142 f->op->destroy(f); 143 continue; 144 } 145 146 /* Get one device info */ 147 status = f->op->get_dev_info(f, 0, &info); 148 if (status != PJ_SUCCESS) { 149 f->op->destroy(f); 150 continue; 151 } 152 153 /* Register the factory */ 154 aud_subsys.drv[i].f = f; 155 aud_subsys.drv[i].f->internal.id = i; 156 aud_subsys.drv[i].start_idx = aud_subsys.dev_cnt; 157 pj_ansi_strncpy(aud_subsys.drv[i].name, info.driver, 158 sizeof(aud_subsys.drv[i].name)); 159 aud_subsys.drv[i].name[sizeof(aud_subsys.drv[i].name)-1] = '\0'; 160 161 /* Register devices */ 162 if (aud_subsys.dev_cnt + dev_cnt > MAX_DEVS) { 163 PJ_LOG(4,(THIS_FILE, "%d device(s) cannot be registered because" 164 " there are too many sound devices", 165 aud_subsys.dev_cnt + dev_cnt - MAX_DEVS)); 166 dev_cnt = MAX_DEVS - aud_subsys.dev_cnt; 167 } 168 for (j=0; j<dev_cnt; ++j) { 169 aud_subsys.dev_list[aud_subsys.dev_cnt++] = MAKE_DEV_ID(i, j); 170 } 171 172 } 173 174 return aud_subsys.drv_cnt ? PJ_SUCCESS : status; 99 175 } 100 176 … … 118 194 --aud_subsys.init_count; 119 195 120 for (i=0; i<aud_subsys. factory_cnt; ++i) {121 pjmedia_aud_dev_factory *f = aud_subsys. factories[i].f;196 for (i=0; i<aud_subsys.drv_cnt; ++i) { 197 pjmedia_aud_dev_factory *f = aud_subsys.drv[i].f; 122 198 123 199 if (!f) … … 125 201 126 202 f->op->destroy(f); 127 aud_subsys.factories[i].f = NULL; 128 } 129 130 return PJ_SUCCESS; 203 aud_subsys.drv[i].f = NULL; 204 } 205 206 return PJ_SUCCESS; 207 } 208 209 /* API: get capability name/info */ 210 PJ_DEF(const char*) pjmedia_aud_dev_cap_name(pjmedia_aud_dev_cap cap, 211 const char **p_desc) 212 { 213 char *desc; 214 unsigned i; 215 216 if (p_desc==NULL) p_desc = &desc; 217 218 for (i=0; i<PJ_ARRAY_SIZE(cap_infos); ++i) { 219 if ((1 << i)==cap) 220 break; 221 } 222 223 if (i==32) { 224 *p_desc = "??"; 225 return "??"; 226 } 227 228 *p_desc = cap_infos[i].info; 229 return cap_infos[i].name; 131 230 } 132 231 … … 134 233 PJ_DEF(unsigned) pjmedia_aud_dev_count(void) 135 234 { 136 unsigned i, count = 0; 137 138 for (i=0; i<aud_subsys.factory_cnt; ++i) { 139 pjmedia_aud_dev_factory *f = aud_subsys.factories[i].f; 140 141 if (!f) 142 continue; 143 144 count += f->op->get_dev_count(f); 145 } 146 147 return count; 148 } 149 150 /* API: Enumerate device ID's. */ 151 PJ_DEF(unsigned) pjmedia_aud_dev_enum(unsigned max_count, 152 pjmedia_aud_dev_id ids[]) 153 { 154 unsigned i, count = 0; 155 156 for (i=0; i<aud_subsys.factory_cnt && count < max_count; ++i) { 157 pjmedia_aud_dev_factory *f = aud_subsys.factories[i].f; 158 unsigned j, fcount; 159 160 if (!f) 161 continue; 162 163 fcount = f->op->get_dev_count(f); 164 for (j=0; j<fcount && count<max_count; ++j) { 165 ids[count++] = MAKE_DEV_ID(i, j); 166 } 167 } 168 169 return count; 170 } 171 235 return aud_subsys.dev_cnt; 236 } 237 238 /* Internal: lookup device id */ 239 static pj_status_t lookup_dev(pjmedia_aud_dev_index id, 240 pjmedia_aud_dev_factory **p_f, 241 unsigned *p_local_index) 242 { 243 int f_id, index; 244 245 if (id == PJMEDIA_AUD_DEV_DEFAULT) 246 id = DEFAULT_DEV_ID; 247 248 PJ_ASSERT_RETURN(id>=0 && id<(int)aud_subsys.dev_cnt, 249 PJMEDIA_EAUD_INVDEV); 250 251 f_id = GET_FID(aud_subsys.dev_list[id]); 252 index = GET_INDEX(aud_subsys.dev_list[id]); 253 254 if (f_id < 0 || f_id >= (int)aud_subsys.drv_cnt) 255 return PJMEDIA_EAUD_INVDEV; 256 257 if (index < 0 || index >= (int)aud_subsys.drv[f_id].dev_cnt) 258 return PJMEDIA_EAUD_INVDEV; 259 260 *p_f = aud_subsys.drv[f_id].f; 261 *p_local_index = (unsigned)index; 262 263 return PJ_SUCCESS; 264 265 } 266 267 /* Internal: convert local index to global device index */ 268 static pj_status_t make_global_index(pjmedia_aud_dev_factory *f, 269 pjmedia_aud_dev_index *id) 270 { 271 unsigned f_id = f->internal.id; 272 273 if (*id == PJMEDIA_AUD_DEV_DEFAULT) 274 return PJ_SUCCESS; 275 276 /* Check that factory still exists */ 277 PJ_ASSERT_RETURN(f, PJ_EBUG); 278 279 /* Check that device index is valid */ 280 PJ_ASSERT_RETURN(*id>=0 && *id<(int)aud_subsys.drv[f_id].dev_cnt, PJ_EBUG); 281 282 *id += aud_subsys.drv[f_id].start_idx; 283 return PJ_SUCCESS; 284 } 172 285 173 286 /* API: Get device information. */ 174 PJ_DEF(pj_status_t) pjmedia_aud_dev_get_info(pjmedia_aud_dev_i did,287 PJ_DEF(pj_status_t) pjmedia_aud_dev_get_info(pjmedia_aud_dev_index id, 175 288 pjmedia_aud_dev_info *info) 176 289 { 177 290 pjmedia_aud_dev_factory *f; 178 int f_id, index; 179 180 if (id == PJMEDIA_AUD_DEV_DEFAULT_ID) 181 id = DEFAULT_DEV_ID; 182 183 f_id = GET_FID(id); 184 index = GET_INDEX(id); 185 186 if (f_id < 0 || f_id >= (int)aud_subsys.factory_cnt) 187 return PJMEDIA_EAUD_INVDEV; 188 189 f = aud_subsys.factories[f_id].f; 190 if (f == NULL) 191 return PJMEDIA_EAUD_INVDEV; 291 unsigned index; 292 pj_status_t status; 293 294 PJ_ASSERT_RETURN(info, PJ_EINVAL); 295 296 status = lookup_dev(id, &f, &index); 297 if (status != PJ_SUCCESS) 298 return status; 192 299 193 300 return f->op->get_dev_info(f, index, info); 301 } 302 303 /* API: find device */ 304 PJ_DEF(pj_status_t) pjmedia_aud_dev_lookup( const char *drv_name, 305 const char *dev_name, 306 pjmedia_aud_dev_index *id) 307 { 308 pjmedia_aud_dev_factory *f = NULL; 309 unsigned i, j; 310 311 PJ_ASSERT_RETURN(drv_name && dev_name && id, PJ_EINVAL); 312 313 for (i=0; i<aud_subsys.drv_cnt; ++i) { 314 if (!pj_ansi_stricmp(drv_name, aud_subsys.drv[i].name)) { 315 f = aud_subsys.drv[i].f; 316 break; 317 } 318 } 319 320 if (!f) 321 return PJ_ENOTFOUND; 322 323 for (j=0; j<aud_subsys.drv[i].dev_cnt; ++j) { 324 pjmedia_aud_dev_info info; 325 pj_status_t status; 326 327 status = f->op->get_dev_info(f, j, &info); 328 if (status != PJ_SUCCESS) 329 return status; 330 331 if (!pj_ansi_stricmp(dev_name, info.name)) 332 break; 333 } 334 335 if (j==aud_subsys.drv[i].dev_cnt) 336 return PJ_ENOTFOUND; 337 338 *id = j; 339 make_global_index(f, id); 340 341 return PJ_SUCCESS; 194 342 } 195 343 … … 197 345 * specified device. 198 346 */ 199 PJ_DEF(pj_status_t) pjmedia_aud_dev_default_param(pjmedia_aud_dev_i did,200 pjmedia_aud_ dev_param *param)347 PJ_DEF(pj_status_t) pjmedia_aud_dev_default_param(pjmedia_aud_dev_index id, 348 pjmedia_aud_param *param) 201 349 { 202 350 pjmedia_aud_dev_factory *f; 203 int f_id,index;351 unsigned index; 204 352 pj_status_t status; 205 353 206 if (id == PJMEDIA_AUD_DEV_DEFAULT_ID) 207 id = DEFAULT_DEV_ID; 208 209 f_id = GET_FID(id); 210 index = GET_INDEX(id); 211 212 if (f_id < 0 || f_id >= (int)aud_subsys.factory_cnt) 213 return PJMEDIA_EAUD_INVDEV; 214 215 f = aud_subsys.factories[f_id].f; 216 if (f == NULL) 217 return PJMEDIA_EAUD_INVDEV; 354 PJ_ASSERT_RETURN(param, PJ_EINVAL); 355 356 status = lookup_dev(id, &f, &index); 357 if (status != PJ_SUCCESS) 358 return status; 218 359 219 360 status = f->op->default_param(f, index, param); … … 222 363 223 364 /* Normalize device IDs */ 224 if (param->rec_id != PJMEDIA_AUD_DEV_DEFAULT_ID) 225 param->rec_id = MAKE_DEV_ID(f_id, param->rec_id); 226 if (param->play_id != PJMEDIA_AUD_DEV_DEFAULT_ID) 227 param->play_id = MAKE_DEV_ID(f_id, param->play_id); 365 make_global_index(f, ¶m->rec_id); 366 make_global_index(f, ¶m->play_id); 228 367 229 368 return PJ_SUCCESS; … … 231 370 232 371 /* API: Open audio stream object using the specified parameters. */ 233 PJ_DEF(pj_status_t) pjmedia_aud_stream_create(const pjmedia_aud_ dev_param *p,372 PJ_DEF(pj_status_t) pjmedia_aud_stream_create(const pjmedia_aud_param *prm, 234 373 pjmedia_aud_rec_cb rec_cb, 235 374 pjmedia_aud_play_cb play_cb, … … 237 376 pjmedia_aud_stream **p_aud_strm) 238 377 { 239 pjmedia_aud_dev_factory *f; 240 pjmedia_aud_dev_param param; 241 int f_id; 378 pjmedia_aud_dev_factory *rec_f=NULL, *play_f=NULL, *f=NULL; 379 pjmedia_aud_param param; 242 380 pj_status_t status; 243 381 382 PJ_ASSERT_RETURN(prm && prm->dir && p_aud_strm, PJ_EINVAL); 383 244 384 /* Must make copy of param because we're changing device ID */ 245 pj_memcpy(¶m, p, sizeof(param)); 246 247 /* Set default device */ 248 if (param.rec_id == PJMEDIA_AUD_DEV_DEFAULT_ID) 249 param.rec_id = DEFAULT_DEV_ID; 250 if (param.play_id == PJMEDIA_AUD_DEV_DEFAULT_ID) 251 param.play_id = DEFAULT_DEV_ID; 385 pj_memcpy(¶m, prm, sizeof(param)); 386 387 /* Normalize rec_id */ 388 if (param.dir & PJMEDIA_DIR_CAPTURE) { 389 unsigned index; 390 391 status = lookup_dev(param.rec_id, &rec_f, &index); 392 if (status != PJ_SUCCESS) 393 return status; 394 395 param.rec_id = index; 396 f = rec_f; 397 } 398 399 /* Normalize play_id */ 400 if (param.dir & PJMEDIA_DIR_PLAYBACK) { 401 unsigned index; 402 403 status = lookup_dev(param.play_id, &play_f, &index); 404 if (status != PJ_SUCCESS) 405 return status; 406 407 param.play_id = index; 408 f = play_f; 409 410 /* For now, rec_id and play_id must belong to the same factory */ 411 PJ_ASSERT_RETURN(rec_f == play_f, PJ_EINVAL); 412 } 413 252 414 253 if (param.dir & PJMEDIA_DIR_CAPTURE) 254 f_id = GET_FID(param.rec_id); 255 else 256 f_id = GET_FID(param.play_id); 257 258 if (f_id < 0 || f_id >= (int)aud_subsys.factory_cnt) 259 return PJMEDIA_EAUD_INVDEV; 260 261 /* Normalize device id's */ 262 param.rec_id = GET_INDEX(param.rec_id); 263 param.play_id = GET_INDEX(param.play_id); 264 265 f = aud_subsys.factories[f_id].f; 266 if (f == NULL) 267 return PJMEDIA_EAUD_INVDEV; 268 415 /* Create the stream */ 269 416 status = f->op->create_stream(f, ¶m, rec_cb, play_cb, 270 417 user_data, p_aud_strm); … … 272 419 return status; 273 420 274 (*p_aud_strm)->factory = f; 421 /* Assign factory id to the stream */ 422 (*p_aud_strm)->factory_id = f->internal.id; 275 423 return PJ_SUCCESS; 276 424 } … … 278 426 /* API: Get the running parameters for the specified audio stream. */ 279 427 PJ_DEF(pj_status_t) pjmedia_aud_stream_get_param(pjmedia_aud_stream *strm, 280 pjmedia_aud_ dev_param *param)428 pjmedia_aud_param *param) 281 429 { 282 430 pj_status_t status; … … 287 435 288 436 /* Normalize device id's */ 289 if (param->rec_id != PJMEDIA_AUD_DEV_DEFAULT_ID) 290 param->rec_id = MAKE_DEV_ID(strm->factory->internal.id, param->rec_id); 291 if (param->play_id != PJMEDIA_AUD_DEV_DEFAULT_ID) 292 param->play_id = MAKE_DEV_ID(strm->factory->internal.id, param->play_id); 437 make_global_index(aud_subsys.drv[strm->factory_id].f, ¶m->rec_id); 438 make_global_index(aud_subsys.drv[strm->factory_id].f, ¶m->play_id); 293 439 294 440 return PJ_SUCCESS;
Note: See TracChangeset
for help on using the changeset viewer.