我建了一个 Freeswitch 内核研究 交流群, 45211986, 欢迎加入, 另外,提供基于SIP的通信服务器及客户端解决方案。
 
这里以模块 helloworld 为例。
1. 创建模块目录  freeswitch/src/mod/applications/mod_helloworld
2. 把模块名放在 freeswitch/modules.conf文件中,make时 根据此文件选择编译哪些模块并生成相应模块的makefile文件
3. 如果你的模块以依赖第三方库,则需要在makefile中指定头文件以及库的路径,一个例子:
 
LOCAL_CFLAGS=-I$(switch_srcdir)/libs/libteletone/src
LOCAL_LDFLAGS=$(switch_srcdir)/libs/libteletone/libteletone.la
 
 
4.如果你的模块包含多个文件则需要 指定文件列表:
 
LOCAL_OBJS=file.c file2.c file3.c 
local_depend: $(LOCAL_OBJS)
 
 
5.编写模块接口
 
freeswitch中 每个模块从加载->运行->关闭 流程由三个宏实现,实际编写模块过程为几个宏的填写。具体业务逻辑在宏内部实现。
SWITCH_MODULE_LOAD_FUNCTION (mod_name)
 
实际展开即为函数,load function 负责系统启动时或运行时加载模块,模块的全局数据结构,钩子设置,事件handler 一般在此处实现。
 
SWITCH_MODULE_RUNTIME_FUNCTION
系统运行时loop, 这里可以启动线程处理请求,监听socket 等等。
SWITCH_MODULE_SHUTDOWN_FUNCTION
模块卸载,这里负责清除全局数据结构,释放资源。
  
 
SWITCH_MODULE_DEFINITION  模块的定义
 
mod_helloworld.c 代码:
 
 
- #include <switch.h>  
-   
- SWITCH_MODULE_LOAD_FUNCTION(mod_helloworld_load);  
-   
-  
- SWITCH_MODULE_RUNTIME_FUNCTION(mod_helloworld_runtime);  
-   
-  
- SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_helloworld_shutdown);  
-   
- SWITCH_MODULE_DEFINITION(mod_helloworld, mod_helloworld_load, mod_helloworld_shutdown, NULL);  
-   
-   
- SWITCH_STANDARD_API(helloworld_function)  
- {  
-     return SWITCH_STATUS_SUCCESS;  
- }  
- static switch_status_t parse_config(switch_bool_t reload)  
- {  
-     switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "parse config\n");  
-   
-     return SWITCH_STATUS_SUCCESS;  
- }  
-   
- SWITCH_MODULE_LOAD_FUNCTION(mod_helloworld_load)  
- {  
-     switch_api_interface_t *api_interface;  
-     
-     *module_interface = switch_loadable_module_create_module_interface(pool, modname);  
-   
-     switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Hello World!\n");  
-   
-     parse_config(SWITCH_FALSE);  
-   
-     SWITCH_ADD_API(api_interface, "helloworld", "Hello World API", helloworld_function, "syntax");  
-   
-     
-     return SWITCH_STATUS_SUCCESS;  
-       
- }  
-   
- SWITCH_MODULE_RUNTIME_FUNCTION(mod_helloworld_runtime)  
- {  
-     while(1) {  
-         switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Hello World!\n");  
-         switch_yield(10000);  
-     }  
- }<pre class="cpp" name="code"></pre>  
- <pre></pre>  
- <pre class="cpp" name="code"></pre><pre class="cpp" name="code"></pre><pre class="cpp" name="code"></pre><pre class="cpp" name="code"></pre><pre class="cpp" name="code"></pre><pre class="cpp" name="code"></pre><pre class="cpp" name="code"></pre><pre class="cpp" name="code"><pre class="cpp" name="code"></pre>  
- <p><br>  
- </p>  
- <pre style="border-bottom:rgb(60,120,181) 1px solid; border-left:rgb(60,120,181) 1px solid; padding-bottom:0.4em; background-color:rgb(240,240,240); padding-left:0.4em; padding-right:0.4em; border-top:rgb(60,120,181) 1px solid; border-right:rgb(60,120,181) 1px solid; padding-top:0.4em"><pre name="code" class="cpp">编译: sudo make mod_helloworld  
- 安装   sudo make mod_helloworld-install  
- dialplan里试一试 function  helloworld.  
- -----------------------------------  
- 高级:  
- 1.模块加载函数内可以加载自定义xml配置文件.  
- 例子:  
- <configuration name="mymodule.conf" description="MyModule configuration">  
-    <settings>  
-     <param name="key" value="value"/>  
-     ...  
-    </settings>  
-  </configuration>  
- You could do the following:  
-   
-  switch_xml_t xml = NULL, x_lists = NULL, x_list = NULL, cfg = NULL;  
-  if ((xml = switch_xml_open_cfg("mymodule.conf", &cfg, NULL))) {  
-    if ((x_lists = switch_xml_child(cfg, "settings"))) {  
-      for (x_list = switch_xml_child(x_lists, "param"); x_list; x_list = x_list->next) {  
-        const char *name = switch_xml_attr(x_list, "name"); 
-        const char *value = switch_xml_attr(x_list, "value");  
-    
-        
-        if (switch_strlen_zero(name)) {  
-          continue;  
-        }  
-          
-        if (switch_strlen_zero(value)) {  
-          continue;  
-        }  
-    
-        if (!strcmp(name, "myattribute")) {  
-          
-        } else if (!strcmp(name, "myotherattribute")) {  
-          
-        } else {  
-          switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unknown attribute %s\n", name);  
-        }  
-      }  
-    }  
-  } else {  
-    switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to load MyModule‘s config!\n");  
-  }  
-   
- 2. 订阅事件  
- 模块可以向系统订阅自己感兴趣的事件,只需一个函数,指定一个你自己的事件回调。  
- 例子:订阅所有事件  
- if (switch_event_bind("mod_mymodule", SWITCH_EVENT_ALL, SWITCH_EVENT_SUBCLASS_ANY, mymodule_event_handler, NULL) != SWITCH_STATUS_SUCCESS) {  
-    switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot bind to event handler!\n");  
-  }  
-   
- 接下来就是编写你的回调函数   
- void mymodule_event_handler(switch_event_t *event);  
- void mymodule_event_handler(switch_event_t *event)   
-  {  
-     switch_assert(event); 
-       
-     switch(event->event_id) {  
-         case SWITCH_EVENT_CHANNEL_CREATE:  
-             switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "A new channel is born, its called \"%s\"\n",   
-                 switch_event_get_header_nil(event, "channel-name")); 
-             break;  
-         case SWITCH_EVENT_CHANNEL_DESTROY:  
-             switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "A channel named \"%s\" has been destroyed\n"  
-                 switch_event_get_header_nil(event, "channel-name"));  
-             break;  
-     }  
-  }  
-   
- 3.在模块内 发起呼叫,定义channle状态回调。。。。  
- </pre><br><br></pre>  
- <p></p>  
- <pre></pre>  
- <pre></pre>  
- <pre></pre>  
- <pre></pre>  
- <pre></pre>  
- <pre></pre>  
- <pre></pre>  
- <pre></pre>  
- <pre></pre>  
-      
- </pre>