<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[Freeswitch-trunk][16408] </title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<div id="header">FreeSWITCH Subversion</div>
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://fisheye.freeswitch.org/changelog/FreeSWITCH?cs=16408">16408</a></dd>
<dt>Author</dt> <dd>anthm</dd>
<dt>Date</dt> <dd>2010-01-19 12:12:39 -0600 (Tue, 19 Jan 2010)</dd>
</dl>

<h3>Log Message</h3>
<pre>mix member play file data in with conference so you can hear the bg while hearing the member file</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#freeswitchtrunksrcmodapplicationsmod_conferencemod_conferencec">freeswitch/trunk/src/mod/applications/mod_conference/mod_conference.c</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="freeswitchtrunksrcmodapplicationsmod_conferencemod_conferencec"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/src/mod/applications/mod_conference/mod_conference.c (16407 => 16408)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/src/mod/applications/mod_conference/mod_conference.c        2010-01-19 18:09:52 UTC (rev 16407)
+++ freeswitch/trunk/src/mod/applications/mod_conference/mod_conference.c        2010-01-19 18:12:39 UTC (rev 16408)
</span><span class="lines">@@ -2031,6 +2031,82 @@
</span><span class="cx">         return NULL;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+
+static void member_add_file_data(conference_member_t *member, int16_t *data, switch_size_t file_data_len)
+{
+        switch_size_t file_sample_len = file_data_len / 2;
+        int16_t file_frame[SWITCH_RECOMMENDED_BUFFER_SIZE/2] = {0};
+
+        if (!member-&gt;fnode) {
+                return;
+        }
+
+        /* if we are done, clean it up */
+        if (member-&gt;fnode-&gt;done) {
+                conference_file_node_t *fnode;
+                switch_memory_pool_t *pool;
+
+                if (member-&gt;fnode-&gt;type != NODE_TYPE_SPEECH) {
+                        switch_core_file_close(&amp;member-&gt;fnode-&gt;fh);
+                }
+
+                fnode = member-&gt;fnode;
+                member-&gt;fnode = member-&gt;fnode-&gt;next;
+
+                pool = fnode-&gt;pool;
+                fnode = NULL;
+                switch_core_destroy_memory_pool(&amp;pool);
+        } else {
+                /* skip this frame until leadin time has expired */
+                if (member-&gt;fnode-&gt;leadin) {
+                        member-&gt;fnode-&gt;leadin--;
+                } else {
+                        if (member-&gt;fnode-&gt;type == NODE_TYPE_SPEECH) {
+                                switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_BLOCKING;
+                                                
+                                if (switch_core_speech_read_tts(member-&gt;fnode-&gt;sh, file_frame, &amp;file_data_len, &amp;flags) == SWITCH_STATUS_SUCCESS) {
+                                        file_sample_len = file_data_len / 2;
+                                } else {
+                                        file_sample_len = file_data_len = 0;
+                                }
+                        } else if (member-&gt;fnode-&gt;type == NODE_TYPE_FILE) {
+                                switch_core_file_read(&amp;member-&gt;fnode-&gt;fh, file_frame, &amp;file_sample_len);
+                                file_data_len = file_sample_len * 2;
+                        }
+
+                        if (file_sample_len &lt;= 0) {
+                                switch_event_t *event;
+                                member-&gt;fnode-&gt;done++;
+                                
+                                if (test_eflag(member-&gt;conference, EFLAG_PLAY_FILE) &amp;&amp;
+                                        switch_event_create_subclass(&amp;event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
+                                        conference_add_event_data(member-&gt;conference, event);
+                                        conference_add_event_member_data(member, event);
+                                        switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, &quot;Action&quot;, &quot;play-file-member-done&quot;);
+                                        switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, &quot;File&quot;, member-&gt;fnode-&gt;file);
+                                        switch_event_fire(&amp;event);
+                                }
+                        } else {        /* there is file node data to mix into the frame */
+                                int32_t i, sample;
+                                
+                                /* Check for output volume adjustments */
+                                if (member-&gt;volume_out_level) {
+                                        switch_change_sln_volume(file_frame, file_sample_len, member-&gt;volume_out_level);
+                                }
+                                
+                                for(i = 0; i &lt; file_sample_len; i++) {
+                                        sample = data[i] + file_frame[i];
+                                        switch_normalize_to_16bit(sample);
+                                        data[i] = sample;
+                                }
+                                
+                        }
+                }
+        }
+}
+
+
+
</ins><span class="cx"> /* launch an input thread for the call leg */
</span><span class="cx"> static void launch_conference_loop_input(conference_member_t *member, switch_memory_pool_t *pool)
</span><span class="cx"> {
</span><span class="lines">@@ -2196,15 +2272,13 @@
</span><span class="cx">         while (switch_test_flag(member, MFLAG_RUNNING) &amp;&amp; switch_test_flag(member, MFLAG_ITHREAD)
</span><span class="cx">                    &amp;&amp; switch_channel_ready(channel)) {
</span><span class="cx">                 char dtmf[128] = &quot;&quot;;
</span><del>-                uint8_t file_frame[SWITCH_RECOMMENDED_BUFFER_SIZE] = { 0 };
</del><span class="cx">                 char *digit;
</span><span class="cx">                 switch_event_t *event;
</span><span class="cx">                 caller_control_action_t *caller_action = NULL;
</span><span class="cx">                 int use_timer = 0;
</span><del>-                switch_size_t file_sample_len = csamples;
-                switch_size_t file_data_len = file_sample_len * 2;
</del><ins>+                switch_buffer_t *use_buffer = NULL;
+                uint32_t mux_used = 0;
</ins><span class="cx"> 
</span><del>-
</del><span class="cx">                 switch_mutex_lock(member-&gt;write_mutex);
</span><span class="cx"> 
</span><span class="cx">                 if (switch_test_flag(member, MFLAG_RESTART)) {
</span><span class="lines">@@ -2287,121 +2361,67 @@
</span><span class="cx">                         caller_action = NULL;
</span><span class="cx">                 }
</span><span class="cx"> 
</span><del>-                /* handle file and TTS frames */
-                if (member-&gt;fnode) {
-                        /* if we are done, clean it up */
-                        if (member-&gt;fnode-&gt;done) {
-                                conference_file_node_t *fnode;
-                                switch_memory_pool_t *pool;
</del><ins>+                
+                use_buffer = NULL;
+                mux_used = (uint32_t) switch_buffer_inuse(member-&gt;mux_buffer);
</ins><span class="cx"> 
</span><del>-                                if (member-&gt;fnode-&gt;type != NODE_TYPE_SPEECH) {
-                                        switch_core_file_close(&amp;member-&gt;fnode-&gt;fh);
</del><ins>+                if (mux_used) {
+                        if (mux_used &lt; bytes) {
+                                if (++low_count &gt;= 5) {
+                                        /* partial frame sitting around this long is useless and builds delay */
+                                        switch_set_flag_locked(member, MFLAG_FLUSH_BUFFER);
</ins><span class="cx">                                 }
</span><ins>+                        } else if (mux_used &gt; flush_len) {
+                                /* getting behind, clear the buffer */
+                                switch_set_flag_locked(member, MFLAG_FLUSH_BUFFER);
+                        }
+                }
+                        
</ins><span class="cx"> 
</span><del>-                                fnode = member-&gt;fnode;
-                                member-&gt;fnode = member-&gt;fnode-&gt;next;
</del><ins>+                use_timer = 1;
+                
+                if (mux_used) {
+                        /* Flush the output buffer and write all the data (presumably muxed) back to the channel */
+                        switch_mutex_lock(member-&gt;audio_out_mutex);
+                        write_frame.data = data;
+                        use_buffer = member-&gt;mux_buffer;
+                        low_count = 0;
+                        if ((write_frame.datalen = (uint32_t) switch_buffer_read(use_buffer, write_frame.data, bytes))) {
+                                if (write_frame.datalen &amp;&amp; switch_test_flag(member, MFLAG_CAN_HEAR)) {
+                                        write_frame.samples = write_frame.datalen / 2;
</ins><span class="cx"> 
</span><del>-                                pool = fnode-&gt;pool;
-                                fnode = NULL;
-                                switch_core_destroy_memory_pool(&amp;pool);
-                        } else {
-                                /* skip this frame until leadin time has expired */
-                                if (member-&gt;fnode-&gt;leadin) {
-                                        member-&gt;fnode-&gt;leadin--;
-                                } else {                /* send the node frame instead of the conference frame to the call leg */
-                                        if (member-&gt;fnode-&gt;type == NODE_TYPE_SPEECH) {
-                                                switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_BLOCKING;
-                                                
-                                                if (switch_core_speech_read_tts(member-&gt;fnode-&gt;sh, file_frame, &amp;file_data_len, &amp;flags) == SWITCH_STATUS_SUCCESS) {
-                                                        file_sample_len = file_data_len / 2;
-                                                } else {
-                                                        file_sample_len = file_data_len = 0;
-                                                }
-                                        } else if (member-&gt;fnode-&gt;type == NODE_TYPE_FILE) {
-                                                switch_core_file_read(&amp;member-&gt;fnode-&gt;fh, file_frame, &amp;file_sample_len);
-                                                file_data_len = file_sample_len * 2;
</del><ins>+                                        /* Check for output volume adjustments */
+                                        if (member-&gt;volume_out_level) {
+                                                switch_change_sln_volume(write_frame.data, write_frame.samples, member-&gt;volume_out_level);
</ins><span class="cx">                                         }
</span><del>-
-                                        if (file_sample_len &lt;= 0) {
-                                                member-&gt;fnode-&gt;done++;
-
-                                                if (test_eflag(member-&gt;conference, EFLAG_PLAY_FILE) &amp;&amp;
-                                                        switch_event_create_subclass(&amp;event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
-                                                        conference_add_event_data(member-&gt;conference, event);
-                                                        conference_add_event_member_data(member, event);
-                                                        switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, &quot;Action&quot;, &quot;play-file-member-done&quot;);
-                                                        switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, &quot;File&quot;, member-&gt;fnode-&gt;file);
-                                                        switch_event_fire(&amp;event);
-                                                }
-                                        } else {        /* there is file node data to deliver */
-                                                write_frame.data = file_frame;
-                                                write_frame.datalen = (uint32_t) file_data_len;
-                                                write_frame.samples = (uint32_t) file_sample_len;
-                                                /* Check for output volume adjustments */
-                                                if (member-&gt;volume_out_level) {
-                                                        switch_change_sln_volume(write_frame.data, write_frame.samples, member-&gt;volume_out_level);
-                                                }
-                                                write_frame.timestamp = timer.samplecount;
-                                                switch_core_session_write_frame(member-&gt;session, &amp;write_frame, SWITCH_IO_FLAG_NONE, 0);
-                                                switch_core_timer_next(&amp;timer);
-
-
-                                                /* forget the conference data we played file node data instead */
-                                                switch_set_flag_locked(member, MFLAG_FLUSH_BUFFER);
</del><ins>+                                        write_frame.timestamp = timer.samplecount;
+                                        if (member-&gt;fnode) {
+                                                member_add_file_data(member, write_frame.data, write_frame.datalen);
</ins><span class="cx">                                         }
</span><ins>+                                        switch_core_session_write_frame(member-&gt;session, &amp;write_frame, SWITCH_IO_FLAG_NONE, 0);
</ins><span class="cx">                                 }
</span><span class="cx">                         }
</span><del>-                } else {
-                        switch_buffer_t *use_buffer = NULL;
-                        uint32_t mux_used = (uint32_t) switch_buffer_inuse(member-&gt;mux_buffer);
</del><span class="cx"> 
</span><del>-                        if (mux_used) {
-                                if (mux_used &lt; bytes) {
-                                        if (++low_count &gt;= 5) {
-                                                /* partial frame sitting around this long is useless and builds delay */
-                                                switch_set_flag_locked(member, MFLAG_FLUSH_BUFFER);
-                                        }
-                                } else if (mux_used &gt; flush_len) {
-                                        /* getting behind, clear the buffer */
-                                        switch_set_flag_locked(member, MFLAG_FLUSH_BUFFER);
</del><ins>+                        switch_mutex_unlock(member-&gt;audio_out_mutex);
+                } else if (member-&gt;fnode) {
+                        write_frame.datalen = bytes;
+                        write_frame.samples = samples;
+                        memset(write_frame.data, 255, write_frame.datalen);
+                        member_add_file_data(member, write_frame.data, write_frame.datalen);
+                        switch_core_session_write_frame(member-&gt;session, &amp;write_frame, SWITCH_IO_FLAG_NONE, 0);
+                } else if (!switch_test_flag(member-&gt;conference, CFLAG_WASTE_BANDWIDTH)) {
+                        if (switch_test_flag(member, MFLAG_WASTE_BANDWIDTH)) {
+                                if (member-&gt;conference-&gt;comfort_noise_level) {
+                                                switch_generate_sln_silence(write_frame.data, samples, member-&gt;conference-&gt;comfort_noise_level);
+                                } else {
+                                        memset(write_frame.data, 255, bytes);
</ins><span class="cx">                                 }
</span><del>-                        }
</del><span class="cx"> 
</span><del>-
-                        use_timer = 1;
-
-                        if (mux_used) {
-                                /* Flush the output buffer and write all the data (presumably muxed) back to the channel */
-                                switch_mutex_lock(member-&gt;audio_out_mutex);
-                                write_frame.data = data;
-                                use_buffer = member-&gt;mux_buffer;
-                                low_count = 0;
-                                if ((write_frame.datalen = (uint32_t) switch_buffer_read(use_buffer, write_frame.data, bytes))) {
-                                        if (write_frame.datalen &amp;&amp; switch_test_flag(member, MFLAG_CAN_HEAR)) {
-                                                write_frame.samples = write_frame.datalen / 2;
-
-                                                /* Check for output volume adjustments */
-                                                if (member-&gt;volume_out_level) {
-                                                        switch_change_sln_volume(write_frame.data, write_frame.samples, member-&gt;volume_out_level);
-                                                }
-                                                write_frame.timestamp = timer.samplecount;
-                                                switch_core_session_write_frame(member-&gt;session, &amp;write_frame, SWITCH_IO_FLAG_NONE, 0);
-                                        }
-                                }
-
-                                switch_mutex_unlock(member-&gt;audio_out_mutex);
-                        } else if (!switch_test_flag(member-&gt;conference, CFLAG_WASTE_BANDWIDTH)) {
-                                if (switch_test_flag(member, MFLAG_WASTE_BANDWIDTH)) {
-                                        if (member-&gt;conference-&gt;comfort_noise_level) {
-                                                switch_generate_sln_silence(write_frame.data, samples, member-&gt;conference-&gt;comfort_noise_level);
-                                        } else {
-                                                memset(write_frame.data, 255, bytes);
-                                        }
-                                        write_frame.datalen = bytes;
-                                        write_frame.samples = samples;
-                                        write_frame.timestamp = timer.samplecount;
-                                        switch_core_session_write_frame(member-&gt;session, &amp;write_frame, SWITCH_IO_FLAG_NONE, 0);
-                                }
</del><ins>+                                write_frame.datalen = bytes;
+                                write_frame.samples = samples;
+                                write_frame.timestamp = timer.samplecount;
+                                
+                                switch_core_session_write_frame(member-&gt;session, &amp;write_frame, SWITCH_IO_FLAG_NONE, 0);
</ins><span class="cx">                         }
</span><span class="cx">                 }
</span><span class="cx"> 
</span></span></pre>
</div>
</div>
<div id="footer">See you at ClueCon</div>

</body>
</html>