Changeset 876f5561 in mainline for uspace/lib/hound/src/protocol.c
- Timestamp:
- 2013-04-10T23:06:52Z (11 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- f0a647c
- Parents:
- eb0ef51
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/hound/src/protocol.c
reb0ef51 r876f5561 48 48 49 49 enum ipc_methods { 50 /** Create new context representation on the server side */ 50 51 IPC_M_HOUND_CONTEXT_REGISTER = IPC_FIRST_USER_METHOD, 52 /** Release existing context representation on the server side */ 51 53 IPC_M_HOUND_CONTEXT_UNREGISTER, 54 /** Request list of objects */ 52 55 IPC_M_HOUND_GET_LIST, 56 /** Create new connection */ 53 57 IPC_M_HOUND_CONNECT, 58 /** Destroy connection */ 54 59 IPC_M_HOUND_DISCONNECT, 60 /** Switch IPC pipe to stream mode */ 55 61 IPC_M_HOUND_STREAM_ENTER, 62 /** Switch IPC pipe back to general mode */ 56 63 IPC_M_HOUND_STREAM_EXIT, 64 /** Wait until there is no data in the stream */ 57 65 IPC_M_HOUND_STREAM_DRAIN, 58 66 }; 59 67 68 69 /** PCM format conversion helper structure */ 60 70 typedef union { 61 71 struct { … … 72 82 ****/ 73 83 84 /** Well defined service name */ 74 85 const char *HOUND_SERVICE = "audio/hound"; 75 86 87 /** 88 * Start a new audio session. 89 * @param service Named service typically 'HOUND_SERVICE' constant. 90 * @return Valid session on success, NULL on failure. 91 */ 76 92 hound_sess_t *hound_service_connect(const char *service) 77 93 { … … 84 100 } 85 101 102 /** 103 * End an existing audio session. 104 * @param sess The session. 105 */ 86 106 void hound_service_disconnect(hound_sess_t *sess) 87 107 { … … 90 110 } 91 111 112 /** 113 * Register a named application context to the audio server. 114 * @param sess Valid audio session. 115 * @param name Valid string identifier 116 * @param record True if the application context wishes to receive data. 117 * @return Valid ID on success, Error code on failure. 118 */ 92 119 hound_context_id_t hound_service_register_context(hound_sess_t *sess, 93 120 const char *name, bool record) … … 113 140 } 114 141 142 /** 143 * Remove application context from the server's list. 144 * @param sess Valid audio session. 145 * @param id Valid context id. 146 * @return Error code. 147 */ 115 148 int hound_service_unregister_context(hound_sess_t *sess, hound_context_id_t id) 116 149 { … … 123 156 } 124 157 158 /** 159 * Retrieve a list of server side actors. 160 * @param[in] sess Valid audio session. 161 * @param[out] ids list of string identifiers. 162 * @param[out] count Number of elements int the @p ids list. 163 * @param[in] flags list requirements. 164 * @param[in] connection name of target actor. Used only if the list should 165 * contain connected actors. 166 * @retval Error code. 167 */ 125 168 int hound_service_get_list(hound_sess_t *sess, const char ***ids, size_t *count, 126 169 int flags, const char *connection) … … 190 233 } 191 234 235 /** 236 * Create a new connection between a source and a sink. 237 * @param sess Valid audio session. 238 * @param source Source name, valid string. 239 * @param sink Sink name, valid string. 240 * @return Error code. 241 */ 192 242 int hound_service_connect_source_sink(hound_sess_t *sess, const char *source, 193 243 const char *sink) … … 212 262 } 213 263 264 /** 265 * Destroy an existing connection between a source and a sink. 266 * @param sess Valid audio session. 267 * @param source Source name, valid string. 268 * @param sink Sink name, valid string. 269 * @return Error code. 270 */ 214 271 int hound_service_disconnect_source_sink(hound_sess_t *sess, const char *source, 215 272 const char *sink) … … 231 288 } 232 289 290 /** 291 * Switch IPC exchange to a STREAM mode. 292 * @param exch IPC exchange. 293 * @param id context id this stream should be associated with 294 * @param flags set stream properties 295 * @param format format of the new stream. 296 * @param bsize size of the server side buffer. 297 * @return Error code. 298 */ 233 299 int hound_service_stream_enter(async_exch_t *exch, hound_context_id_t id, 234 300 int flags, pcm_format_t format, size_t bsize) … … 243 309 } 244 310 311 /** 312 * Destroy existing stream and return IPC exchange to general mode. 313 * @param exch IPC exchange. 314 * @return Error code. 315 */ 245 316 int hound_service_stream_exit(async_exch_t *exch) 246 317 { … … 248 319 } 249 320 321 /** 322 * Wait until the server side buffer is empty. 323 * @param exch IPC exchange. 324 * @return Error code. 325 */ 250 326 int hound_service_stream_drain(async_exch_t *exch) 251 327 { … … 253 329 } 254 330 331 /** 332 * Write audio data to a stream. 333 * @param exch IPC exchange in STREAM MODE. 334 * @param data Audio data buffer. 335 * @size size of the buffer 336 * @return Error code. 337 */ 255 338 int hound_service_stream_write(async_exch_t *exch, const void *data, size_t size) 256 339 { … … 258 341 } 259 342 343 /** 344 * Read data from a stream. 345 * @param exch IPC exchange in STREAM MODE. 346 * @param data Audio data buffer. 347 * @size size of the buffer 348 * @return Error code. 349 */ 260 350 int hound_service_stream_read(async_exch_t *exch, void *data, size_t size) 261 351 { … … 271 361 static const hound_server_iface_t *server_iface; 272 362 363 /** 364 * Set hound server interface implementation. 365 * @param iface Initialized Hound server interface. 366 */ 273 367 void hound_service_set_server_iface(const hound_server_iface_t *iface) 274 368 { … … 276 370 } 277 371 372 /** 373 * Server side implementation of the hound protocol. IPC connection handler. 374 * @param iid initial call id 375 * @param icall pointer to initial call structure. 376 * @param arg (unused) 377 */ 278 378 void hound_connection_handler(ipc_callid_t iid, ipc_call_t *icall, void *arg) 279 379 { … … 291 391 switch (IPC_GET_IMETHOD(call)) { 292 392 case IPC_M_HOUND_CONTEXT_REGISTER: { 393 /* check interface functions */ 293 394 if (!server_iface || !server_iface->add_context) { 294 395 async_answer_0(callid, ENOTSUP); … … 297 398 bool record = IPC_GET_ARG1(call); 298 399 void *name; 400 401 /* Get context name */ 299 402 int ret = 300 403 async_data_write_accept(&name, true, 0, 0, 0, 0); … … 306 409 ret = server_iface->add_context(server_iface->server, 307 410 &id, name, record); 411 /** new context should create a copy */ 412 free(name); 308 413 if (ret != EOK) { 309 free(name);310 414 async_answer_0(callid, ret); 311 415 } else { … … 315 419 } 316 420 case IPC_M_HOUND_CONTEXT_UNREGISTER: { 421 /* check interface functions */ 317 422 if (!server_iface || !server_iface->rem_context) { 318 423 async_answer_0(callid, ENOTSUP); 319 424 break; 320 425 } 426 427 /* get id, 1st param */ 321 428 hound_context_id_t id = IPC_GET_ARG1(call); 322 429 const int ret = … … 326 433 } 327 434 case IPC_M_HOUND_GET_LIST: { 435 /* check interface functions */ 328 436 if (!server_iface || !server_iface->get_list) { 329 437 async_answer_0(callid, ENOTSUP); 330 438 break; 331 439 } 440 332 441 const char **list = NULL; 333 442 const int flags = IPC_GET_ARG1(call); … … 336 445 char *conn_name = NULL; 337 446 int ret = EOK; 447 448 /* get connected actor name if provided */ 338 449 if (conn) 339 450 ret = async_data_write_accept( … … 345 456 conn_name, flags); 346 457 free(conn_name); 458 459 /* Alloc string sizes array */ 347 460 size_t *sizes = NULL; 348 461 if (count) … … 383 496 } 384 497 case IPC_M_HOUND_CONNECT: { 498 /* check interface functions */ 385 499 if (!server_iface || !server_iface->connect) { 386 500 async_answer_0(callid, ENOTSUP); 387 501 break; 388 502 } 503 389 504 void *source = NULL; 390 505 void *sink = NULL; 506 507 /* read source name */ 391 508 int ret = 392 509 async_data_write_accept(&source, true, 0, 0, 0, 0); 510 /* read sink name */ 511 if (ret == EOK) 512 ret = async_data_write_accept(&sink, 513 true, 0, 0, 0, 0); 514 515 if (ret == EOK) 516 ret = server_iface->connect( 517 server_iface->server, source, sink); 518 free(source); 519 free(sink); 520 async_answer_0(callid, ret); 521 break; 522 } 523 case IPC_M_HOUND_DISCONNECT: { 524 /* check interface functions */ 525 if (!server_iface || !server_iface->disconnect) { 526 async_answer_0(callid, ENOTSUP); 527 break; 528 } 529 530 void *source = NULL; 531 void *sink = NULL; 532 533 /* read source name */ 534 int ret = 535 async_data_write_accept(&source, true, 0, 0, 0, 0); 536 /*read sink name */ 393 537 if (ret == EOK) 394 538 ret = async_data_write_accept(&sink, … … 402 546 break; 403 547 } 404 case IPC_M_HOUND_DISCONNECT: {405 if (!server_iface || !server_iface->disconnect) {406 async_answer_0(callid, ENOTSUP);407 break;408 }409 void *source = NULL;410 void *sink = NULL;411 int ret =412 async_data_write_accept(&source, true, 0, 0, 0, 0);413 if (ret == EOK)414 ret = async_data_write_accept(&sink,415 true, 0, 0, 0, 0);416 if (ret == EOK)417 ret = server_iface->connect(418 server_iface->server, source, sink);419 free(source);420 free(sink);421 async_answer_0(callid, ret);422 break;423 }424 548 case IPC_M_HOUND_STREAM_ENTER: { 549 /* check interface functions */ 425 550 if (!server_iface || !server_iface->is_record_context 426 551 || !server_iface->add_stream … … 430 555 } 431 556 557 /* get parameters */ 432 558 hound_context_id_t id = IPC_GET_ARG1(call); 433 559 const int flags = IPC_GET_ARG2(call); … … 439 565 }; 440 566 size_t bsize = IPC_GET_ARG4(call); 567 441 568 void *stream; 442 569 int ret = server_iface->add_stream(server_iface->server, … … 451 578 if(server_iface->stream_data_read) { 452 579 async_answer_0(callid, EOK); 580 /* start answering read calls */ 453 581 hound_server_write_data(stream); 454 582 server_iface->rem_stream( … … 460 588 if (server_iface->stream_data_write) { 461 589 async_answer_0(callid, EOK); 590 /* accept write calls */ 462 591 hound_server_read_data(stream); 463 592 server_iface->rem_stream( … … 481 610 } 482 611 612 /** 613 * Read data and push it to the stream. 614 * @param stream target stream, will push data there. 615 */ 483 616 static void hound_server_read_data(void *stream) 484 617 { … … 487 620 size_t size = 0; 488 621 int ret_answer = EOK; 622 /* accept data write or drain */ 489 623 while (async_data_write_receive_call(&callid, &call, &size) 490 624 || (IPC_GET_IMETHOD(call) == IPC_M_HOUND_STREAM_DRAIN)) { 625 /* check drain first */ 491 626 if (IPC_GET_IMETHOD(call) == IPC_M_HOUND_STREAM_DRAIN) { 492 627 int ret = ENOTSUP; … … 496 631 continue; 497 632 } 633 634 /* there was an error last time */ 498 635 if (ret_answer != EOK) { 499 636 async_answer_0(callid, ret_answer); 500 637 continue; 501 638 } 639 502 640 char *buffer = malloc(size); 503 641 if (!buffer) { … … 507 645 const int ret = async_data_write_finalize(callid, buffer, size); 508 646 if (ret == EOK) { 647 /* push data to stream */ 509 648 ret_answer = server_iface->stream_data_write( 510 649 stream, buffer, size); … … 517 656 } 518 657 658 /** 659 * Accept reads and pull data from the stream. 660 * @param stream target stream, will pull data from there. 661 */ 519 662 static void hound_server_write_data(void *stream) 520 663 { … … 524 667 size_t size = 0; 525 668 int ret_answer = EOK; 669 /* accept data read and drain */ 526 670 while (async_data_read_receive_call(&callid, &call, &size) 527 671 || (IPC_GET_IMETHOD(call) == IPC_M_HOUND_STREAM_DRAIN)) { 672 /* drain does not make much sense but it is allowed */ 528 673 if (IPC_GET_IMETHOD(call) == IPC_M_HOUND_STREAM_DRAIN) { 529 674 int ret = ENOTSUP; … … 533 678 continue; 534 679 } 680 /* there was an error last time */ 535 681 if (ret_answer != EOK) { 536 682 async_answer_0(callid, ret_answer); … … 559 705 ***/ 560 706 707 /** 708 * Register new hound service to the location service. 709 * @param[in] name server name 710 * @param[out] id assigned service id. 711 * @return Error code. 712 */ 561 713 int hound_server_register(const char *name, service_id_t *id) 562 714 { … … 571 723 } 572 724 725 /** 726 * Unregister server from the location service. 727 * @param id previously assigned service id. 728 */ 573 729 void hound_server_unregister(service_id_t id) 574 730 { … … 576 732 } 577 733 734 /** 735 * Set callback on device category change event. 736 * @param cb Callback function. 737 * @return Error code. 738 */ 578 739 int hound_server_set_device_change_callback(dev_change_callback_t cb) 579 740 { … … 581 742 } 582 743 583 744 /** 745 * Walk through all device in the audio-pcm category. 746 * @param callback Function to call on every device. 747 * @return Error code. 748 */ 584 749 int hound_server_devices_iterate(device_callback_t callback) 585 750 {
Note:
See TracChangeset
for help on using the changeset viewer.