diff --git a/coreapi/chat.c b/coreapi/chat.c index e8f1ed061..af0db2c99 100644 --- a/coreapi/chat.c +++ b/coreapi/chat.c @@ -310,9 +310,15 @@ void linphone_chat_room_set_user_data(LinphoneChatRoom *cr, void *ud) { void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg) { /*stubed rtt text*/ if (cr->call && linphone_call_params_realtime_text_enabled(linphone_call_get_current_params(cr->call))) { - char crlf[4]="CRLF"; - linphone_chat_message_put_char(msg,*(uint32_t*)crlf); /*CRLF*/ + char crlf[4] = "CRLF"; + linphone_chat_message_put_char(msg, *(uint32_t*)crlf); /*CRLF*/ linphone_chat_message_set_state(msg, LinphoneChatMessageStateDelivered); + + if (cr->is_composing == LinphoneIsComposingActive) { + cr->is_composing = LinphoneIsComposingIdle; + } + linphone_chat_room_delete_composing_idle_timer(cr); + linphone_chat_room_delete_composing_refresh_timer(cr); return; } linphone_chat_message_set_state(msg, LinphoneChatMessageStateInProgress); @@ -649,51 +655,6 @@ void linphone_core_is_composing_received(LinphoneCore *lc, SalOp *op, const SalI LinphoneAddress *addr = linphone_address_new(is_composing->from); LinphoneChatRoom *cr = _linphone_core_get_chat_room(lc, addr); if (cr != NULL) { - /*rtt stub*/ - LinphoneCall *call = linphone_core_find_call_from_uri(lc,cr->peer); - if (call && linphone_call_params_realtime_text_enabled(linphone_call_get_current_params(call))) { - const char * rtt; - if (cr->call == NULL) { - /*attach cr to call*/ - cr->call = call; - linphone_call_ref(cr->call); - } - if (cr->pending_message == NULL) { - cr->pending_message = linphone_chat_room_create_message(cr,""); - } - - rtt = sal_custom_header_find(sal_op_get_recv_custom_header(op),"X-RTT"); - if (rtt) { - if (strcmp(rtt,"CRLF")==0) { - LinphoneChatMessage *msg = cr->pending_message; - /*forge a message*/ - linphone_chat_message_set_from(msg, cr->peer_url); - - { - LinphoneAddress *to; - to=sal_op_get_to(op) ? linphone_address_new(sal_op_get_to(op)) : linphone_address_new(linphone_core_get_identity(lc)); - msg->to=to; - } - - msg->time=ms_time(0); - msg->state=LinphoneChatMessageStateDelivered; - msg->is_read=FALSE; - msg->dir=LinphoneChatMessageIncoming; - msg->storage_id=linphone_chat_message_store(msg); - - if(cr->unread_count < 0) cr->unread_count = 1; - else cr->unread_count++; - - linphone_chat_room_message_received(cr,lc,msg); - linphone_chat_message_unref(msg); - cr->pending_message=NULL; - } else if (strcmp(rtt,"S P")==0) { - cr->pending_message->message=ms_strcat_printf(cr->pending_message->message," "); - } else { - cr->pending_message->message=ms_strcat_printf(cr->pending_message->message,rtt); - } - } - } linphone_chat_room_notify_is_composing(cr, is_composing->text); } linphone_address_destroy(addr); @@ -840,7 +801,52 @@ static void linphone_chat_room_send_is_composing_notification(LinphoneChatRoom * } } +void linphone_core_real_time_text_received(LinphoneCore *lc, LinphoneChatRoom *cr, uint32_t character, LinphoneCall *call) { + char *value = NULL; + + if (call && linphone_call_params_realtime_text_enabled(linphone_call_get_current_params(call))) { + if (cr->call == NULL) { + /*attach cr to call*/ + cr->call = call; + linphone_call_ref(cr->call); + } + if (cr->pending_message == NULL) { + cr->pending_message = linphone_chat_room_create_message(cr, ""); + } + + value = ms_strdup_printf("%c%c%c%c",((char*)&character)[0],((char*)&character)[1],((char*)&character)[2],((char*)&character)[3]); + ms_message("Received RTT character: %s (%lu)", value, (unsigned long)character); + if (strcmp(value, "CRLF") == 0) { + // End of message + LinphoneChatMessage *msg = cr->pending_message; + ms_message("CRLF received, forge a message with content %s", cr->pending_message->message); + + linphone_chat_message_set_from(msg, cr->peer_url); + linphone_chat_message_set_to(msg, linphone_address_new(linphone_core_get_identity(lc))); + msg->time = ms_time(0); + msg->state = LinphoneChatMessageStateDelivered; + msg->is_read = FALSE; + msg->dir = LinphoneChatMessageIncoming; + msg->storage_id = linphone_chat_message_store(msg); + + if (cr->unread_count < 0) cr->unread_count = 1; + else cr->unread_count++; + + linphone_chat_room_message_received(cr, lc, msg); + linphone_chat_message_unref(msg); + cr->pending_message = NULL; + } else { + cr->pending_message->message = ms_strcat_printf(cr->pending_message->message, value); + ms_message("Received text since beginning of RTT session or last CRLF is %s", cr->pending_message->message); + } + ms_free(value); + } +} + uint32_t linphone_chat_room_get_char(const LinphoneChatRoom *cr) { + if (cr->pending_message && strlen(cr->pending_message->message) > 0) { + return cr->pending_message->message[strlen(cr->pending_message->message)-1]; + } return 0; } @@ -853,7 +859,7 @@ int linphone_chat_message_put_char(LinphoneChatMessage *msg, uint32_t charater) } text_stream_putchar32(call->textstream, charater); - + linphone_chat_room_compose(cr); return 0; } static int linphone_chat_room_stop_composing(void *data, unsigned int revents) { diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 52d0e85c3..15e897651 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -375,8 +375,9 @@ static MSList *make_codec_list(LinphoneCore *lc, CodecConstraints * hints, SalSt PayloadType *pt=(PayloadType*)it->data; int num; - if (!(pt->flags & PAYLOAD_TYPE_ENABLED)) + if (!payload_type_enabled(pt)) { continue; + } if (hints->bandwidth_limit>0 && !linphone_core_is_payload_type_usable_for_bandwidth(lc,pt,hints->bandwidth_limit)){ ms_message("Codec %s/%i eliminated because of audio bandwidth constraint of %i kbit/s", pt->mime_type,pt->clock_rate,hints->bandwidth_limit); @@ -1410,6 +1411,9 @@ void linphone_call_fix_call_parameters(LinphoneCall *call, SalMediaDescription * ms_message("Call [%p]: re-enabling video in our call params because the remote wants it and the policy allows to automatically accept.", call); call->params->has_video = TRUE; } + if (rcp->realtimetext_enabled && !call->params->realtimetext_enabled) { + call->params->realtimetext_enabled = TRUE; + } } } @@ -1762,6 +1766,7 @@ const LinphoneCallParams * linphone_call_get_remote_params(LinphoneCall *call){ for (i = 0; i < nb_text_streams; i++) { sd = sal_media_description_get_active_stream_of_type(md, SalText, i); if (sal_stream_description_has_srtp(sd) == TRUE) cp->media_encryption = LinphoneMediaEncryptionSRTP; + cp->realtimetext_enabled = TRUE; } if (!cp->has_video){ if (md->bandwidth>0 && md->bandwidth<=linphone_core_get_edge_bw(call->core)){ @@ -4242,7 +4247,8 @@ void linphone_call_handle_stream_events(LinphoneCall *call, int stream_index){ } else if (evt==ORTP_EVENT_TELEPHONE_EVENT){ linphone_core_dtmf_received(call,evd->info.telephone_event); } else if (evt == ORTP_EVENT_RTT_CHARACTER_RECEIVED) { - //TODO + LinphoneChatRoom * chat_room = linphone_core_get_chat_room(call->core, linphone_call_get_remote_address(call)); + linphone_core_real_time_text_received(call->core, chat_room, evd->info.received_rtt_character, call); } ortp_event_destroy(ev); } diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 4b11d7dac..e25e171f3 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -1117,6 +1117,8 @@ static PayloadType* find_payload_type_from_list(const char* type, int rate, int static bool_t linphone_core_codec_supported(LinphoneCore *lc, SalStreamType type, const char *mime){ if (type == SalVideo && lp_config_get_int(lc->config, "video", "rtp_io", FALSE)){ return TRUE; /*in rtp io mode, we don't transcode video, thus we can support a format for which we have no encoder nor decoder.*/ + } else if (type == SalText) { + return TRUE; } return ms_filter_codec_supported(mime); } @@ -1420,7 +1422,7 @@ const char * linphone_core_get_version(void){ } static void linphone_core_register_payload_type(LinphoneCore *lc, const PayloadType *const_pt, const char *recv_fmtp, bool_t enabled){ - MSList **codec_list=const_pt->type==PAYLOAD_VIDEO ? &lc->default_video_codecs : &lc->default_audio_codecs; + MSList **codec_list = const_pt->type==PAYLOAD_VIDEO ? &lc->default_video_codecs : const_pt->type==PAYLOAD_TEXT ? &lc->default_text_codecs : &lc->default_audio_codecs; if (linphone_core_codec_supported(lc, (const_pt->type == PAYLOAD_VIDEO) ? SalVideo : const_pt->type == PAYLOAD_TEXT ? SalText : SalAudio, const_pt->mime_type)){ PayloadType *pt=payload_type_clone(const_pt); int number=-1; @@ -1553,6 +1555,8 @@ static void linphone_core_register_default_codecs(LinphoneCore *lc){ linphone_core_register_payload_type(lc,&payload_type_speex_nb,"vbr=on",TRUE); linphone_core_register_payload_type(lc,&payload_type_pcmu8000,NULL,TRUE); linphone_core_register_payload_type(lc,&payload_type_pcma8000,NULL,TRUE); + linphone_core_register_payload_type(lc,&payload_type_t140,NULL,TRUE); + linphone_core_register_payload_type(lc,&payload_type_t140_red,NULL,TRUE); /*other audio codecs, not enabled by default, in order of preference*/ linphone_core_register_payload_type(lc,&payload_type_gsm,NULL,FALSE); @@ -1591,9 +1595,6 @@ static void linphone_core_register_default_codecs(LinphoneCore *lc){ linphone_core_register_payload_type(lc,&payload_type_aal2_g726_40,NULL,FALSE); linphone_core_register_payload_type(lc,&payload_type_codec2,NULL,FALSE); - linphone_core_register_payload_type(lc,&payload_type_t140,NULL,TRUE); - linphone_core_register_payload_type(lc,&payload_type_t140_red,NULL,TRUE); - #ifdef VIDEO_ENABLED /*default enabled video codecs, in order of preference*/ diff --git a/coreapi/misc.c b/coreapi/misc.c index 628e1bf19..5381d093e 100644 --- a/coreapi/misc.c +++ b/coreapi/misc.c @@ -242,6 +242,9 @@ bool_t linphone_core_is_payload_type_usable_for_bandwidth(LinphoneCore *lc, cons } else ret=FALSE; break; + case PAYLOAD_TEXT: + ret=TRUE; + break; } return ret; } diff --git a/coreapi/private.h b/coreapi/private.h index 6f4780375..51d52f16e 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -458,6 +458,7 @@ void linphone_proxy_config_write_to_config_file(struct _LpConfig* config,Linphon void linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessage *msg); void linphone_core_is_composing_received(LinphoneCore *lc, SalOp *op, const SalIsComposing *is_composing); +void linphone_core_real_time_text_received(LinphoneCore *lc, LinphoneChatRoom *cr, uint32_t character, LinphoneCall *call); void linphone_call_init_stats(LinphoneCallStats *stats, int type); void linphone_call_fix_call_parameters(LinphoneCall *call, SalMediaDescription *rmd); diff --git a/oRTP b/oRTP index f7d3955db..9e7f98c8b 160000 --- a/oRTP +++ b/oRTP @@ -1 +1 @@ -Subproject commit f7d3955db17d06c02b7afb806a9c5082e29c429f +Subproject commit 9e7f98c8bd5c3be1a1f67215bb90e84c6ab3c196 diff --git a/tester/message_tester.c b/tester/message_tester.c index 1ceca40b1..6649e4cd4 100644 --- a/tester/message_tester.c +++ b/tester/message_tester.c @@ -1334,14 +1334,15 @@ static void real_time_text_message(void) { BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,1)); { LinphoneChatMessage * msg = marie->stat.last_received_chat_message; - BC_ASSERT_PTR_NOT_NULL(linphone_core_get_chat_room(marie->lc,pauline->identity)); BC_ASSERT_PTR_NOT_NULL(msg); if (msg) { BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(msg),"BLA BLA"); } } + linphone_chat_message_destroy(rtt_message); } end_call(marie, pauline); + linphone_call_params_destroy(marie_params); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); }