Linphone callState 电话状态的监听状态(二)

来源:互联网 发布:高校教学软件租赁 编辑:程序博客网 时间:2024/06/06 01:04

Linphone callState 电话状态的监听状态

callState是一个观察者模式

接着上一篇的说, 这篇主要是涉及到linphone中c层的注册监听机制. 主要是代码追踪和代码过程.

linphonecore_jni.cc中的添加监听事件的方法

linphonecore_jni.cc中extern "C" void Java_org_linphone_core_LinphoneCoreImpl_addListener(JNIEnv* env, jobject thiz, jlong lc, jobject jlistener) {    LinphoneJavaBindings *ljb = (LinphoneJavaBindings *) linphone_core_get_user_data((LinphoneCore *)lc);    LinphoneCoreVTable *vTable = linphone_core_v_table_new();    LinphoneCoreData* ldata = new LinphoneCoreData(env, thiz, vTable, jlistener, ljb);    linphone_core_v_table_set_user_data(vTable, ldata);    linphone_core_add_listener((LinphoneCore*)lc, vTable);}

LinphoneJavaBindings的代码及使用方法

说明

这个类绑定的是java类, 确定的是进行回调的监听机制.就是从c层回调至java层.
实现了LinphoneCoreListener中所有的方法.

代码

绑定了各种java的方法, 用于回调吧class LinphoneJavaBindings {public:    LinphoneJavaBindings(JNIEnv *env) {        listenerClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCoreListener"));        authMethodClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCore$AuthMethod"));        authMethodFromIntId = env->GetStaticMethodID(authMethodClass,"fromInt","(I)Lorg/linphone/core/LinphoneCore$AuthMethod;");        /*displayStatus(LinphoneCore lc,String message);*/        displayStatusId = env->GetMethodID(listenerClass,"displayStatus","(Lorg/linphone/core/LinphoneCore;Ljava/lang/String;)V");        /*void generalState(LinphoneCore lc,int state); */        globalStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCore$GlobalState"));        globalStateFromIntId = env->GetStaticMethodID(globalStateClass,"fromInt","(I)Lorg/linphone/core/LinphoneCore$GlobalState;");        globalStateId = env->GetMethodID(listenerClass,"globalState","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCore$GlobalState;Ljava/lang/String;)V");        /*registrationState(LinphoneCore lc, LinphoneProxyConfig cfg, LinphoneCore.RegistrationState cstate, String smessage);*/        registrationStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCore$RegistrationState"));        registrationStateFromIntId = env->GetStaticMethodID(registrationStateClass,"fromInt","(I)Lorg/linphone/core/LinphoneCore$RegistrationState;");        registrationStateId = env->GetMethodID(listenerClass,"registrationState","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneProxyConfig;Lorg/linphone/core/LinphoneCore$RegistrationState;Ljava/lang/String;)V");        /*callState(LinphoneCore lc, LinphoneCall call, LinphoneCall.State cstate,String message);*/        callStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCall$State"));        callStateFromIntId = env->GetStaticMethodID(callStateClass,"fromInt","(I)Lorg/linphone/core/LinphoneCall$State;");        callStateId = env->GetMethodID(listenerClass,"callState","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCall;Lorg/linphone/core/LinphoneCall$State;Ljava/lang/String;)V");        transferStateId = env->GetMethodID(listenerClass,"transferState","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCall;Lorg/linphone/core/LinphoneCall$State;)V");        /*callStatsUpdated(LinphoneCore lc, LinphoneCall call, LinphoneCallStats stats);*/        callStatsUpdatedId = env->GetMethodID(listenerClass, "callStatsUpdated", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCall;Lorg/linphone/core/LinphoneCallStats;)V");        /*callEncryption(LinphoneCore lc, LinphoneCall call, boolean encrypted,String auth_token);*/        callEncryptionChangedId = env->GetMethodID(listenerClass,"callEncryptionChanged","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCall;ZLjava/lang/String;)V");        /*void ecCalibrationStatus(LinphoneCore.EcCalibratorStatus status, int delay_ms, Object data);*/        ecCalibratorStatusClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCore$EcCalibratorStatus"));        ecCalibratorStatusFromIntId = env->GetStaticMethodID(ecCalibratorStatusClass,"fromInt","(I)Lorg/linphone/core/LinphoneCore$EcCalibratorStatus;");        ecCalibrationStatusId = env->GetMethodID(listenerClass,"ecCalibrationStatus","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCore$EcCalibratorStatus;ILjava/lang/Object;)V");        /*void newSubscriptionRequest(LinphoneCore lc, LinphoneFriend lf, String url)*/        newSubscriptionRequestId = env->GetMethodID(listenerClass,"newSubscriptionRequest","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneFriend;Ljava/lang/String;)V");        authInfoRequestedId = env->GetMethodID(listenerClass,"authInfoRequested","(Lorg/linphone/core/LinphoneCore;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");        authenticationRequestedId = env->GetMethodID(listenerClass,"authenticationRequested","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneAuthInfo;Lorg/linphone/core/LinphoneCore$AuthMethod;)V");        /*void notifyPresenceReceived(LinphoneCore lc, LinphoneFriend lf);*/        notifyPresenceReceivedId = env->GetMethodID(listenerClass,"notifyPresenceReceived","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneFriend;)V");        messageReceivedId = env->GetMethodID(listenerClass,"messageReceived","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatRoom;Lorg/linphone/core/LinphoneChatMessage;)V");        messageReceivedUnableToDecryptedId = env->GetMethodID(listenerClass,"messageReceivedUnableToDecrypted","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatRoom;Lorg/linphone/core/LinphoneChatMessage;)V");        isComposingReceivedId = env->GetMethodID(listenerClass,"isComposingReceived","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatRoom;)V");        dtmfReceivedId = env->GetMethodID(listenerClass,"dtmfReceived","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCall;I)V");        infoReceivedId = env->GetMethodID(listenerClass,"infoReceived", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCall;Lorg/linphone/core/LinphoneInfoMessage;)V");        subscriptionStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/SubscriptionState"));        subscriptionStateFromIntId = env->GetStaticMethodID(subscriptionStateClass,"fromInt","(I)Lorg/linphone/core/SubscriptionState;");        subscriptionStateId = env->GetMethodID(listenerClass,"subscriptionStateChanged", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneEvent;Lorg/linphone/core/SubscriptionState;)V");        publishStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/PublishState"));        publishStateFromIntId = env->GetStaticMethodID(publishStateClass,"fromInt","(I)Lorg/linphone/core/PublishState;");        publishStateId = env->GetMethodID(listenerClass,"publishStateChanged", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneEvent;Lorg/linphone/core/PublishState;)V");        notifyRecvId = env->GetMethodID(listenerClass,"notifyReceived", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneEvent;Ljava/lang/String;Lorg/linphone/core/LinphoneContent;)V");        configuringStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCore$RemoteProvisioningState"));        configuringStateFromIntId = env->GetStaticMethodID(configuringStateClass,"fromInt","(I)Lorg/linphone/core/LinphoneCore$RemoteProvisioningState;");        configuringStateId = env->GetMethodID(listenerClass,"configuringStatus","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCore$RemoteProvisioningState;Ljava/lang/String;)V");        fileTransferProgressIndicationId = env->GetMethodID(listenerClass, "fileTransferProgressIndication", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatMessage;Lorg/linphone/core/LinphoneContent;I)V");        fileTransferSendId = env->GetMethodID(listenerClass, "fileTransferSend", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatMessage;Lorg/linphone/core/LinphoneContent;Ljava/nio/ByteBuffer;I)I");        fileTransferRecvId = env->GetMethodID(listenerClass, "fileTransferRecv", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatMessage;Lorg/linphone/core/LinphoneContent;[BI)V");        logCollectionUploadStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCore$LogCollectionUploadState"));        logCollectionUploadStateFromIntId = env->GetStaticMethodID(logCollectionUploadStateClass, "fromInt", "(I)Lorg/linphone/core/LinphoneCore$LogCollectionUploadState;");        logCollectionUploadProgressId = env->GetMethodID(listenerClass, "uploadProgressIndication", "(Lorg/linphone/core/LinphoneCore;II)V");        logCollectionUploadStateId = env->GetMethodID(listenerClass, "uploadStateChanged", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCore$LogCollectionUploadState;Ljava/lang/String;)V");    }}

创建

在linhonecore.c中void *linphone_core_get_user_data(const LinphoneCore *lc){    return lc->data;}

说明了具体的对象还是LinphoneCore中.

LinphoneCoreVTable的作用及代码

代码

/** * This structure holds all callbacks that the application should implement. * None is mandatory.**/typedef struct _LinphoneCoreVTable{    LinphoneCoreGlobalStateChangedCb global_state_changed; /**<Notifies global state changes*/    LinphoneCoreRegistrationStateChangedCb registration_state_changed;/**<Notifies registration state changes*/    LinphoneCoreCallStateChangedCb call_state_changed;/**<Notifies call state changes*/    LinphoneCoreNotifyPresenceReceivedCb notify_presence_received; /**< Notify received presence events*/    LinphoneCoreNotifyPresenceReceivedForUriOrTelCb notify_presence_received_for_uri_or_tel; /**< Notify received presence events*/    LinphoneCoreNewSubscriptionRequestedCb new_subscription_requested; /**< Notify about pending presence subscription request */    LINPHONE_DEPRECATED LinphoneCoreAuthInfoRequestedCb auth_info_requested; /**< @deprecated Use authentication_requested instead. Ask the application some authentication information */    LinphoneCoreAuthenticationRequestedCb authentication_requested; /**< Ask the application some authentication information */    LinphoneCoreCallLogUpdatedCb call_log_updated; /**< Notifies that call log list has been updated */    LinphoneCoreMessageReceivedCb message_received; /**< a message is received, can be text or external body*/    LinphoneCoreCbsMessageReceivedUnableDecryptCb message_received_unable_decrypt; /**< an encrypted message is received but we can't decrypt it*/    LinphoneCoreIsComposingReceivedCb is_composing_received; /**< An is-composing notification has been received */    LinphoneCoreDtmfReceivedCb dtmf_received; /**< A dtmf has been received received */    LinphoneCoreReferReceivedCb refer_received; /**< An out of call refer was received */    LinphoneCoreCallEncryptionChangedCb call_encryption_changed; /**<Notifies on change in the encryption of call streams */    LinphoneCoreTransferStateChangedCb transfer_state_changed; /**<Notifies when a transfer is in progress */    LinphoneCoreBuddyInfoUpdatedCb buddy_info_updated; /**< a LinphoneFriend's BuddyInfo has changed*/    LinphoneCoreCallStatsUpdatedCb call_stats_updated; /**<Notifies on refreshing of call's statistics. */    LinphoneCoreInfoReceivedCb info_received; /**<Notifies an incoming informational message received.*/    LinphoneCoreSubscriptionStateChangedCb subscription_state_changed; /**<Notifies subscription state change */    LinphoneCoreNotifyReceivedCb notify_received; /**< Notifies a an event notification, see linphone_core_subscribe() */    LinphoneCorePublishStateChangedCb publish_state_changed;/**Notifies publish state change (only from #LinphoneEvent api)*/    LinphoneCoreConfiguringStatusCb configuring_status; /** Notifies configuring status changes */    LINPHONE_DEPRECATED DisplayStatusCb display_status; /**< @deprecated Callback that notifies various events with human readable text.*/    LINPHONE_DEPRECATED DisplayMessageCb display_message;/**< @deprecated Callback to display a message to the user */    LINPHONE_DEPRECATED DisplayMessageCb display_warning;/**< @deprecated Callback to display a warning to the user */    LINPHONE_DEPRECATED DisplayUrlCb display_url; /**< @deprecated */    LINPHONE_DEPRECATED ShowInterfaceCb show; /**< vNotifies the application that it should show up*/    LINPHONE_DEPRECATED LinphoneCoreTextMessageReceivedCb text_received; /**< @deprecated, use #message_received instead <br> A text message has been received */    LINPHONE_DEPRECATED LinphoneCoreFileTransferRecvCb file_transfer_recv; /**< @deprecated Callback to store file received attached to a #LinphoneChatMessage */    LINPHONE_DEPRECATED LinphoneCoreFileTransferSendCb file_transfer_send; /**< @deprecated Callback to collect file chunk to be sent for a #LinphoneChatMessage */    LINPHONE_DEPRECATED LinphoneCoreFileTransferProgressIndicationCb file_transfer_progress_indication; /**< @deprecated Callback to indicate file transfer progress */    LinphoneCoreNetworkReachableCb network_reachable; /**< Callback to report IP network status (I.E up/down )*/    LinphoneCoreLogCollectionUploadStateChangedCb log_collection_upload_state_changed; /**< Callback to upload collected logs */    LinphoneCoreLogCollectionUploadProgressIndicationCb log_collection_upload_progress_indication; /**< Callback to indicate log collection upload progress */    LinphoneCoreFriendListCreatedCb friend_list_created;    LinphoneCoreFriendListRemovedCb friend_list_removed;    void *user_data; /**<User data associated with the above callbacks */} LinphoneCoreVTable;

说明

回调时应用的查询表. 创建内存空间后, 供下列函数使用.

创建

LinphoneCoreVTable *linphone_core_v_table_new() {    return ms_new0(LinphoneCoreVTable,1);}

目的就是实例化一个table

class LinphoneCoreData的作用及代码

代码

    LinphoneCoreData(JNIEnv *env, jobject lc, LinphoneCoreVTable *vTable, jobject alistener, LinphoneJavaBindings *ljb) {        core = env->NewGlobalRef(lc);        listener = env->NewGlobalRef(alistener);        memset(vTable, 0, sizeof(LinphoneCoreVTable));        if (ljb->displayStatusId) {            vTable->display_status = displayStatusCb;        }        if (ljb->globalStateId) {            vTable->global_state_changed = globalStateChange;        }        if (ljb->registrationStateId) {            vTable->registration_state_changed = registrationStateChange;        }        if (ljb->callStateId) {            vTable->call_state_changed = callStateChange;        }        if (ljb->transferStateId) {            vTable->transfer_state_changed = transferStateChanged;        }        if (ljb->callStatsUpdatedId) {            vTable->call_stats_updated = callStatsUpdated;        }        if (ljb->callEncryptionChangedId) {            vTable->call_encryption_changed = callEncryptionChange;        }        if (ljb->newSubscriptionRequestId) {            vTable->new_subscription_requested = new_subscription_requested;        }        if (ljb->authInfoRequestedId) {            vTable->auth_info_requested = authInfoRequested;        }        if (ljb->authenticationRequestedId) {            vTable->authentication_requested = authenticationRequested;        }        if (ljb->notifyPresenceReceivedId) {            vTable->notify_presence_received = notify_presence_received;        }        if (ljb->messageReceivedId) {            vTable->message_received = message_received;        }        if (ljb->messageReceivedUnableToDecryptedId) {            vTable->message_received_unable_decrypt = message_received_unable_decrypt;        }        if (ljb->isComposingReceivedId) {            vTable->is_composing_received = is_composing_received;        }        if (ljb->dtmfReceivedId) {            vTable->dtmf_received = dtmf_received;        }        if (ljb->infoReceivedId) {            vTable->info_received = infoReceived;        }        if (ljb->subscriptionStateId) {            vTable->subscription_state_changed = subscriptionStateChanged;        }        if (ljb->publishStateId) {            vTable->publish_state_changed = publishStateChanged;        }        if (ljb->notifyRecvId) {            vTable->notify_received = notifyReceived;        }        if (ljb->configuringStateId) {            vTable->configuring_status = configuringStatus;        }        if (ljb->fileTransferProgressIndicationId) {            vTable->file_transfer_progress_indication = fileTransferProgressIndication;        }        if (ljb->fileTransferSendId) {            vTable->file_transfer_send = fileTransferSend;        }        if (ljb->fileTransferRecvId) {            vTable->file_transfer_recv = fileTransferRecv;        }        if (ljb->logCollectionUploadProgressId) {            vTable->log_collection_upload_progress_indication = logCollectionUploadProgressIndication;        }        if (ljb->logCollectionUploadStateId) {            vTable->log_collection_upload_state_changed = logCollectionUploadStateChange;        }        if (ljb->friendListCreatedId) {            vTable->friend_list_created = friendListCreated;        }        if (ljb->friendListRemovedId) {            vTable->friend_list_removed = friendListRemoved;        }    }

说明

这是类是将VTable一一对应起来, 进行数据的操作. 通过调用相应的方法, 对上层java方法进行回调操作, 这里时ListenerCoreListener主要的操作实体类.

linphone_core_v_table_set_user_data()函数都干了什么

代码

void linphone_core_v_table_set_user_data(LinphoneCoreVTable *table, void *data) {    table->user_data = data;}

说明

将数据赋值.

重点来了linphone_core_add_listener

代码

void linphone_core_add_listener(LinphoneCore *lc, LinphoneCoreVTable *vtable){    LinphoneCoreCbs *cbs = linphone_factory_create_core_cbs(linphone_factory_get());    _linphone_core_cbs_set_v_table(cbs, vtable, FALSE);    _linphone_core_add_callbacks(lc, cbs, FALSE);    linphone_core_cbs_unref(cbs);}

说明

这个是真刀真枪的用道德时候了.

LinphoneCoreCbs

代码

struct _LinphoneCoreCbs {    belle_sip_object_t base;    LinphoneCoreVTable *vtable;    bool_t autorelease;};

说明

这个路径好深啊, 我只能这么说了.

创建

linphone_factory_create_core_cbs()函数创建

LinphoneCore *linphone_factory_create_core(const LinphoneFactory *factory, LinphoneCoreCbs *cbs,        const char *config_path, const char *factory_config_path) {    LpConfig *config = lp_config_new_with_factory(config_path, factory_config_path);    LinphoneCore *lc = _linphone_core_new_with_config(cbs, config, NULL);    lp_config_unref(config);    return lc;}

东西很多,最后在找到了这个bctbx_list_append_link

bctbx_list_t *bctbx_list_append_link(bctbx_list_t *elem, bctbx_list_t *new_elem) {    bctbx_list_t *it = elem;    if (elem == NULL) return new_elem;    if (new_elem == NULL) return elem;    while (it->next != NULL) it = bctbx_list_next(it);    it->next = new_elem;    new_elem->prev = it;    return elem;}

这个就是将监听时间添到了列表中.

但是什么时候回调的呢

关于这个问题, 我觉得应该会有很多地方调用. 但是总会有一个列表的, 猜测应该vtable.c中.

没错了,就应该是这个文件中.

会不会就是这个呢

#define NOTIFY_IF_EXIST_INTERNAL(function_name, internal_val, ...) \    bctbx_list_t* iterator; \    VTableReference *ref; \    lc->vtable_notify_recursion++;\    for (iterator=lc->vtable_refs; iterator!=NULL; iterator=iterator->next){\        if ((ref=(VTableReference*)iterator->data)->valid && (lc->current_cbs=ref->cbs)->vtable->function_name && (ref->internal == internal_val)) {\            lc->current_cbs->vtable->function_name(__VA_ARGS__);\        }\    }\    lc->vtable_notify_recursion--;

然后处理的方法应该在这里面

void linphone_core_notify_notify_received(LinphoneCore *lc, LinphoneEvent *lev, const char *notified_event, const LinphoneContent *body) {    NOTIFY_IF_EXIST_INTERNAL(notify_received, linphone_event_is_internal(lev), lc, lev, notified_event, body);    cleanup_dead_vtable_refs(lc);}void linphone_core_notify_subscription_state_changed(LinphoneCore *lc, LinphoneEvent *lev, LinphoneSubscriptionState state) {    NOTIFY_IF_EXIST_INTERNAL(subscription_state_changed,linphone_event_is_internal(lev), lc,lev,state);    cleanup_dead_vtable_refs(lc);}void linphone_core_notify_publish_state_changed(LinphoneCore *lc, LinphoneEvent *lev, LinphonePublishState state) {    NOTIFY_IF_EXIST_INTERNAL(publish_state_changed, linphone_event_is_internal(lev), lc, lev, state);    cleanup_dead_vtable_refs(lc);}
0 0
原创粉丝点击