diff options
Diffstat (limited to 'toxav')
-rw-r--r-- | toxav/av_test.c | 173 | ||||
-rw-r--r-- | toxav/msi.h | 2 | ||||
-rw-r--r-- | toxav/toxav.c | 184 | ||||
-rw-r--r-- | toxav/toxav.h | 22 |
4 files changed, 266 insertions, 115 deletions
diff --git a/toxav/av_test.c b/toxav/av_test.c index 594e7232..41f5a758 100644 --- a/toxav/av_test.c +++ b/toxav/av_test.c | |||
@@ -16,13 +16,25 @@ | |||
16 | 16 | ||
17 | typedef struct { | 17 | typedef struct { |
18 | bool incoming; | 18 | bool incoming; |
19 | bool ringing; | 19 | TOXAV_CALL_STATE state; |
20 | bool ended; | ||
21 | bool errored; | ||
22 | bool sending; | ||
23 | bool paused; | ||
24 | } CallControl; | 20 | } CallControl; |
25 | 21 | ||
22 | const char* stringify_state(TOXAV_CALL_STATE s) | ||
23 | { | ||
24 | static const char* strings[] = | ||
25 | { | ||
26 | "NOT SENDING", | ||
27 | "SENDING AUDIO", | ||
28 | "SENDING VIDEO", | ||
29 | "SENDING AUDIO AND VIDEO", | ||
30 | "PAUSED", | ||
31 | "END", | ||
32 | "ERROR" | ||
33 | }; | ||
34 | |||
35 | return strings [s]; | ||
36 | }; | ||
37 | |||
26 | 38 | ||
27 | /** | 39 | /** |
28 | * Callbacks | 40 | * Callbacks |
@@ -34,53 +46,9 @@ void t_toxav_call_cb(ToxAV *av, uint32_t friend_number, bool audio_enabled, bool | |||
34 | } | 46 | } |
35 | void t_toxav_call_state_cb(ToxAV *av, uint32_t friend_number, TOXAV_CALL_STATE state, void *user_data) | 47 | void t_toxav_call_state_cb(ToxAV *av, uint32_t friend_number, TOXAV_CALL_STATE state, void *user_data) |
36 | { | 48 | { |
37 | printf("Handling CALL STATE callback: "); | 49 | printf("Handling CALL STATE callback: %s\n", stringify_state(state)); |
38 | |||
39 | if (((CallControl*)user_data)->paused) | ||
40 | ((CallControl*)user_data)->paused = false; | ||
41 | |||
42 | switch (state) | ||
43 | { | ||
44 | case TOXAV_CALL_STATE_NOT_SENDING: { | ||
45 | printf("Not sending"); | ||
46 | ((CallControl*)user_data)->sending = false; | ||
47 | } break; | ||
48 | |||
49 | case TOXAV_CALL_STATE_SENDING_A: { | ||
50 | printf("Sending Audio"); | ||
51 | ((CallControl*)user_data)->sending = true; | ||
52 | } break; | ||
53 | |||
54 | case TOXAV_CALL_STATE_SENDING_V: { | ||
55 | printf("Sending Video"); | ||
56 | ((CallControl*)user_data)->sending = true; | ||
57 | } break; | ||
58 | |||
59 | case TOXAV_CALL_STATE_SENDING_AV: { | ||
60 | printf("Sending Both"); | ||
61 | ((CallControl*)user_data)->sending = true; | ||
62 | } break; | ||
63 | |||
64 | case TOXAV_CALL_STATE_PAUSED: { | ||
65 | printf("Paused"); | ||
66 | ((CallControl*)user_data)->paused = true; | ||
67 | ((CallControl*)user_data)->sending = false; | ||
68 | } break; | ||
69 | |||
70 | case TOXAV_CALL_STATE_END: { | ||
71 | printf("Ended"); | ||
72 | ((CallControl*)user_data)->ended = true; | ||
73 | ((CallControl*)user_data)->sending = false; | ||
74 | } break; | ||
75 | |||
76 | case TOXAV_CALL_STATE_ERROR: { | ||
77 | printf("Error"); | ||
78 | ((CallControl*)user_data)->errored = true; | ||
79 | ((CallControl*)user_data)->sending = false; | ||
80 | } break; | ||
81 | } | ||
82 | 50 | ||
83 | printf("\n"); | 51 | ((CallControl*)user_data)->state = state; |
84 | } | 52 | } |
85 | void t_toxav_receive_video_frame_cb(ToxAV *av, uint32_t friend_number, | 53 | void t_toxav_receive_video_frame_cb(ToxAV *av, uint32_t friend_number, |
86 | uint16_t width, uint16_t height, | 54 | uint16_t width, uint16_t height, |
@@ -211,27 +179,24 @@ int main (int argc, char** argv) | |||
211 | long long unsigned int start_time = time(NULL); \ | 179 | long long unsigned int start_time = time(NULL); \ |
212 | \ | 180 | \ |
213 | \ | 181 | \ |
214 | while (!AliceCC.ended || !BobCC.ended) { \ | 182 | while (BobCC.state != TOXAV_CALL_STATE_END) { \ |
215 | \ | 183 | \ |
216 | if (BobCC.incoming) { \ | 184 | if (BobCC.incoming) { \ |
217 | TOXAV_ERR_ANSWER rc; \ | 185 | TOXAV_ERR_ANSWER rc; \ |
218 | toxav_answer(BobAV, 0, 48, 4000, &rc); \ | 186 | toxav_answer(BobAV, 0, A_BR, V_BR, &rc); \ |
219 | \ | 187 | \ |
220 | if (rc != TOXAV_ERR_ANSWER_OK) { \ | 188 | if (rc != TOXAV_ERR_ANSWER_OK) { \ |
221 | printf("toxav_answer failed: %d\n", rc); \ | 189 | printf("toxav_answer failed: %d\n", rc); \ |
222 | exit(1); \ | 190 | exit(1); \ |
223 | } \ | 191 | } \ |
224 | BobCC.incoming = false; \ | 192 | BobCC.incoming = false; \ |
225 | BobCC.sending = true; /* There is no more start callback when answering */\ | 193 | } else { \ |
226 | } \ | ||
227 | else if (AliceCC.sending && BobCC.sending) { \ | ||
228 | /* TODO rtp */ \ | 194 | /* TODO rtp */ \ |
229 | \ | 195 | \ |
230 | if (time(NULL) - start_time == 5) { \ | 196 | if (time(NULL) - start_time == 5) { \ |
231 | \ | 197 | \ |
232 | TOXAV_ERR_CALL_CONTROL rc; \ | 198 | TOXAV_ERR_CALL_CONTROL rc; \ |
233 | toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_CANCEL, &rc); \ | 199 | toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_CANCEL, &rc); \ |
234 | AliceCC.ended = true; /* There is no more end callback when hanging up */\ | ||
235 | \ | 200 | \ |
236 | if (rc != TOXAV_ERR_CALL_CONTROL_OK) { \ | 201 | if (rc != TOXAV_ERR_CALL_CONTROL_OK) { \ |
237 | printf("toxav_call_control failed: %d\n", rc); \ | 202 | printf("toxav_call_control failed: %d\n", rc); \ |
@@ -286,7 +251,7 @@ int main (int argc, char** argv) | |||
286 | } | 251 | } |
287 | } | 252 | } |
288 | 253 | ||
289 | while (!AliceCC.ended) | 254 | while (AliceCC.state != TOXAV_CALL_STATE_END) |
290 | iterate(Bsn, AliceAV, BobAV); | 255 | iterate(Bsn, AliceAV, BobAV); |
291 | 256 | ||
292 | printf("Success!\n"); | 257 | printf("Success!\n"); |
@@ -323,9 +288,99 @@ int main (int argc, char** argv) | |||
323 | } | 288 | } |
324 | 289 | ||
325 | /* Alice will not receive end state */ | 290 | /* Alice will not receive end state */ |
326 | while (!BobCC.ended) | 291 | while (BobCC.state != TOXAV_CALL_STATE_END) |
292 | iterate(Bsn, AliceAV, BobAV); | ||
293 | |||
294 | printf("Success!\n"); | ||
295 | } | ||
296 | |||
297 | { /* Check Mute-Unmute etc */ | ||
298 | printf("\nTrying mute functionality...\n"); | ||
299 | |||
300 | |||
301 | memset(&AliceCC, 0, sizeof(CallControl)); | ||
302 | memset(&BobCC, 0, sizeof(CallControl)); | ||
303 | |||
304 | /* Assume sending audio and video */ | ||
305 | { | ||
306 | TOXAV_ERR_CALL rc; | ||
307 | toxav_call(AliceAV, 0, 48, 1000, &rc); | ||
308 | |||
309 | if (rc != TOXAV_ERR_CALL_OK) { | ||
310 | printf("toxav_call failed: %d\n", rc); | ||
311 | exit(1); | ||
312 | } | ||
313 | } | ||
314 | |||
315 | while (!BobCC.incoming) | ||
327 | iterate(Bsn, AliceAV, BobAV); | 316 | iterate(Bsn, AliceAV, BobAV); |
328 | 317 | ||
318 | /* At first try all stuff while in invalid state */ | ||
319 | assert(!toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_PAUSE, NULL)); | ||
320 | assert(!toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_RESUME, NULL)); | ||
321 | assert(!toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_MUTE_AUDIO, NULL)); | ||
322 | assert(!toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_MUTE_VIDEO, NULL)); | ||
323 | assert(!toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_UNMUTE_AUDIO, NULL)); | ||
324 | assert(!toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_UNMUTE_VIDEO, NULL)); | ||
325 | |||
326 | { | ||
327 | TOXAV_ERR_ANSWER rc; | ||
328 | toxav_answer(BobAV, 0, 48, 4000, &rc); | ||
329 | |||
330 | if (rc != TOXAV_ERR_ANSWER_OK) { | ||
331 | printf("toxav_answer failed: %d\n", rc); | ||
332 | exit(1); | ||
333 | } | ||
334 | } | ||
335 | |||
336 | iterate(Bsn, AliceAV, BobAV); | ||
337 | |||
338 | /* Pause and Resume */ | ||
339 | printf("Pause and Resume\n"); | ||
340 | assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_PAUSE, NULL)); | ||
341 | iterate(Bsn, AliceAV, BobAV); | ||
342 | assert(BobCC.state == TOXAV_CALL_STATE_PAUSED); | ||
343 | assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_RESUME, NULL)); | ||
344 | iterate(Bsn, AliceAV, BobAV); | ||
345 | assert(BobCC.state == TOXAV_CALL_STATE_SENDING_AV); | ||
346 | |||
347 | /* Mute/Unmute single */ | ||
348 | printf("Mute/Unmute single\n"); | ||
349 | assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_MUTE_AUDIO, NULL)); | ||
350 | iterate(Bsn, AliceAV, BobAV); | ||
351 | assert(BobCC.state == TOXAV_CALL_CONTROL_MUTE_AUDIO); | ||
352 | assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_UNMUTE_AUDIO, NULL)); | ||
353 | iterate(Bsn, AliceAV, BobAV); | ||
354 | assert(BobCC.state == TOXAV_CALL_CONTROL_UNMUTE_AUDIO); | ||
355 | |||
356 | /* Mute/Unmute both */ | ||
357 | printf("Mute/Unmute both\n"); | ||
358 | assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_MUTE_AUDIO, NULL)); | ||
359 | iterate(Bsn, AliceAV, BobAV); | ||
360 | assert(BobCC.state == TOXAV_CALL_STATE_SENDING_V); | ||
361 | assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_MUTE_VIDEO, NULL)); | ||
362 | iterate(Bsn, AliceAV, BobAV); | ||
363 | assert(BobCC.state == TOXAV_CALL_STATE_NOT_SENDING); | ||
364 | assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_UNMUTE_AUDIO, NULL)); | ||
365 | iterate(Bsn, AliceAV, BobAV); | ||
366 | assert(BobCC.state == TOXAV_CALL_STATE_SENDING_A); | ||
367 | assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_UNMUTE_VIDEO, NULL)); | ||
368 | iterate(Bsn, AliceAV, BobAV); | ||
369 | assert(BobCC.state == TOXAV_CALL_STATE_SENDING_AV); | ||
370 | |||
371 | { | ||
372 | TOXAV_ERR_CALL_CONTROL rc; | ||
373 | toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_CANCEL, &rc); | ||
374 | |||
375 | if (rc != TOXAV_ERR_CALL_CONTROL_OK) { | ||
376 | printf("toxav_call_control failed: %d\n", rc); | ||
377 | exit(1); | ||
378 | } | ||
379 | } | ||
380 | |||
381 | iterate(Bsn, AliceAV, BobAV); | ||
382 | assert(BobCC.state == TOXAV_CALL_STATE_END); | ||
383 | |||
329 | printf("Success!\n"); | 384 | printf("Success!\n"); |
330 | } | 385 | } |
331 | 386 | ||
diff --git a/toxav/msi.h b/toxav/msi.h index 783d3928..b846542d 100644 --- a/toxav/msi.h +++ b/toxav/msi.h | |||
@@ -41,8 +41,8 @@ typedef enum { | |||
41 | msi_InvalidState, | 41 | msi_InvalidState, |
42 | msi_StrayMessage, | 42 | msi_StrayMessage, |
43 | msi_SystemError, | 43 | msi_SystemError, |
44 | msi_ErrUndisclosed, | ||
45 | msi_HandleError, | 44 | msi_HandleError, |
45 | msi_ErrUndisclosed, /* NOTE: must be last enum otherwise parsing wont work */ | ||
46 | } MSIError; | 46 | } MSIError; |
47 | 47 | ||
48 | /** | 48 | /** |
diff --git a/toxav/toxav.c b/toxav/toxav.c index 5054d399..e6b51ee4 100644 --- a/toxav/toxav.c +++ b/toxav/toxav.c | |||
@@ -235,6 +235,8 @@ bool toxav_call(ToxAV* av, uint32_t friend_number, uint32_t audio_bit_rate, uint | |||
235 | return false; | 235 | return false; |
236 | } | 236 | } |
237 | 237 | ||
238 | call->msi_call->av_call = call; | ||
239 | |||
238 | return true; | 240 | return true; |
239 | } | 241 | } |
240 | 242 | ||
@@ -310,12 +312,22 @@ bool toxav_call_control(ToxAV* av, uint32_t friend_number, TOXAV_CALL_CONTROL co | |||
310 | switch (control) | 312 | switch (control) |
311 | { | 313 | { |
312 | case TOXAV_CALL_CONTROL_RESUME: { | 314 | case TOXAV_CALL_CONTROL_RESUME: { |
313 | if (call->msi_call->self_capabilities == 0 && | 315 | if (!call->active) { |
316 | rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL; | ||
317 | goto END; | ||
318 | } | ||
319 | |||
320 | /* Only act if paused and had media transfer active before */ | ||
321 | if (call->msi_call->self_capabilities == 0 && | ||
314 | call->last_capabilities ) { | 322 | call->last_capabilities ) { |
315 | /* Only act if paused and had media transfer active before */ | ||
316 | 323 | ||
317 | if (msi_change_capabilities(call->msi_call, call->last_capabilities) == -1) | 324 | if (msi_change_capabilities(call->msi_call, |
318 | return false; | 325 | call->last_capabilities) == -1) { |
326 | /* The only reason for this function to fail is invalid state | ||
327 | * ( not active ) */ | ||
328 | rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL; | ||
329 | goto END; | ||
330 | } | ||
319 | 331 | ||
320 | rtp_start_receiving(call->rtps[audio_index]); | 332 | rtp_start_receiving(call->rtps[audio_index]); |
321 | rtp_start_receiving(call->rtps[video_index]); | 333 | rtp_start_receiving(call->rtps[video_index]); |
@@ -323,13 +335,21 @@ bool toxav_call_control(ToxAV* av, uint32_t friend_number, TOXAV_CALL_CONTROL co | |||
323 | } break; | 335 | } break; |
324 | 336 | ||
325 | case TOXAV_CALL_CONTROL_PAUSE: { | 337 | case TOXAV_CALL_CONTROL_PAUSE: { |
338 | if (!call->active) { | ||
339 | rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL; | ||
340 | goto END; | ||
341 | } | ||
342 | |||
343 | /* Only act if not already paused */ | ||
326 | if (call->msi_call->self_capabilities) { | 344 | if (call->msi_call->self_capabilities) { |
327 | /* Only act if not already paused */ | ||
328 | |||
329 | call->last_capabilities = call->msi_call->self_capabilities; | 345 | call->last_capabilities = call->msi_call->self_capabilities; |
330 | 346 | ||
331 | if (msi_change_capabilities(call->msi_call, 0) == -1 ) | 347 | if (msi_change_capabilities(call->msi_call, 0) == -1 ) { |
332 | return false; | 348 | /* The only reason for this function to fail is invalid state |
349 | * ( not active ) */ | ||
350 | rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL; | ||
351 | goto END; | ||
352 | } | ||
333 | 353 | ||
334 | rtp_stop_receiving(call->rtps[audio_index]); | 354 | rtp_stop_receiving(call->rtps[audio_index]); |
335 | rtp_stop_receiving(call->rtps[video_index]); | 355 | rtp_stop_receiving(call->rtps[video_index]); |
@@ -341,26 +361,84 @@ bool toxav_call_control(ToxAV* av, uint32_t friend_number, TOXAV_CALL_CONTROL co | |||
341 | msi_hangup(call->msi_call); | 361 | msi_hangup(call->msi_call); |
342 | 362 | ||
343 | /* No mather the case, terminate the call */ | 363 | /* No mather the case, terminate the call */ |
364 | call_kill_transmission(call); | ||
344 | call_remove(call); | 365 | call_remove(call); |
345 | } break; | 366 | } break; |
346 | 367 | ||
347 | case TOXAV_CALL_CONTROL_MUTE_AUDIO: { | 368 | case TOXAV_CALL_CONTROL_MUTE_AUDIO: { |
348 | if (call->msi_call->self_capabilities & msi_CapRAudio || | 369 | if (!call->active) { |
349 | call->msi_call->self_capabilities & msi_CapSAudio) { | 370 | rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL; |
350 | 371 | goto END; | |
351 | uint8_t capabilities = call->msi_call->self_capabilities; | 372 | } |
352 | capabilities ^= msi_CapRAudio; | 373 | |
353 | capabilities ^= msi_CapRAudio; | 374 | if (call->msi_call->self_capabilities & msi_CapRAudio) { |
354 | 375 | if (msi_change_capabilities(call->msi_call, call-> | |
355 | if (msi_change_capabilities(call->msi_call, call->msi_call->self_capabilities) == -1) | 376 | msi_call->self_capabilities ^ msi_CapRAudio) == -1) { |
356 | return false; | 377 | /* The only reason for this function to fail is invalid state |
378 | * ( not active ) */ | ||
379 | rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL; | ||
380 | goto END; | ||
381 | } | ||
357 | 382 | ||
358 | rtp_stop_receiving(call->rtps[audio_index]); | 383 | rtp_stop_receiving(call->rtps[audio_index]); |
359 | } | 384 | } |
360 | } break; | 385 | } break; |
361 | 386 | ||
362 | case TOXAV_CALL_CONTROL_MUTE_VIDEO: { | 387 | case TOXAV_CALL_CONTROL_MUTE_VIDEO: { |
388 | if (!call->active) { | ||
389 | rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL; | ||
390 | goto END; | ||
391 | } | ||
392 | |||
393 | if (call->msi_call->self_capabilities & msi_CapRVideo) { | ||
394 | if (msi_change_capabilities(call->msi_call, call-> | ||
395 | msi_call->self_capabilities ^ msi_CapRVideo) == -1) { | ||
396 | /* The only reason for this function to fail is invalid state | ||
397 | * ( not active ) */ | ||
398 | rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL; | ||
399 | goto END; | ||
400 | } | ||
401 | |||
402 | rtp_stop_receiving(call->rtps[video_index]); | ||
403 | } | ||
404 | } break; | ||
405 | |||
406 | case TOXAV_CALL_CONTROL_UNMUTE_AUDIO: { | ||
407 | if (!call->active) { | ||
408 | rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL; | ||
409 | goto END; | ||
410 | } | ||
411 | |||
412 | if (call->msi_call->self_capabilities & ~msi_CapRAudio) { | ||
413 | if (msi_change_capabilities(call->msi_call, call-> | ||
414 | msi_call->self_capabilities | msi_CapRAudio) == -1) { | ||
415 | /* The only reason for this function to fail is invalid state | ||
416 | * ( not active ) */ | ||
417 | rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL; | ||
418 | goto END; | ||
419 | } | ||
420 | |||
421 | rtp_start_receiving(call->rtps[audio_index]); | ||
422 | } | ||
423 | } break; | ||
424 | |||
425 | case TOXAV_CALL_CONTROL_UNMUTE_VIDEO: { | ||
426 | if (!call->active) { | ||
427 | rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL; | ||
428 | goto END; | ||
429 | } | ||
363 | 430 | ||
431 | if (call->msi_call->self_capabilities & ~msi_CapRVideo) { | ||
432 | if (msi_change_capabilities(call->msi_call, call-> | ||
433 | msi_call->self_capabilities | msi_CapRVideo) == -1) { | ||
434 | /* The only reason for this function to fail is invalid state | ||
435 | * ( not active ) */ | ||
436 | rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL; | ||
437 | goto END; | ||
438 | } | ||
439 | |||
440 | rtp_start_receiving(call->rtps[video_index]); | ||
441 | } | ||
364 | } break; | 442 | } break; |
365 | } | 443 | } |
366 | 444 | ||
@@ -558,8 +636,6 @@ void toxav_callback_receive_audio_frame(ToxAV* av, toxav_receive_audio_frame_cb* | |||
558 | * :: Internal | 636 | * :: Internal |
559 | * | 637 | * |
560 | ******************************************************************************/ | 638 | ******************************************************************************/ |
561 | /** TODO: | ||
562 | */ | ||
563 | int callback_invite(void* toxav_inst, MSICall* call) | 639 | int callback_invite(void* toxav_inst, MSICall* call) |
564 | { | 640 | { |
565 | ToxAV* toxav = toxav_inst; | 641 | ToxAV* toxav = toxav_inst; |
@@ -586,15 +662,20 @@ int callback_start(void* toxav_inst, MSICall* call) | |||
586 | 662 | ||
587 | ToxAVCall* av_call = call_get(toxav, call->friend_id); | 663 | ToxAVCall* av_call = call_get(toxav, call->friend_id); |
588 | 664 | ||
589 | if (av_call == NULL || !call_prepare_transmission(av_call)) { | 665 | if (av_call == NULL) { |
590 | call_remove(av_call); | 666 | /* Should this ever happen? */ |
591 | return -1; | 667 | return -1; |
592 | } | 668 | } |
593 | 669 | ||
594 | TOXAV_CALL_STATE state = capabilities_to_state(av_call->msi_call->peer_capabilities); | 670 | if (!call_prepare_transmission(av_call)) { |
671 | callback_error(toxav_inst, call); | ||
672 | call_remove(av_call); | ||
673 | return -1; | ||
674 | } | ||
595 | 675 | ||
596 | if (toxav->scb.first) | 676 | if (toxav->scb.first) |
597 | toxav->scb.first(toxav, call->friend_id, state, toxav->scb.second); | 677 | toxav->scb.first(toxav, call->friend_id, |
678 | capabilities_to_state(call->peer_capabilities), toxav->scb.second); | ||
598 | 679 | ||
599 | return 0; | 680 | return 0; |
600 | } | 681 | } |
@@ -603,18 +684,19 @@ int callback_end(void* toxav_inst, MSICall* call) | |||
603 | { | 684 | { |
604 | ToxAV* toxav = toxav_inst; | 685 | ToxAV* toxav = toxav_inst; |
605 | 686 | ||
606 | call_kill_transmission(call->av_call); | ||
607 | call_remove(call->av_call); | ||
608 | |||
609 | if (toxav->scb.first) | 687 | if (toxav->scb.first) |
610 | toxav->scb.first(toxav, call->friend_id, TOXAV_CALL_STATE_END, toxav->scb.second); | 688 | toxav->scb.first(toxav, call->friend_id, TOXAV_CALL_STATE_END, toxav->scb.second); |
611 | 689 | ||
690 | call_kill_transmission(call->av_call); | ||
691 | call_remove(call->av_call); | ||
692 | |||
612 | return 0; | 693 | return 0; |
613 | } | 694 | } |
614 | 695 | ||
615 | int callback_error(void* toxav_inst, MSICall* call) | 696 | int callback_error(void* toxav_inst, MSICall* call) |
616 | { | 697 | { |
617 | ToxAV* toxav = toxav_inst; | 698 | ToxAV* toxav = toxav_inst; |
699 | |||
618 | if (toxav->scb.first) | 700 | if (toxav->scb.first) |
619 | toxav->scb.first(toxav, call->friend_id, TOXAV_CALL_STATE_ERROR, toxav->scb.second); | 701 | toxav->scb.first(toxav, call->friend_id, TOXAV_CALL_STATE_ERROR, toxav->scb.second); |
620 | 702 | ||
@@ -633,14 +715,16 @@ int callback_capabilites(void* toxav_inst, MSICall* call) | |||
633 | 715 | ||
634 | TOXAV_CALL_STATE capabilities_to_state(uint8_t capabilities) | 716 | TOXAV_CALL_STATE capabilities_to_state(uint8_t capabilities) |
635 | { | 717 | { |
636 | if ((capabilities & msi_CapSAudio) && (capabilities & msi_CapSVideo)) | 718 | if (capabilities == 0) |
719 | return TOXAV_CALL_STATE_PAUSED; | ||
720 | else if ((capabilities & msi_CapSAudio) && (capabilities & msi_CapSVideo)) | ||
637 | return TOXAV_CALL_STATE_SENDING_AV; | 721 | return TOXAV_CALL_STATE_SENDING_AV; |
638 | else if (capabilities & msi_CapSAudio) | 722 | else if (capabilities & msi_CapSAudio) |
639 | return TOXAV_CALL_STATE_SENDING_A; | 723 | return TOXAV_CALL_STATE_SENDING_A; |
640 | else if (capabilities & msi_CapSVideo) | 724 | else if (capabilities & msi_CapSVideo) |
641 | return TOXAV_CALL_STATE_SENDING_V; | 725 | return TOXAV_CALL_STATE_SENDING_V; |
642 | else | 726 | |
643 | return TOXAV_CALL_STATE_PAUSED; | 727 | return TOXAV_CALL_STATE_NOT_SENDING; |
644 | } | 728 | } |
645 | 729 | ||
646 | bool audio_bitrate_invalid(uint32_t bitrate) | 730 | bool audio_bitrate_invalid(uint32_t bitrate) |
@@ -798,8 +882,6 @@ bool call_prepare_transmission(ToxAVCall* call) | |||
798 | goto MUTEX_INIT_ERROR; | 882 | goto MUTEX_INIT_ERROR; |
799 | } | 883 | } |
800 | 884 | ||
801 | uint8_t capabilities = call->msi_call->self_capabilities; | ||
802 | |||
803 | call->cs = cs_new(call->msi_call->peer_vfpsz); | 885 | call->cs = cs_new(call->msi_call->peer_vfpsz); |
804 | 886 | ||
805 | if ( !call->cs ) { | 887 | if ( !call->cs ) { |
@@ -813,8 +895,7 @@ bool call_prepare_transmission(ToxAVCall* call) | |||
813 | memcpy(&call->cs->acb, &av->acb, sizeof(av->acb)); | 895 | memcpy(&call->cs->acb, &av->acb, sizeof(av->acb)); |
814 | memcpy(&call->cs->vcb, &av->vcb, sizeof(av->vcb)); | 896 | memcpy(&call->cs->vcb, &av->vcb, sizeof(av->vcb)); |
815 | 897 | ||
816 | if (capabilities & msi_CapSAudio || capabilities & msi_CapRAudio) { /* Prepare audio sending */ | 898 | { /* Prepare audio */ |
817 | |||
818 | call->rtps[audio_index] = rtp_new(rtp_TypeAudio, av->m, call->friend_id); | 899 | call->rtps[audio_index] = rtp_new(rtp_TypeAudio, av->m, call->friend_id); |
819 | 900 | ||
820 | if ( !call->rtps[audio_index] ) { | 901 | if ( !call->rtps[audio_index] ) { |
@@ -824,22 +905,21 @@ bool call_prepare_transmission(ToxAVCall* call) | |||
824 | 905 | ||
825 | call->rtps[audio_index]->cs = call->cs; | 906 | call->rtps[audio_index]->cs = call->cs; |
826 | 907 | ||
827 | if (cs_enable_audio_sending(call->cs, call->s_audio_b, 2) != 0) { | 908 | /* Only enable sending if bitrate is defined */ |
909 | if (call->s_audio_b > 0 && cs_enable_audio_sending(call->cs, call->s_audio_b, 2) != 0) { | ||
828 | LOGGER_WARNING("Failed to enable audio sending!"); | 910 | LOGGER_WARNING("Failed to enable audio sending!"); |
829 | goto FAILURE; | 911 | goto FAILURE; |
830 | } | 912 | } |
831 | 913 | ||
832 | if (capabilities & msi_CapRAudio) { | 914 | if (cs_enable_audio_receiving(call->cs) != 0) { |
833 | if (cs_enable_audio_receiving(call->cs) != 0) { | 915 | LOGGER_WARNING("Failed to enable audio receiving!"); |
834 | LOGGER_WARNING("Failed to enable audio receiving!"); | 916 | goto FAILURE; |
835 | goto FAILURE; | ||
836 | } | ||
837 | |||
838 | rtp_start_receiving(call->rtps[audio_index]); | ||
839 | } | 917 | } |
918 | |||
919 | rtp_start_receiving(call->rtps[audio_index]); | ||
840 | } | 920 | } |
841 | 921 | ||
842 | if (capabilities & msi_CapSVideo || capabilities & msi_CapRVideo) { /* Prepare video rtp */ | 922 | { /* Prepare video */ |
843 | call->rtps[video_index] = rtp_new(rtp_TypeVideo, av->m, call->friend_id); | 923 | call->rtps[video_index] = rtp_new(rtp_TypeVideo, av->m, call->friend_id); |
844 | 924 | ||
845 | if ( !call->rtps[video_index] ) { | 925 | if ( !call->rtps[video_index] ) { |
@@ -849,26 +929,26 @@ bool call_prepare_transmission(ToxAVCall* call) | |||
849 | 929 | ||
850 | call->rtps[video_index]->cs = call->cs; | 930 | call->rtps[video_index]->cs = call->cs; |
851 | 931 | ||
852 | if (cs_enable_video_sending(call->cs, call->s_video_b) != 0) { | 932 | /* Only enable sending if bitrate is defined */ |
933 | if (call->s_video_b > 0 && cs_enable_video_sending(call->cs, call->s_video_b) != 0) { | ||
853 | LOGGER_WARNING("Failed to enable video sending!"); | 934 | LOGGER_WARNING("Failed to enable video sending!"); |
854 | goto FAILURE; | 935 | goto FAILURE; |
855 | } | 936 | } |
856 | 937 | ||
857 | if (capabilities & msi_CapRVideo) { | 938 | |
858 | if (cs_enable_video_receiving(call->cs) != 0) { | 939 | if (cs_enable_video_receiving(call->cs) != 0) { |
859 | LOGGER_WARNING("Failed to enable video receiving!"); | 940 | LOGGER_WARNING("Failed to enable video receiving!"); |
860 | goto FAILURE; | 941 | goto FAILURE; |
861 | } | ||
862 | |||
863 | rtp_start_receiving(call->rtps[audio_index]); | ||
864 | } | 942 | } |
943 | |||
944 | rtp_start_receiving(call->rtps[audio_index]); | ||
865 | } | 945 | } |
866 | 946 | ||
867 | call->active = 1; | 947 | call->active = 1; |
868 | pthread_mutex_unlock(call->mutex_control); | 948 | pthread_mutex_unlock(call->mutex_control); |
869 | return true; | 949 | return true; |
870 | 950 | ||
871 | FAILURE: | 951 | FAILURE: |
872 | rtp_kill(call->rtps[audio_index]); | 952 | rtp_kill(call->rtps[audio_index]); |
873 | call->rtps[audio_index] = NULL; | 953 | call->rtps[audio_index] = NULL; |
874 | rtp_kill(call->rtps[video_index]); | 954 | rtp_kill(call->rtps[video_index]); |
@@ -883,7 +963,7 @@ bool call_prepare_transmission(ToxAVCall* call) | |||
883 | pthread_mutex_unlock(call->mutex_control); | 963 | pthread_mutex_unlock(call->mutex_control); |
884 | return false; | 964 | return false; |
885 | 965 | ||
886 | MUTEX_INIT_ERROR: | 966 | MUTEX_INIT_ERROR: |
887 | pthread_mutex_unlock(call->mutex_control); | 967 | pthread_mutex_unlock(call->mutex_control); |
888 | LOGGER_ERROR("Mutex initialization failed!\n"); | 968 | LOGGER_ERROR("Mutex initialization failed!\n"); |
889 | return false; | 969 | return false; |
diff --git a/toxav/toxav.h b/toxav/toxav.h index 5e82faa6..ec232ddd 100644 --- a/toxav/toxav.h +++ b/toxav/toxav.h | |||
@@ -246,7 +246,7 @@ void toxav_callback_call_state(ToxAV *av, toxav_call_state_cb *function, void *u | |||
246 | typedef enum TOXAV_CALL_CONTROL { | 246 | typedef enum TOXAV_CALL_CONTROL { |
247 | /** | 247 | /** |
248 | * Resume a previously paused call. Only valid if the pause was caused by this | 248 | * Resume a previously paused call. Only valid if the pause was caused by this |
249 | * client. Not valid before the call is accepted. | 249 | * client, if not, this control is ignored. Not valid before the call is accepted. |
250 | */ | 250 | */ |
251 | TOXAV_CALL_CONTROL_RESUME, | 251 | TOXAV_CALL_CONTROL_RESUME, |
252 | /** | 252 | /** |
@@ -269,7 +269,19 @@ typedef enum TOXAV_CALL_CONTROL { | |||
269 | * compliance, this will cause the `receive_video_frame` event to stop being | 269 | * compliance, this will cause the `receive_video_frame` event to stop being |
270 | * triggered on receiving an video frame from the friend. | 270 | * triggered on receiving an video frame from the friend. |
271 | */ | 271 | */ |
272 | TOXAV_CALL_CONTROL_MUTE_VIDEO | 272 | TOXAV_CALL_CONTROL_MUTE_VIDEO, |
273 | /** | ||
274 | * Notify the friend that we are AGAIN ready to handle incoming audio. | ||
275 | * This control will not work if the call is not started with audio | ||
276 | * initiated. | ||
277 | */ | ||
278 | TOXAV_CALL_CONTROL_UNMUTE_AUDIO, | ||
279 | /** | ||
280 | * Notify the friend that we are AGAIN ready to handle incoming video. | ||
281 | * This control will not work if the call is not started with video | ||
282 | * initiated. | ||
283 | */ | ||
284 | TOXAV_CALL_CONTROL_UNMUTE_VIDEO | ||
273 | } TOXAV_CALL_CONTROL; | 285 | } TOXAV_CALL_CONTROL; |
274 | typedef enum TOXAV_ERR_CALL_CONTROL { | 286 | typedef enum TOXAV_ERR_CALL_CONTROL { |
275 | TOXAV_ERR_CALL_CONTROL_OK, | 287 | TOXAV_ERR_CALL_CONTROL_OK, |
@@ -296,7 +308,11 @@ typedef enum TOXAV_ERR_CALL_CONTROL { | |||
296 | * other party paused the call. The call will resume after both parties sent | 308 | * other party paused the call. The call will resume after both parties sent |
297 | * the RESUME control. | 309 | * the RESUME control. |
298 | */ | 310 | */ |
299 | TOXAV_ERR_CALL_CONTROL_ALREADY_PAUSED | 311 | TOXAV_ERR_CALL_CONTROL_ALREADY_PAUSED, |
312 | /** | ||
313 | * Tried to unmute a call that was not already muted. | ||
314 | */ | ||
315 | TOXAV_ERR_CALL_CONTROL_NOT_MUTED | ||
300 | } TOXAV_ERR_CALL_CONTROL; | 316 | } TOXAV_ERR_CALL_CONTROL; |
301 | /** | 317 | /** |
302 | * Sends a call control command to a friend. | 318 | * Sends a call control command to a friend. |