- Timestamp:
- Dec 28, 2016 3:40:07 AM (8 years ago)
- Location:
- pjproject/branches/projects/uwp
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/branches/projects/uwp
- Property svn:mergeinfo changed
/pjproject/trunk (added) merged: 5209,5212-5234,5237-5253,5255,5257-5292,5294-5297,5299-5332,5334-5394,5396-5438,5440-5469,5471-5496,5498-5510
- Property svn:mergeinfo changed
-
pjproject/branches/projects/uwp/pjmedia/src/pjmedia-audiodev/audiodev.c
r5210 r5513 20 20 #include <pjmedia-audiodev/audiodev_imp.h> 21 21 #include <pj/assert.h> 22 #include <pj/errno.h>23 #include <pj/log.h>24 #include <pj/pool.h>25 #include <pj/string.h>26 22 27 23 #define THIS_FILE "audiodev.c" 28 29 #define DEFINE_CAP(name, info) {name, info}30 31 /* Capability names */32 static struct cap_info33 {34 const char *name;35 const char *info;36 } cap_infos[] =37 {38 DEFINE_CAP("ext-fmt", "Extended/non-PCM format"),39 DEFINE_CAP("latency-in", "Input latency/buffer size setting"),40 DEFINE_CAP("latency-out", "Output latency/buffer size setting"),41 DEFINE_CAP("vol-in", "Input volume setting"),42 DEFINE_CAP("vol-out", "Output volume setting"),43 DEFINE_CAP("meter-in", "Input meter"),44 DEFINE_CAP("meter-out", "Output meter"),45 DEFINE_CAP("route-in", "Input routing"),46 DEFINE_CAP("route-out", "Output routing"),47 DEFINE_CAP("aec", "Accoustic echo cancellation"),48 DEFINE_CAP("aec-tail", "Tail length setting for AEC"),49 DEFINE_CAP("vad", "Voice activity detection"),50 DEFINE_CAP("cng", "Comfort noise generation"),51 DEFINE_CAP("plg", "Packet loss concealment")52 };53 54 55 /*56 * The device index seen by application and driver is different.57 *58 * At application level, device index is index to global list of device.59 * At driver level, device index is index to device list on that particular60 * factory only.61 */62 #define MAKE_DEV_ID(f_id, index) (((f_id & 0xFFFF) << 16) | (index & 0xFFFF))63 #define GET_INDEX(dev_id) ((dev_id) & 0xFFFF)64 #define GET_FID(dev_id) ((dev_id) >> 16)65 #define DEFAULT_DEV_ID 066 24 67 25 … … 119 77 #endif 120 78 121 #define MAX_DRIVERS 16122 #define MAX_DEVS 64123 124 125 /* driver structure */126 struct driver127 {128 /* Creation function */129 pjmedia_aud_dev_factory_create_func_ptr create;130 /* Factory instance */131 pjmedia_aud_dev_factory *f;132 char name[32]; /* Driver name */133 unsigned dev_cnt; /* Number of devices */134 unsigned start_idx; /* Start index in global list */135 int rec_dev_idx;/* Default capture device. */136 int play_dev_idx;/* Default playback device */137 int dev_idx; /* Default device. */138 };139 140 /* The audio subsystem */141 static struct aud_subsys142 {143 unsigned init_count; /* How many times init() is called */144 pj_pool_factory *pf; /* The pool factory. */145 146 unsigned drv_cnt; /* Number of drivers. */147 struct driver drv[MAX_DRIVERS]; /* Array of drivers. */148 149 unsigned dev_cnt; /* Total number of devices. */150 pj_uint32_t dev_list[MAX_DEVS];/* Array of device IDs. */151 152 } aud_subsys;153 154 /* API: get capability name/info */155 PJ_DEF(const char*) pjmedia_aud_dev_cap_name(pjmedia_aud_dev_cap cap,156 const char **p_desc)157 {158 const char *desc;159 unsigned i;160 161 if (p_desc==NULL) p_desc = &desc;162 163 for (i=0; i<PJ_ARRAY_SIZE(cap_infos); ++i) {164 if ((1 << i)==cap)165 break;166 }167 168 if (i==PJ_ARRAY_SIZE(cap_infos)) {169 *p_desc = "??";170 return "??";171 }172 173 *p_desc = cap_infos[i].info;174 return cap_infos[i].name;175 }176 177 static pj_status_t get_cap_pointer(const pjmedia_aud_param *param,178 pjmedia_aud_dev_cap cap,179 void **ptr,180 unsigned *size)181 {182 #define FIELD_INFO(name) *ptr = (void*)¶m->name; \183 *size = sizeof(param->name)184 185 switch (cap) {186 case PJMEDIA_AUD_DEV_CAP_EXT_FORMAT:187 FIELD_INFO(ext_fmt);188 break;189 case PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY:190 FIELD_INFO(input_latency_ms);191 break;192 case PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY:193 FIELD_INFO(output_latency_ms);194 break;195 case PJMEDIA_AUD_DEV_CAP_INPUT_VOLUME_SETTING:196 FIELD_INFO(input_vol);197 break;198 case PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING:199 FIELD_INFO(output_vol);200 break;201 case PJMEDIA_AUD_DEV_CAP_INPUT_ROUTE:202 FIELD_INFO(input_route);203 break;204 case PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE:205 FIELD_INFO(output_route);206 break;207 case PJMEDIA_AUD_DEV_CAP_EC:208 FIELD_INFO(ec_enabled);209 break;210 case PJMEDIA_AUD_DEV_CAP_EC_TAIL:211 FIELD_INFO(ec_tail_ms);212 break;213 /* vad is no longer in "fmt" in 2.0.214 case PJMEDIA_AUD_DEV_CAP_VAD:215 FIELD_INFO(ext_fmt.vad);216 break;217 */218 case PJMEDIA_AUD_DEV_CAP_CNG:219 FIELD_INFO(cng_enabled);220 break;221 case PJMEDIA_AUD_DEV_CAP_PLC:222 FIELD_INFO(plc_enabled);223 break;224 default:225 return PJMEDIA_EAUD_INVCAP;226 }227 228 #undef FIELD_INFO229 230 return PJ_SUCCESS;231 }232 233 /* API: set cap value to param */234 PJ_DEF(pj_status_t) pjmedia_aud_param_set_cap( pjmedia_aud_param *param,235 pjmedia_aud_dev_cap cap,236 const void *pval)237 {238 void *cap_ptr;239 unsigned cap_size;240 pj_status_t status;241 242 status = get_cap_pointer(param, cap, &cap_ptr, &cap_size);243 if (status != PJ_SUCCESS)244 return status;245 246 pj_memcpy(cap_ptr, pval, cap_size);247 param->flags |= cap;248 249 return PJ_SUCCESS;250 }251 252 /* API: get cap value from param */253 PJ_DEF(pj_status_t) pjmedia_aud_param_get_cap( const pjmedia_aud_param *param,254 pjmedia_aud_dev_cap cap,255 void *pval)256 {257 void *cap_ptr;258 unsigned cap_size;259 pj_status_t status;260 261 status = get_cap_pointer(param, cap, &cap_ptr, &cap_size);262 if (status != PJ_SUCCESS)263 return status;264 265 if ((param->flags & cap) == 0) {266 pj_bzero(cap_ptr, cap_size);267 return PJMEDIA_EAUD_INVCAP;268 }269 270 pj_memcpy(pval, cap_ptr, cap_size);271 return PJ_SUCCESS;272 }273 274 /* Internal: init driver */275 static pj_status_t init_driver(unsigned drv_idx, pj_bool_t refresh)276 {277 struct driver *drv = &aud_subsys.drv[drv_idx];278 pjmedia_aud_dev_factory *f;279 unsigned i, dev_cnt;280 pj_status_t status;281 282 if (!refresh && drv->create) {283 /* Create the factory */284 f = (*drv->create)(aud_subsys.pf);285 if (!f)286 return PJ_EUNKNOWN;287 288 /* Call factory->init() */289 status = f->op->init(f);290 if (status != PJ_SUCCESS) {291 f->op->destroy(f);292 return status;293 }294 } else {295 f = drv->f;296 }297 298 if (!f)299 return PJ_EUNKNOWN;300 301 /* Get number of devices */302 dev_cnt = f->op->get_dev_count(f);303 if (dev_cnt + aud_subsys.dev_cnt > MAX_DEVS) {304 PJ_LOG(4,(THIS_FILE, "%d device(s) cannot be registered because"305 " there are too many devices",306 aud_subsys.dev_cnt + dev_cnt - MAX_DEVS));307 dev_cnt = MAX_DEVS - aud_subsys.dev_cnt;308 }309 310 /* enabling this will cause pjsua-lib initialization to fail when there311 * is no sound device installed in the system, even when pjsua has been312 * run with --null-audio313 *314 if (dev_cnt == 0) {315 f->op->destroy(f);316 return PJMEDIA_EAUD_NODEV;317 }318 */319 320 /* Fill in default devices */321 drv->play_dev_idx = drv->rec_dev_idx =322 drv->dev_idx = PJMEDIA_AUD_INVALID_DEV;323 for (i=0; i<dev_cnt; ++i) {324 pjmedia_aud_dev_info info;325 326 status = f->op->get_dev_info(f, i, &info);327 if (status != PJ_SUCCESS) {328 f->op->destroy(f);329 return status;330 }331 332 if (drv->name[0]=='\0') {333 /* Set driver name */334 pj_ansi_strncpy(drv->name, info.driver, sizeof(drv->name));335 drv->name[sizeof(drv->name)-1] = '\0';336 }337 338 if (drv->play_dev_idx < 0 && info.output_count) {339 /* Set default playback device */340 drv->play_dev_idx = i;341 }342 if (drv->rec_dev_idx < 0 && info.input_count) {343 /* Set default capture device */344 drv->rec_dev_idx = i;345 }346 if (drv->dev_idx < 0 && info.input_count &&347 info.output_count)348 {349 /* Set default capture and playback device */350 drv->dev_idx = i;351 }352 353 if (drv->play_dev_idx >= 0 && drv->rec_dev_idx >= 0 &&354 drv->dev_idx >= 0)355 {356 /* Done. */357 break;358 }359 }360 361 /* Register the factory */362 drv->f = f;363 drv->f->sys.drv_idx = drv_idx;364 drv->start_idx = aud_subsys.dev_cnt;365 drv->dev_cnt = dev_cnt;366 367 /* Register devices to global list */368 for (i=0; i<dev_cnt; ++i) {369 aud_subsys.dev_list[aud_subsys.dev_cnt++] = MAKE_DEV_ID(drv_idx, i);370 }371 372 return PJ_SUCCESS;373 }374 375 /* Internal: deinit driver */376 static void deinit_driver(unsigned drv_idx)377 {378 struct driver *drv = &aud_subsys.drv[drv_idx];379 380 if (drv->f) {381 drv->f->op->destroy(drv->f);382 drv->f = NULL;383 }384 385 pj_bzero(drv, sizeof(*drv));386 drv->play_dev_idx = drv->rec_dev_idx =387 drv->dev_idx = PJMEDIA_AUD_INVALID_DEV;388 }389 79 390 80 /* API: Initialize the audio subsystem. */ … … 393 83 unsigned i; 394 84 pj_status_t status; 85 pjmedia_aud_subsys *aud_subsys = pjmedia_get_aud_subsys(); 395 86 396 87 /* Allow init() to be called multiple times as long as there is matching 397 88 * number of shutdown(). 398 89 */ 399 if (aud_subsys .init_count++ != 0) {90 if (aud_subsys->init_count++ != 0) { 400 91 return PJ_SUCCESS; 401 92 } … … 408 99 409 100 /* Init */ 410 aud_subsys .pf = pf;411 aud_subsys .drv_cnt = 0;412 aud_subsys .dev_cnt = 0;101 aud_subsys->pf = pf; 102 aud_subsys->drv_cnt = 0; 103 aud_subsys->dev_cnt = 0; 413 104 414 105 /* Register creation functions */ 415 106 #if PJMEDIA_AUDIO_DEV_HAS_OPENSL 416 aud_subsys .drv[aud_subsys.drv_cnt++].create = &pjmedia_opensl_factory;107 aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_opensl_factory; 417 108 #endif 418 109 #if PJMEDIA_AUDIO_DEV_HAS_ANDROID_JNI 419 aud_subsys .drv[aud_subsys.drv_cnt++].create = &pjmedia_android_factory;110 aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_android_factory; 420 111 #endif 421 112 #if PJMEDIA_AUDIO_DEV_HAS_BB10 422 aud_subsys .drv[aud_subsys.drv_cnt++].create = &pjmedia_bb10_factory;113 aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_bb10_factory; 423 114 #endif 424 115 #if PJMEDIA_AUDIO_DEV_HAS_ALSA 425 aud_subsys .drv[aud_subsys.drv_cnt++].create = &pjmedia_alsa_factory;116 aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_alsa_factory; 426 117 #endif 427 118 #if PJMEDIA_AUDIO_DEV_HAS_COREAUDIO 428 aud_subsys .drv[aud_subsys.drv_cnt++].create = &pjmedia_coreaudio_factory;119 aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_coreaudio_factory; 429 120 #endif 430 121 #if PJMEDIA_AUDIO_DEV_HAS_PORTAUDIO 431 aud_subsys .drv[aud_subsys.drv_cnt++].create = &pjmedia_pa_factory;122 aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_pa_factory; 432 123 #endif 433 124 #if PJMEDIA_AUDIO_DEV_HAS_WMME 434 aud_subsys .drv[aud_subsys.drv_cnt++].create = &pjmedia_wmme_factory;125 aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_wmme_factory; 435 126 #endif 436 127 #if PJMEDIA_AUDIO_DEV_HAS_BDIMAD 437 aud_subsys .drv[aud_subsys.drv_cnt++].create = &pjmedia_bdimad_factory;128 aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_bdimad_factory; 438 129 #endif 439 130 #if PJMEDIA_AUDIO_DEV_HAS_SYMB_VAS 440 aud_subsys .drv[aud_subsys.drv_cnt++].create = &pjmedia_symb_vas_factory;131 aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_symb_vas_factory; 441 132 #endif 442 133 #if PJMEDIA_AUDIO_DEV_HAS_SYMB_APS 443 aud_subsys .drv[aud_subsys.drv_cnt++].create = &pjmedia_aps_factory;134 aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_aps_factory; 444 135 #endif 445 136 #if PJMEDIA_AUDIO_DEV_HAS_SYMB_MDA 446 aud_subsys .drv[aud_subsys.drv_cnt++].create = &pjmedia_symb_mda_factory;137 aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_symb_mda_factory; 447 138 #endif 448 139 #if PJMEDIA_AUDIO_DEV_HAS_WASAPI … … 450 141 #endif 451 142 #if PJMEDIA_AUDIO_DEV_HAS_NULL_AUDIO 452 aud_subsys .drv[aud_subsys.drv_cnt++].create = &pjmedia_null_audio_factory;143 aud_subsys->drv[aud_subsys->drv_cnt++].create = &pjmedia_null_audio_factory; 453 144 #endif 454 145 455 146 /* Initialize each factory and build the device ID list */ 456 for (i=0; i<aud_subsys .drv_cnt; ++i) {457 status = init_driver(i, PJ_FALSE);147 for (i=0; i<aud_subsys->drv_cnt; ++i) { 148 status = pjmedia_aud_driver_init(i, PJ_FALSE); 458 149 if (status != PJ_SUCCESS) { 459 deinit_driver(i);150 pjmedia_aud_driver_deinit(i); 460 151 continue; 461 152 } 462 153 } 463 154 464 return aud_subsys .dev_cnt ? PJ_SUCCESS : status;155 return aud_subsys->dev_cnt ? PJ_SUCCESS : status; 465 156 } 466 157 … … 470 161 { 471 162 pj_status_t status; 472 473 if (aud_subsys.init_count == 0) 163 pjmedia_aud_subsys *aud_subsys = pjmedia_get_aud_subsys(); 164 165 if (aud_subsys->init_count == 0) 474 166 return PJMEDIA_EAUD_INIT; 475 167 476 aud_subsys .drv[aud_subsys.drv_cnt].create = adf;477 status = init_driver(aud_subsys.drv_cnt, PJ_FALSE);168 aud_subsys->drv[aud_subsys->drv_cnt].create = adf; 169 status = pjmedia_aud_driver_init(aud_subsys->drv_cnt, PJ_FALSE); 478 170 if (status == PJ_SUCCESS) { 479 aud_subsys .drv_cnt++;171 aud_subsys->drv_cnt++; 480 172 } else { 481 deinit_driver(aud_subsys.drv_cnt);173 pjmedia_aud_driver_deinit(aud_subsys->drv_cnt); 482 174 } 483 175 … … 490 182 { 491 183 unsigned i, j; 492 493 if (aud_subsys.init_count == 0) 184 pjmedia_aud_subsys *aud_subsys = pjmedia_get_aud_subsys(); 185 186 if (aud_subsys->init_count == 0) 494 187 return PJMEDIA_EAUD_INIT; 495 188 496 for (i=0; i<aud_subsys .drv_cnt; ++i) {497 struct driver *drv = &aud_subsys.drv[i];189 for (i=0; i<aud_subsys->drv_cnt; ++i) { 190 pjmedia_aud_driver *drv = &aud_subsys->drv[i]; 498 191 499 192 if (drv->create == adf) { 500 193 for (j = drv->start_idx; j < drv->start_idx + drv->dev_cnt; j++) 501 194 { 502 aud_subsys .dev_list[j] = (pj_uint32_t)PJMEDIA_AUD_INVALID_DEV;195 aud_subsys->dev_list[j] = (pj_uint32_t)PJMEDIA_AUD_INVALID_DEV; 503 196 } 504 197 505 deinit_driver(i);198 pjmedia_aud_driver_deinit(i); 506 199 return PJ_SUCCESS; 507 200 } … … 514 207 PJ_DEF(pj_pool_factory*) pjmedia_aud_subsys_get_pool_factory(void) 515 208 { 516 return aud_subsys.pf; 209 pjmedia_aud_subsys *aud_subsys = pjmedia_get_aud_subsys(); 210 return aud_subsys->pf; 517 211 } 518 212 … … 521 215 { 522 216 unsigned i; 217 pjmedia_aud_subsys *aud_subsys = pjmedia_get_aud_subsys(); 523 218 524 219 /* Allow shutdown() to be called multiple times as long as there is matching 525 220 * number of init(). 526 221 */ 527 if (aud_subsys .init_count == 0) {222 if (aud_subsys->init_count == 0) { 528 223 return PJ_SUCCESS; 529 224 } 530 --aud_subsys .init_count;531 532 if (aud_subsys .init_count == 0) {533 for (i=0; i<aud_subsys .drv_cnt; ++i) {534 deinit_driver(i);225 --aud_subsys->init_count; 226 227 if (aud_subsys->init_count == 0) { 228 for (i=0; i<aud_subsys->drv_cnt; ++i) { 229 pjmedia_aud_driver_deinit(i); 535 230 } 536 231 537 aud_subsys .pf = NULL;232 aud_subsys->pf = NULL; 538 233 } 539 234 return PJ_SUCCESS; 540 235 } 541 542 /* API: Refresh the list of sound devices installed in the system. */543 PJ_DEF(pj_status_t) pjmedia_aud_dev_refresh(void)544 {545 unsigned i;546 547 aud_subsys.dev_cnt = 0;548 for (i=0; i<aud_subsys.drv_cnt; ++i) {549 struct driver *drv = &aud_subsys.drv[i];550 551 if (drv->f && drv->f->op->refresh) {552 pj_status_t status = drv->f->op->refresh(drv->f);553 if (status != PJ_SUCCESS) {554 PJ_PERROR(4, (THIS_FILE, status, "Unable to refresh device "555 "list for %s", drv->name));556 }557 }558 init_driver(i, PJ_TRUE);559 }560 return PJ_SUCCESS;561 }562 563 /* API: Get the number of sound devices installed in the system. */564 PJ_DEF(unsigned) pjmedia_aud_dev_count(void)565 {566 return aud_subsys.dev_cnt;567 }568 569 /* Internal: convert local index to global device index */570 static pj_status_t make_global_index(unsigned drv_idx,571 pjmedia_aud_dev_index *id)572 {573 if (*id < 0) {574 return PJ_SUCCESS;575 }576 577 /* Check that factory still exists */578 PJ_ASSERT_RETURN(aud_subsys.drv[drv_idx].f, PJ_EBUG);579 580 /* Check that device index is valid */581 PJ_ASSERT_RETURN(*id>=0 && *id<(int)aud_subsys.drv[drv_idx].dev_cnt,582 PJ_EBUG);583 584 *id += aud_subsys.drv[drv_idx].start_idx;585 return PJ_SUCCESS;586 }587 588 /* Internal: lookup device id */589 static pj_status_t lookup_dev(pjmedia_aud_dev_index id,590 pjmedia_aud_dev_factory **p_f,591 unsigned *p_local_index)592 {593 int f_id, index;594 595 if (id < 0) {596 unsigned i;597 598 if (id == PJMEDIA_AUD_INVALID_DEV)599 return PJMEDIA_EAUD_INVDEV;600 601 for (i=0; i<aud_subsys.drv_cnt; ++i) {602 struct driver *drv = &aud_subsys.drv[i];603 if (drv->dev_idx >= 0) {604 id = drv->dev_idx;605 make_global_index(i, &id);606 break;607 } else if (id==PJMEDIA_AUD_DEFAULT_CAPTURE_DEV &&608 drv->rec_dev_idx >= 0)609 {610 id = drv->rec_dev_idx;611 make_global_index(i, &id);612 break;613 } else if (id==PJMEDIA_AUD_DEFAULT_PLAYBACK_DEV &&614 drv->play_dev_idx >= 0)615 {616 id = drv->play_dev_idx;617 make_global_index(i, &id);618 break;619 }620 }621 622 if (id < 0) {623 return PJMEDIA_EAUD_NODEFDEV;624 }625 }626 627 f_id = GET_FID(aud_subsys.dev_list[id]);628 index = GET_INDEX(aud_subsys.dev_list[id]);629 630 if (f_id < 0 || f_id >= (int)aud_subsys.drv_cnt)631 return PJMEDIA_EAUD_INVDEV;632 633 if (index < 0 || index >= (int)aud_subsys.drv[f_id].dev_cnt)634 return PJMEDIA_EAUD_INVDEV;635 636 *p_f = aud_subsys.drv[f_id].f;637 *p_local_index = (unsigned)index;638 639 return PJ_SUCCESS;640 641 }642 643 /* API: Get device information. */644 PJ_DEF(pj_status_t) pjmedia_aud_dev_get_info(pjmedia_aud_dev_index id,645 pjmedia_aud_dev_info *info)646 {647 pjmedia_aud_dev_factory *f;648 unsigned index;649 pj_status_t status;650 651 PJ_ASSERT_RETURN(info && id!=PJMEDIA_AUD_INVALID_DEV, PJ_EINVAL);652 PJ_ASSERT_RETURN(aud_subsys.pf, PJMEDIA_EAUD_INIT);653 654 status = lookup_dev(id, &f, &index);655 if (status != PJ_SUCCESS)656 return status;657 658 return f->op->get_dev_info(f, index, info);659 }660 661 /* API: find device */662 PJ_DEF(pj_status_t) pjmedia_aud_dev_lookup( const char *drv_name,663 const char *dev_name,664 pjmedia_aud_dev_index *id)665 {666 pjmedia_aud_dev_factory *f = NULL;667 unsigned drv_idx, dev_idx;668 669 PJ_ASSERT_RETURN(drv_name && dev_name && id, PJ_EINVAL);670 PJ_ASSERT_RETURN(aud_subsys.pf, PJMEDIA_EAUD_INIT);671 672 for (drv_idx=0; drv_idx<aud_subsys.drv_cnt; ++drv_idx) {673 if (!pj_ansi_stricmp(drv_name, aud_subsys.drv[drv_idx].name)) {674 f = aud_subsys.drv[drv_idx].f;675 break;676 }677 }678 679 if (!f)680 return PJ_ENOTFOUND;681 682 for (dev_idx=0; dev_idx<aud_subsys.drv[drv_idx].dev_cnt; ++dev_idx) {683 pjmedia_aud_dev_info info;684 pj_status_t status;685 686 status = f->op->get_dev_info(f, dev_idx, &info);687 if (status != PJ_SUCCESS)688 return status;689 690 if (!pj_ansi_stricmp(dev_name, info.name))691 break;692 }693 694 if (dev_idx==aud_subsys.drv[drv_idx].dev_cnt)695 return PJ_ENOTFOUND;696 697 *id = dev_idx;698 make_global_index(drv_idx, id);699 700 return PJ_SUCCESS;701 }702 703 /* API: Initialize the audio device parameters with default values for the704 * specified device.705 */706 PJ_DEF(pj_status_t) pjmedia_aud_dev_default_param(pjmedia_aud_dev_index id,707 pjmedia_aud_param *param)708 {709 pjmedia_aud_dev_factory *f;710 unsigned index;711 pj_status_t status;712 713 PJ_ASSERT_RETURN(param && id!=PJMEDIA_AUD_INVALID_DEV, PJ_EINVAL);714 PJ_ASSERT_RETURN(aud_subsys.pf, PJMEDIA_EAUD_INIT);715 716 status = lookup_dev(id, &f, &index);717 if (status != PJ_SUCCESS)718 return status;719 720 status = f->op->default_param(f, index, param);721 if (status != PJ_SUCCESS)722 return status;723 724 /* Normalize device IDs */725 make_global_index(f->sys.drv_idx, ¶m->rec_id);726 make_global_index(f->sys.drv_idx, ¶m->play_id);727 728 return PJ_SUCCESS;729 }730 731 /* API: Open audio stream object using the specified parameters. */732 PJ_DEF(pj_status_t) pjmedia_aud_stream_create(const pjmedia_aud_param *prm,733 pjmedia_aud_rec_cb rec_cb,734 pjmedia_aud_play_cb play_cb,735 void *user_data,736 pjmedia_aud_stream **p_aud_strm)737 {738 pjmedia_aud_dev_factory *rec_f=NULL, *play_f=NULL, *f=NULL;739 pjmedia_aud_param param;740 pj_status_t status;741 742 PJ_ASSERT_RETURN(prm && prm->dir && p_aud_strm, PJ_EINVAL);743 PJ_ASSERT_RETURN(aud_subsys.pf, PJMEDIA_EAUD_INIT);744 PJ_ASSERT_RETURN(prm->dir==PJMEDIA_DIR_CAPTURE ||745 prm->dir==PJMEDIA_DIR_PLAYBACK ||746 prm->dir==PJMEDIA_DIR_CAPTURE_PLAYBACK,747 PJ_EINVAL);748 749 /* Must make copy of param because we're changing device ID */750 pj_memcpy(¶m, prm, sizeof(param));751 752 /* Normalize rec_id */753 if (param.dir & PJMEDIA_DIR_CAPTURE) {754 unsigned index;755 756 if (param.rec_id < 0)757 param.rec_id = PJMEDIA_AUD_DEFAULT_CAPTURE_DEV;758 759 status = lookup_dev(param.rec_id, &rec_f, &index);760 if (status != PJ_SUCCESS)761 return status;762 763 param.rec_id = index;764 f = rec_f;765 }766 767 /* Normalize play_id */768 if (param.dir & PJMEDIA_DIR_PLAYBACK) {769 unsigned index;770 771 if (param.play_id < 0)772 param.play_id = PJMEDIA_AUD_DEFAULT_PLAYBACK_DEV;773 774 status = lookup_dev(param.play_id, &play_f, &index);775 if (status != PJ_SUCCESS)776 return status;777 778 param.play_id = index;779 f = play_f;780 }781 782 PJ_ASSERT_RETURN(f != NULL, PJ_EBUG);783 784 /* For now, rec_id and play_id must belong to the same factory */785 PJ_ASSERT_RETURN((param.dir != PJMEDIA_DIR_CAPTURE_PLAYBACK) ||786 (rec_f == play_f),787 PJMEDIA_EAUD_INVDEV);788 789 /* Create the stream */790 status = f->op->create_stream(f, ¶m, rec_cb, play_cb,791 user_data, p_aud_strm);792 if (status != PJ_SUCCESS)793 return status;794 795 /* Assign factory id to the stream */796 (*p_aud_strm)->sys.drv_idx = f->sys.drv_idx;797 return PJ_SUCCESS;798 }799 800 /* API: Get the running parameters for the specified audio stream. */801 PJ_DEF(pj_status_t) pjmedia_aud_stream_get_param(pjmedia_aud_stream *strm,802 pjmedia_aud_param *param)803 {804 pj_status_t status;805 806 PJ_ASSERT_RETURN(strm && param, PJ_EINVAL);807 PJ_ASSERT_RETURN(aud_subsys.pf, PJMEDIA_EAUD_INIT);808 809 status = strm->op->get_param(strm, param);810 if (status != PJ_SUCCESS)811 return status;812 813 /* Normalize device id's */814 make_global_index(strm->sys.drv_idx, ¶m->rec_id);815 make_global_index(strm->sys.drv_idx, ¶m->play_id);816 817 return PJ_SUCCESS;818 }819 820 /* API: Get the value of a specific capability of the audio stream. */821 PJ_DEF(pj_status_t) pjmedia_aud_stream_get_cap(pjmedia_aud_stream *strm,822 pjmedia_aud_dev_cap cap,823 void *value)824 {825 return strm->op->get_cap(strm, cap, value);826 }827 828 /* API: Set the value of a specific capability of the audio stream. */829 PJ_DEF(pj_status_t) pjmedia_aud_stream_set_cap(pjmedia_aud_stream *strm,830 pjmedia_aud_dev_cap cap,831 const void *value)832 {833 return strm->op->set_cap(strm, cap, value);834 }835 836 /* API: Start the stream. */837 PJ_DEF(pj_status_t) pjmedia_aud_stream_start(pjmedia_aud_stream *strm)838 {839 return strm->op->start(strm);840 }841 842 /* API: Stop the stream. */843 PJ_DEF(pj_status_t) pjmedia_aud_stream_stop(pjmedia_aud_stream *strm)844 {845 return strm->op->stop(strm);846 }847 848 /* API: Destroy the stream. */849 PJ_DEF(pj_status_t) pjmedia_aud_stream_destroy(pjmedia_aud_stream *strm)850 {851 return strm->op->destroy(strm);852 }853 854
Note: See TracChangeset
for help on using the changeset viewer.