summaryrefslogtreecommitdiff
path: root/toxav/toxav.c
diff options
context:
space:
mode:
Diffstat (limited to 'toxav/toxav.c')
-rw-r--r--toxav/toxav.c432
1 files changed, 234 insertions, 198 deletions
diff --git a/toxav/toxav.c b/toxav/toxav.c
index 584b3898..5054d399 100644
--- a/toxav/toxav.c
+++ b/toxav/toxav.c
@@ -42,6 +42,7 @@ enum {
42 42
43typedef struct ToxAVCall_s 43typedef struct ToxAVCall_s
44{ 44{
45 ToxAV* av;
45 pthread_mutex_t mutex_control[1]; 46 pthread_mutex_t mutex_control[1];
46 pthread_mutex_t mutex_encoding_audio[1]; 47 pthread_mutex_t mutex_encoding_audio[1];
47 pthread_mutex_t mutex_encoding_video[1]; 48 pthread_mutex_t mutex_encoding_video[1];
@@ -55,6 +56,8 @@ typedef struct ToxAVCall_s
55 uint32_t s_audio_b; /* Sending audio bitrate */ 56 uint32_t s_audio_b; /* Sending audio bitrate */
56 uint32_t s_video_b; /* Sending video bitrate */ 57 uint32_t s_video_b; /* Sending video bitrate */
57 58
59 uint8_t last_capabilities;
60
58 struct ToxAVCall_s *prev; 61 struct ToxAVCall_s *prev;
59 struct ToxAVCall_s *next; 62 struct ToxAVCall_s *next;
60} ToxAVCall; 63} ToxAVCall;
@@ -83,22 +86,20 @@ struct toxAV
83}; 86};
84 87
85 88
86void i_callback_invite(void* toxav_inst, MSICall* call); 89int callback_invite(void* toxav_inst, MSICall* call);
87void i_callback_ringing(void* toxav_inst, MSICall* call); 90int callback_start(void* toxav_inst, MSICall* call);
88void i_callback_start(void* toxav_inst, MSICall* call); 91int callback_end(void* toxav_inst, MSICall* call);
89void i_callback_end(void* toxav_inst, MSICall* call); 92int callback_error(void* toxav_inst, MSICall* call);
90void i_callback_error(void* toxav_inst, MSICall* call); 93int callback_capabilites(void* toxav_inst, MSICall* call);
91void i_callback_capabilites(void* toxav_inst, MSICall* call);
92 94
93TOXAV_CALL_STATE capabilities_to_state(uint8_t capabilities); 95TOXAV_CALL_STATE capabilities_to_state(uint8_t capabilities);
94ToxAVCall* i_toxav_get_call(ToxAV* av, uint32_t friend_number); 96ToxAVCall* call_new(ToxAV* av, uint32_t friend_number, TOXAV_ERR_CALL* error);
95ToxAVCall* i_toxav_add_call(ToxAV* av, uint32_t friend_number); 97ToxAVCall* call_get(ToxAV* av, uint32_t friend_number);
96void i_toxav_remove_call(ToxAV* av, uint32_t friend_number); 98void call_remove(ToxAVCall* call);
97ToxAVCall* i_toxav_init_call(ToxAV* av, uint32_t friend_number, TOXAV_ERR_CALL* error); 99bool audio_bitrate_invalid(uint32_t bitrate);
98bool i_toxav_audio_bitrate_invalid(uint32_t bitrate); 100bool video_bitrate_invalid(uint32_t bitrate);
99bool i_toxav_video_bitrate_invalid(uint32_t bitrate); 101bool call_prepare_transmission(ToxAVCall* call);
100bool i_toxav_prepare_transmission(ToxAV* av, ToxAVCall* call); 102void call_kill_transmission(ToxAVCall* call);
101void i_toxav_kill_transmission(ToxAV* av, uint32_t friend_number);
102 103
103 104
104 105
@@ -136,14 +137,12 @@ ToxAV* toxav_new(Tox* tox, TOXAV_ERR_NEW* error)
136 av->interval = 200; 137 av->interval = 200;
137 av->msi->av = av; 138 av->msi->av = av;
138 139
139 msi_register_callback(av->msi, i_callback_invite, msi_OnInvite); 140 msi_register_callback(av->msi, callback_invite, msi_OnInvite);
140 msi_register_callback(av->msi, i_callback_ringing, msi_OnRinging); 141 msi_register_callback(av->msi, callback_start, msi_OnStart);
141 msi_register_callback(av->msi, i_callback_start, msi_OnStart); 142 msi_register_callback(av->msi, callback_end, msi_OnEnd);
142 msi_register_callback(av->msi, i_callback_end, msi_OnReject); 143 msi_register_callback(av->msi, callback_error, msi_OnError);
143 msi_register_callback(av->msi, i_callback_end, msi_OnEnd); 144 msi_register_callback(av->msi, callback_error, msi_OnPeerTimeout);
144 msi_register_callback(av->msi, i_callback_error, msi_OnError); 145 msi_register_callback(av->msi, callback_capabilites, msi_OnCapabilities);
145 msi_register_callback(av->msi, i_callback_error, msi_OnPeerTimeout);
146 msi_register_callback(av->msi, i_callback_capabilites, msi_OnCapabilities);
147 146
148 147
149 if (error) 148 if (error)
@@ -166,7 +165,16 @@ void toxav_kill(ToxAV* av)
166 return; 165 return;
167 166
168 msi_kill(av->msi); 167 msi_kill(av->msi);
169 /* TODO iterate over calls */ 168
169 /* Msi kill will hang up all calls so just clean these calls */
170 if (av->calls) {
171 ToxAVCall* it = call_get(av, av->calls_head);
172 for (; it; it = it->next) {
173 call_kill_transmission(it);
174 call_remove(it); /* This will eventually free av->calls */
175 }
176 }
177
170 free(av); 178 free(av);
171} 179}
172 180
@@ -208,20 +216,20 @@ void toxav_iteration(ToxAV* av)
208 216
209bool toxav_call(ToxAV* av, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_CALL* error) 217bool toxav_call(ToxAV* av, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_CALL* error)
210{ 218{
211 ToxAVCall* call = i_toxav_init_call(av, friend_number, error); 219 ToxAVCall* call = call_new(av, friend_number, error);
212 if (call == NULL) 220 if (call == NULL)
213 return false; 221 return false;
214 222
215 call->s_audio_b = audio_bit_rate; 223 call->s_audio_b = audio_bit_rate;
216 call->s_video_b = video_bit_rate; 224 call->s_video_b = video_bit_rate;
217 225
218 uint8_t capabilities = 0; 226 call->last_capabilities = msi_CapRAudio | msi_CapRVideo;
219 227
220 capabilities |= audio_bit_rate > 0 ? msi_CapSAudio : 0; 228 call->last_capabilities |= audio_bit_rate > 0 ? msi_CapSAudio : 0;
221 capabilities |= video_bit_rate > 0 ? msi_CapSVideo : 0; 229 call->last_capabilities |= video_bit_rate > 0 ? msi_CapSVideo : 0;
222 230
223 if (msi_invite(av->msi, &call->msi_call, friend_number, capabilities) != 0) { 231 if (msi_invite(av->msi, &call->msi_call, friend_number, call->last_capabilities) != 0) {
224 i_toxav_remove_call(av, friend_number); 232 call_remove(call);
225 if (error) 233 if (error)
226 *error = TOXAV_ERR_CALL_MALLOC; 234 *error = TOXAV_ERR_CALL_MALLOC;
227 return false; 235 return false;
@@ -244,14 +252,14 @@ bool toxav_answer(ToxAV* av, uint32_t friend_number, uint32_t audio_bit_rate, ui
244 goto END; 252 goto END;
245 } 253 }
246 254
247 if ((audio_bit_rate && i_toxav_audio_bitrate_invalid(audio_bit_rate)) 255 if ((audio_bit_rate && audio_bitrate_invalid(audio_bit_rate))
248 ||(video_bit_rate && i_toxav_video_bitrate_invalid(video_bit_rate)) 256 ||(video_bit_rate && video_bitrate_invalid(video_bit_rate))
249 ) { 257 ) {
250 rc = TOXAV_ERR_CALL_INVALID_BIT_RATE; 258 rc = TOXAV_ERR_CALL_INVALID_BIT_RATE;
251 goto END; 259 goto END;
252 } 260 }
253 261
254 ToxAVCall* call = i_toxav_get_call(av, friend_number); 262 ToxAVCall* call = call_get(av, friend_number);
255 if (call == NULL) { 263 if (call == NULL) {
256 rc = TOXAV_ERR_ANSWER_FRIEND_NOT_CALLING; 264 rc = TOXAV_ERR_ANSWER_FRIEND_NOT_CALLING;
257 goto END; 265 goto END;
@@ -260,12 +268,12 @@ bool toxav_answer(ToxAV* av, uint32_t friend_number, uint32_t audio_bit_rate, ui
260 call->s_audio_b = audio_bit_rate; 268 call->s_audio_b = audio_bit_rate;
261 call->s_video_b = video_bit_rate; 269 call->s_video_b = video_bit_rate;
262 270
263 uint8_t capabilities = 0; 271 call->last_capabilities = msi_CapRAudio | msi_CapRVideo;
264 272
265 capabilities |= audio_bit_rate > 0 ? msi_CapSAudio : 0; 273 call->last_capabilities |= audio_bit_rate > 0 ? msi_CapSAudio : 0;
266 capabilities |= video_bit_rate > 0 ? msi_CapSVideo : 0; 274 call->last_capabilities |= video_bit_rate > 0 ? msi_CapSVideo : 0;
267 275
268 if (msi_answer(call->msi_call, capabilities) != 0) 276 if (msi_answer(call->msi_call, call->last_capabilities) != 0)
269 rc = TOXAV_ERR_ANSWER_FRIEND_NOT_CALLING; /* the only reason for msi_answer to fail */ 277 rc = TOXAV_ERR_ANSWER_FRIEND_NOT_CALLING; /* the only reason for msi_answer to fail */
270 278
271 279
@@ -292,7 +300,7 @@ bool toxav_call_control(ToxAV* av, uint32_t friend_number, TOXAV_CALL_CONTROL co
292 } 300 }
293 301
294 302
295 ToxAVCall* call = i_toxav_get_call(av, friend_number); 303 ToxAVCall* call = call_get(av, friend_number);
296 if (call == NULL) { 304 if (call == NULL) {
297 rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL; 305 rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL;
298 goto END; 306 goto END;
@@ -302,29 +310,53 @@ bool toxav_call_control(ToxAV* av, uint32_t friend_number, TOXAV_CALL_CONTROL co
302 switch (control) 310 switch (control)
303 { 311 {
304 case TOXAV_CALL_CONTROL_RESUME: { 312 case TOXAV_CALL_CONTROL_RESUME: {
305 313 if (call->msi_call->self_capabilities == 0 &&
314 call->last_capabilities ) {
315 /* Only act if paused and had media transfer active before */
316
317 if (msi_change_capabilities(call->msi_call, call->last_capabilities) == -1)
318 return false;
319
320 rtp_start_receiving(call->rtps[audio_index]);
321 rtp_start_receiving(call->rtps[video_index]);
322 }
306 } break; 323 } break;
307 324
308 case TOXAV_CALL_CONTROL_PAUSE: { 325 case TOXAV_CALL_CONTROL_PAUSE: {
309 326 if (call->msi_call->self_capabilities) {
327 /* Only act if not already paused */
328
329 call->last_capabilities = call->msi_call->self_capabilities;
330
331 if (msi_change_capabilities(call->msi_call, 0) == -1 )
332 return false;
333
334 rtp_stop_receiving(call->rtps[audio_index]);
335 rtp_stop_receiving(call->rtps[video_index]);
336 }
310 } break; 337 } break;
311 338
312 case TOXAV_CALL_CONTROL_CANCEL: { 339 case TOXAV_CALL_CONTROL_CANCEL: {
313 if (call->msi_call->state == msi_CallActive 340 /* Hang up */
314 || call->msi_call->state == msi_CallRequesting) { 341 msi_hangup(call->msi_call);
315 /* Hang up */
316 msi_hangup(call->msi_call);
317 } else if (call->msi_call->state == msi_CallRequested) {
318 /* Reject the call */
319 msi_reject(call->msi_call);
320 }
321 342
322 // No mather the case, terminate the call 343 /* No mather the case, terminate the call */
323 i_toxav_remove_call(av, friend_number); 344 call_remove(call);
324 } break; 345 } break;
325 346
326 case TOXAV_CALL_CONTROL_MUTE_AUDIO: { 347 case TOXAV_CALL_CONTROL_MUTE_AUDIO: {
327 348 if (call->msi_call->self_capabilities & msi_CapRAudio ||
349 call->msi_call->self_capabilities & msi_CapSAudio) {
350
351 uint8_t capabilities = call->msi_call->self_capabilities;
352 capabilities ^= msi_CapRAudio;
353 capabilities ^= msi_CapRAudio;
354
355 if (msi_change_capabilities(call->msi_call, call->msi_call->self_capabilities) == -1)
356 return false;
357
358 rtp_stop_receiving(call->rtps[audio_index]);
359 }
328 } break; 360 } break;
329 361
330 case TOXAV_CALL_CONTROL_MUTE_VIDEO: { 362 case TOXAV_CALL_CONTROL_MUTE_VIDEO: {
@@ -364,7 +396,7 @@ bool toxav_send_video_frame(ToxAV* av, uint32_t friend_number, uint16_t width, u
364 goto END; 396 goto END;
365 } 397 }
366 398
367 call = i_toxav_get_call(av, friend_number); 399 call = call_get(av, friend_number);
368 if (call == NULL) { 400 if (call == NULL) {
369 rc = TOXAV_ERR_SEND_FRAME_FRIEND_NOT_IN_CALL; 401 rc = TOXAV_ERR_SEND_FRAME_FRIEND_NOT_IN_CALL;
370 goto END; 402 goto END;
@@ -461,7 +493,7 @@ bool toxav_send_audio_frame(ToxAV* av, uint32_t friend_number, const int16_t* pc
461 goto END; 493 goto END;
462 } 494 }
463 495
464 call = i_toxav_get_call(av, friend_number); 496 call = call_get(av, friend_number);
465 if (call == NULL) { 497 if (call == NULL) {
466 rc = TOXAV_ERR_SEND_FRAME_FRIEND_NOT_IN_CALL; 498 rc = TOXAV_ERR_SEND_FRAME_FRIEND_NOT_IN_CALL;
467 goto END; 499 goto END;
@@ -526,19 +558,16 @@ void toxav_callback_receive_audio_frame(ToxAV* av, toxav_receive_audio_frame_cb*
526 * :: Internal 558 * :: Internal
527 * 559 *
528 ******************************************************************************/ 560 ******************************************************************************/
529/** TODO: 561/** TODO:
530 * - If crutial callback not present send error.
531 * - Error handling by return values from callbacks and setting 'error'.
532 */ 562 */
533void i_callback_invite(void* toxav_inst, MSICall* call) 563int callback_invite(void* toxav_inst, MSICall* call)
534{ 564{
535 ToxAV* toxav = toxav_inst; 565 ToxAV* toxav = toxav_inst;
536 566
537 ToxAVCall* av_call = i_toxav_init_call(toxav, call->friend_id, NULL); 567 ToxAVCall* av_call = call_new(toxav, call->friend_id, NULL);
538 if (av_call == NULL) { 568 if (av_call == NULL) {
539 LOGGER_WARNING("Failed to start call, rejecting..."); 569 LOGGER_WARNING("Failed to initialize call...");
540 msi_reject(call); 570 return -1;
541 return;
542 } 571 }
543 572
544 call->av_call = av_call; 573 call->av_call = av_call;
@@ -547,55 +576,59 @@ void i_callback_invite(void* toxav_inst, MSICall* call)
547 if (toxav->ccb.first) 576 if (toxav->ccb.first)
548 toxav->ccb.first(toxav, call->friend_id, call->peer_capabilities & msi_CapSAudio, 577 toxav->ccb.first(toxav, call->friend_id, call->peer_capabilities & msi_CapSAudio,
549 call->peer_capabilities & msi_CapSVideo, toxav->ccb.second); 578 call->peer_capabilities & msi_CapSVideo, toxav->ccb.second);
579
580 return 0;
550} 581}
551 582
552void i_callback_ringing(void* toxav_inst, MSICall* call) 583int callback_start(void* toxav_inst, MSICall* call)
553{
554 ToxAV* toxav = toxav_inst;
555 if (toxav->scb.first)
556 toxav->scb.first(toxav, call->friend_id, TOXAV_CALL_STATE_RINGING, toxav->scb.second);
557}
558
559void i_callback_start(void* toxav_inst, MSICall* call)
560{ 584{
561 ToxAV* toxav = toxav_inst; 585 ToxAV* toxav = toxav_inst;
562 586
563 ToxAVCall* av_call = i_toxav_get_call(toxav, call->friend_id); 587 ToxAVCall* av_call = call_get(toxav, call->friend_id);
564 588
565 if (av_call == NULL || !i_toxav_prepare_transmission(toxav, av_call)) { 589 if (av_call == NULL || !call_prepare_transmission(av_call)) {
566 /* TODO send error */ 590 call_remove(av_call);
567 i_toxav_remove_call(toxav, call->friend_id); 591 return -1;
568 return;
569 } 592 }
570 593
571 TOXAV_CALL_STATE state = capabilities_to_state(av_call->msi_call->peer_capabilities); 594 TOXAV_CALL_STATE state = capabilities_to_state(av_call->msi_call->peer_capabilities);
572 595
573 if (toxav->scb.first) 596 if (toxav->scb.first)
574 toxav->scb.first(toxav, call->friend_id, state, toxav->scb.second); 597 toxav->scb.first(toxav, call->friend_id, state, toxav->scb.second);
598
599 return 0;
575} 600}
576 601
577void i_callback_end(void* toxav_inst, MSICall* call) 602int callback_end(void* toxav_inst, MSICall* call)
578{ 603{
579 ToxAV* toxav = toxav_inst; 604 ToxAV* toxav = toxav_inst;
580 605
581 i_toxav_kill_transmission(toxav, call->friend_id); 606 call_kill_transmission(call->av_call);
582 i_toxav_remove_call(toxav, call->friend_id); 607 call_remove(call->av_call);
583 608
584 if (toxav->scb.first) 609 if (toxav->scb.first)
585 toxav->scb.first(toxav, call->friend_id, TOXAV_CALL_STATE_END, toxav->scb.second); 610 toxav->scb.first(toxav, call->friend_id, TOXAV_CALL_STATE_END, toxav->scb.second);
611
612 return 0;
586} 613}
587 614
588void i_callback_error(void* toxav_inst, MSICall* call) 615int callback_error(void* toxav_inst, MSICall* call)
589{ 616{
590 ToxAV* toxav = toxav_inst; 617 ToxAV* toxav = toxav_inst;
591 if (toxav->scb.first) 618 if (toxav->scb.first)
592 toxav->scb.first(toxav, call->friend_id, TOXAV_CALL_STATE_ERROR, toxav->scb.second); 619 toxav->scb.first(toxav, call->friend_id, TOXAV_CALL_STATE_ERROR, toxav->scb.second);
620
621 return 0;
593} 622}
594 623
595void i_callback_capabilites(void* toxav_inst, MSICall* call) 624int callback_capabilites(void* toxav_inst, MSICall* call)
596{ 625{
597 ToxAV* toxav = toxav_inst; 626 ToxAV* toxav = toxav_inst;
598 /* TODO handle this */ 627 if (toxav->scb.first)
628 toxav->scb.first(toxav, call->friend_id,
629 capabilities_to_state(call->peer_capabilities), toxav->scb.second);
630
631 return 0;
599} 632}
600 633
601TOXAV_CALL_STATE capabilities_to_state(uint8_t capabilities) 634TOXAV_CALL_STATE capabilities_to_state(uint8_t capabilities)
@@ -610,32 +643,64 @@ TOXAV_CALL_STATE capabilities_to_state(uint8_t capabilities)
610 return TOXAV_CALL_STATE_PAUSED; 643 return TOXAV_CALL_STATE_PAUSED;
611} 644}
612 645
613ToxAVCall* i_toxav_get_call(ToxAV* av, uint32_t friend_number) 646bool audio_bitrate_invalid(uint32_t bitrate)
614{ 647{
615 if (av->calls == NULL || av->calls_tail < friend_number) 648 /* Opus RFC 6716 section-2.1.1 dictates the following:
616 return NULL; 649 * Opus supports all bitrates from 6 kbit/s to 510 kbit/s.
617 650 */
618 return av->calls[friend_number]; 651 return bitrate < 6 || bitrate > 510;
619} 652}
620 653
621ToxAVCall* i_toxav_add_call(ToxAV* av, uint32_t friend_number) 654bool video_bitrate_invalid(uint32_t bitrate)
622{ 655{
623 ToxAVCall* rc = calloc(sizeof(ToxAVCall), 1); 656 /* TODO: If anyone knows the answer to this one please fill it up */
657 return false;
658}
659
660ToxAVCall* call_new(ToxAV* av, uint32_t friend_number, TOXAV_ERR_CALL* error)
661{
662 TOXAV_ERR_CALL rc = TOXAV_ERR_CALL_OK;
663 ToxAVCall* call = NULL;
624 664
625 if (rc == NULL) 665 if (m_friend_exists(av->m, friend_number) == 0) {
626 return NULL; 666 rc = TOXAV_ERR_CALL_FRIEND_NOT_FOUND;
667 goto END;
668 }
627 669
628 rc->friend_id = friend_number; 670 if (m_get_friend_connectionstatus(av->m, friend_number) != 1) {
671 rc = TOXAV_ERR_CALL_FRIEND_NOT_CONNECTED;
672 goto END;
673 }
629 674
630 if (create_recursive_mutex(rc->mutex_control) != 0) { 675 if (call_get(av, friend_number) != NULL) {
631 free(rc); 676 rc = TOXAV_ERR_CALL_FRIEND_ALREADY_IN_CALL;
632 return NULL; 677 goto END;
633 } 678 }
634 679
635 if (create_recursive_mutex(rc->mutex_do) != 0) { 680
636 pthread_mutex_destroy(rc->mutex_control); 681 call = calloc(sizeof(ToxAVCall), 1);
637 free(rc); 682
638 return NULL; 683 if (call == NULL) {
684 rc = TOXAV_ERR_CALL_MALLOC;
685 goto END;
686 }
687
688 call->av = av;
689 call->friend_id = friend_number;
690
691 if (create_recursive_mutex(call->mutex_control) != 0) {
692 free(call);
693 call = NULL;
694 rc = TOXAV_ERR_CALL_MALLOC;
695 goto END;
696 }
697
698 if (create_recursive_mutex(call->mutex_do) != 0) {
699 pthread_mutex_destroy(call->mutex_control);
700 free(call);
701 call = NULL;
702 rc = TOXAV_ERR_CALL_MALLOC;
703 goto END;
639 } 704 }
640 705
641 706
@@ -643,10 +708,12 @@ ToxAVCall* i_toxav_add_call(ToxAV* av, uint32_t friend_number)
643 av->calls = calloc (sizeof(ToxAVCall*), friend_number + 1); 708 av->calls = calloc (sizeof(ToxAVCall*), friend_number + 1);
644 709
645 if (av->calls == NULL) { 710 if (av->calls == NULL) {
646 pthread_mutex_destroy(rc->mutex_control); 711 pthread_mutex_destroy(call->mutex_control);
647 pthread_mutex_destroy(rc->mutex_do); 712 pthread_mutex_destroy(call->mutex_do);
648 free(rc); 713 free(call);
649 return NULL; 714 call = NULL;
715 rc = TOXAV_ERR_CALL_MALLOC;
716 goto END;
650 } 717 }
651 718
652 av->calls_tail = av->calls_head = friend_number; 719 av->calls_tail = av->calls_head = friend_number;
@@ -655,10 +722,12 @@ ToxAVCall* i_toxav_add_call(ToxAV* av, uint32_t friend_number)
655 void* tmp = realloc(av->calls, sizeof(ToxAVCall*) * friend_number + 1); 722 void* tmp = realloc(av->calls, sizeof(ToxAVCall*) * friend_number + 1);
656 723
657 if (tmp == NULL) { 724 if (tmp == NULL) {
658 pthread_mutex_destroy(rc->mutex_control); 725 pthread_mutex_destroy(call->mutex_control);
659 pthread_mutex_destroy(rc->mutex_do); 726 pthread_mutex_destroy(call->mutex_do);
660 free(rc); 727 free(call);
661 return NULL; 728 call = NULL;
729 rc = TOXAV_ERR_CALL_MALLOC;
730 goto END;
662 } 731 }
663 732
664 av->calls = tmp; 733 av->calls = tmp;
@@ -668,105 +737,41 @@ ToxAVCall* i_toxav_add_call(ToxAV* av, uint32_t friend_number)
668 for (; i < friend_number; i ++) 737 for (; i < friend_number; i ++)
669 av->calls[i] = NULL; 738 av->calls[i] = NULL;
670 739
671 rc->prev = av->calls[av->calls_tail]; 740 call->prev = av->calls[av->calls_tail];
672 av->calls[av->calls_tail]->next = rc; 741 av->calls[av->calls_tail]->next = call;
673 742
674 av->calls_tail = friend_number; 743 av->calls_tail = friend_number;
675 744
676 } else if (av->calls_head > friend_number) { /* Inserting at front */ 745 } else if (av->calls_head > friend_number) { /* Inserting at front */
677 rc->next = av->calls[av->calls_head]; 746 call->next = av->calls[av->calls_head];
678 av->calls[av->calls_head]->prev = rc; 747 av->calls[av->calls_head]->prev = call;
679 av->calls_head = friend_number; 748 av->calls_head = friend_number;
680 } 749 }
681 750
682 av->calls[friend_number] = rc; 751 av->calls[friend_number] = call;
683 return rc;
684}
685
686void i_toxav_remove_call(ToxAV* av, uint32_t friend_number)
687{
688 ToxAVCall* tc = i_toxav_get_call(av, friend_number);
689
690 if (tc == NULL)
691 return;
692
693 ToxAVCall* prev = tc->prev;
694 ToxAVCall* next = tc->next;
695
696 pthread_mutex_destroy(tc->mutex_control);
697 pthread_mutex_destroy(tc->mutex_do);
698
699 free(tc);
700
701 if (prev)
702 prev->next = next;
703 else if (next)
704 av->calls_head = next->friend_id;
705 else goto CLEAR;
706 752
707 if (next) 753END:
708 next->prev = prev;
709 else if (prev)
710 av->calls_tail = prev->friend_id;
711 else goto CLEAR;
712
713 av->calls[friend_number] = NULL;
714 return;
715
716CLEAR:
717 av->calls_head = av->calls_tail = 0;
718 free(av->calls);
719 av->calls = NULL;
720}
721
722ToxAVCall* i_toxav_init_call(ToxAV* av, uint32_t friend_number, TOXAV_ERR_CALL* error)
723{
724 TOXAV_ERR_CALL rc = TOXAV_ERR_CALL_OK;
725 ToxAVCall* call = NULL;
726
727 if (m_friend_exists(av->m, friend_number) == 0) {
728 rc = TOXAV_ERR_CALL_FRIEND_NOT_FOUND;
729 goto END;
730 }
731
732 if (m_get_friend_connectionstatus(av->m, friend_number) != 1) {
733 rc = TOXAV_ERR_CALL_FRIEND_NOT_CONNECTED;
734 goto END;
735 }
736
737 if (i_toxav_get_call(av, friend_number) != NULL) {
738 rc = TOXAV_ERR_CALL_FRIEND_ALREADY_IN_CALL;
739 goto END;
740 }
741
742 call = i_toxav_add_call(av, friend_number);
743 if (call == NULL) {
744 rc = TOXAV_ERR_CALL_MALLOC;
745 }
746
747 END:
748 if (error) 754 if (error)
749 *error = rc; 755 *error = rc;
750 756
751 return call; 757 return call;
752} 758}
753 759
754bool i_toxav_audio_bitrate_invalid(uint32_t bitrate) 760ToxAVCall* call_get(ToxAV* av, uint32_t friend_number)
755{ 761{
756 /* Opus RFC 6716 section-2.1.1 dictates the following: 762 if (av->calls == NULL || av->calls_tail < friend_number)
757 * Opus supports all bitrates from 6 kbit/s to 510 kbit/s. 763 return NULL;
758 */ 764
759 return bitrate < 6 || bitrate > 510; 765 return av->calls[friend_number];
760}
761
762bool i_toxav_video_bitrate_invalid(uint32_t bitrate)
763{
764 /* TODO: If anyone knows the answer to this one please fill it up */
765 return false;
766} 766}
767 767
768bool i_toxav_prepare_transmission(ToxAV* av, ToxAVCall* call) 768bool call_prepare_transmission(ToxAVCall* call)
769{ 769{
770 if (call == NULL)
771 return false;
772
773 ToxAV* av = call->av;
774
770 if (!av->acb.first && !av->vcb.first) 775 if (!av->acb.first && !av->vcb.first)
771 /* It makes no sense to have CSession without callbacks */ 776 /* It makes no sense to have CSession without callbacks */
772 return false; 777 return false;
@@ -830,7 +835,7 @@ bool i_toxav_prepare_transmission(ToxAV* av, ToxAVCall* call)
830 goto FAILURE; 835 goto FAILURE;
831 } 836 }
832 837
833 rtp_register_for_receiving(call->rtps[audio_index]); 838 rtp_start_receiving(call->rtps[audio_index]);
834 } 839 }
835 } 840 }
836 841
@@ -854,8 +859,8 @@ bool i_toxav_prepare_transmission(ToxAV* av, ToxAVCall* call)
854 LOGGER_WARNING("Failed to enable video receiving!"); 859 LOGGER_WARNING("Failed to enable video receiving!");
855 goto FAILURE; 860 goto FAILURE;
856 } 861 }
857 862
858 rtp_register_for_receiving(call->rtps[audio_index]); 863 rtp_start_receiving(call->rtps[audio_index]);
859 } 864 }
860 } 865 }
861 866
@@ -863,7 +868,7 @@ bool i_toxav_prepare_transmission(ToxAV* av, ToxAVCall* call)
863 pthread_mutex_unlock(call->mutex_control); 868 pthread_mutex_unlock(call->mutex_control);
864 return true; 869 return true;
865 870
866FAILURE: 871 FAILURE:
867 rtp_kill(call->rtps[audio_index]); 872 rtp_kill(call->rtps[audio_index]);
868 call->rtps[audio_index] = NULL; 873 call->rtps[audio_index] = NULL;
869 rtp_kill(call->rtps[video_index]); 874 rtp_kill(call->rtps[video_index]);
@@ -878,25 +883,19 @@ FAILURE:
878 pthread_mutex_unlock(call->mutex_control); 883 pthread_mutex_unlock(call->mutex_control);
879 return false; 884 return false;
880 885
881MUTEX_INIT_ERROR: 886 MUTEX_INIT_ERROR:
882 pthread_mutex_unlock(call->mutex_control); 887 pthread_mutex_unlock(call->mutex_control);
883 LOGGER_ERROR("Mutex initialization failed!\n"); 888 LOGGER_ERROR("Mutex initialization failed!\n");
884 return false; 889 return false;
885} 890}
886 891
887void i_toxav_kill_transmission(ToxAV* av, uint32_t friend_number) 892void call_kill_transmission(ToxAVCall* call)
888{ 893{
889 ToxAVCall* call = i_toxav_get_call(av, friend_number); 894 if (call == NULL || call->active == 0)
890 if (!call)
891 return; 895 return;
892 896
893 pthread_mutex_lock(call->mutex_control); 897 pthread_mutex_lock(call->mutex_control);
894 898
895 if (!call->active) {
896 pthread_mutex_unlock(call->mutex_control);
897 return;
898 }
899
900 call->active = 0; 899 call->active = 0;
901 900
902 pthread_mutex_lock(call->mutex_encoding_audio); 901 pthread_mutex_lock(call->mutex_encoding_audio);
@@ -918,4 +917,41 @@ void i_toxav_kill_transmission(ToxAV* av, uint32_t friend_number)
918 pthread_mutex_destroy(call->mutex_do); 917 pthread_mutex_destroy(call->mutex_do);
919 918
920 pthread_mutex_unlock(call->mutex_control); 919 pthread_mutex_unlock(call->mutex_control);
920}
921
922void call_remove(ToxAVCall* call)
923{
924 if (call == NULL)
925 return;
926
927 uint32_t friend_id = call->friend_id;
928 ToxAV* av = call->av;
929
930 ToxAVCall* prev = call->prev;
931 ToxAVCall* next = call->next;
932
933 pthread_mutex_destroy(call->mutex_control);
934 pthread_mutex_destroy(call->mutex_do);
935
936 free(call);
937
938 if (prev)
939 prev->next = next;
940 else if (next)
941 av->calls_head = next->friend_id;
942 else goto CLEAR;
943
944 if (next)
945 next->prev = prev;
946 else if (prev)
947 av->calls_tail = prev->friend_id;
948 else goto CLEAR;
949
950 av->calls[friend_id] = NULL;
951 return;
952
953CLEAR:
954 av->calls_head = av->calls_tail = 0;
955 free(av->calls);
956 av->calls = NULL;
921} \ No newline at end of file 957} \ No newline at end of file