<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>teknopipo.nl &#187; Telecom</title>
	<atom:link href="http://www.teknopipo.nl/archives/category/telecom/feed" rel="self" type="application/rss+xml" />
	<link>http://www.teknopipo.nl</link>
	<description></description>
	<lastBuildDate>Tue, 29 Nov 2011 17:45:46 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Java SysEx programming</title>
		<link>http://www.teknopipo.nl/archives/677</link>
		<comments>http://www.teknopipo.nl/archives/677#comments</comments>
		<pubDate>Wed, 05 May 2010 21:44:15 +0000</pubDate>
		<dc:creator>teknopipo</dc:creator>
				<category><![CDATA[Audio]]></category>
		<category><![CDATA[Telecom]]></category>
		<category><![CDATA[javasound]]></category>
		<category><![CDATA[message]]></category>
		<category><![CDATA[midi]]></category>
		<category><![CDATA[mmj]]></category>
		<category><![CDATA[osx]]></category>
		<category><![CDATA[snow leopard]]></category>
		<category><![CDATA[sysex]]></category>

		<guid isPermaLink="false">http://www.teknopipo.nl/?p=677</guid>
		<description><![CDATA[I&#8217;m taking my first steps into the world of JavaSound programming. The first thing I learned is that the Snow Leopard default javax.sound.midi.spi implementation is buggy when it comes to SysEx message transmission. For the time being I&#8217;m sticking with the MMJ library instead. As an example, I&#8217;ve been trying to send a &#8220;SID Skip [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.teknopipo.nl/wp-content/uploads/2010/05/ElektronSidStation.png"><img class="alignleft size-full wp-image-678" style="border: 1px solid black; margin-left: 5px; margin-right: 5px;" title="ElektronSidStation" src="http://www.teknopipo.nl/wp-content/uploads/2010/05/ElektronSidStation.png" alt="" width="158" height="124" /></a>I&#8217;m taking my first steps into the world of JavaSound programming. The first thing I learned is that the Snow Leopard default <code>javax.sound.midi.spi</code> implementation is buggy when it comes to SysEx message transmission. For the time being I&#8217;m sticking with the <a href="http://www.humatic.de/htools/mmj.htm" target="_blank">MMJ</a> library instead.</p>
<p>As an example, I&#8217;ve been trying to send a &#8220;SID Skip Patch&#8221; command to my SID station. The SysEx message for this command is <code>F0 00 20 3C 01 00 03 F7</code>.</p>
<p>The following code shows how to construct this message in Java (example based on <a href="http://www.jsresources.org/examples/SendSysex.java.html" target="_blank">SendSysex.java</a> at jsresources.org):</p>
<p><code><br />
String s = "F000203C010003F7";<br />
int n = s.length() / 2;<br />
byte[] msg = new byte[n];<br />
for (int i = 0; i &lt; n; i++) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;msg[i] = (byte) Integer.parseInt(<br />
&nbsp;&nbsp;&nbsp;&nbsp;s.substring(i * 2, i * 2 + 2), 16);<br />
}<br />
</code></p>
<p>The next step is to send the resulting byte array to a MIDI output. The following code works fine (tested with <a href="http://www.snoize.com/MIDIMonitor/" target="_blank">MIDI monitor</a> and on a real SID station through an <a href="http://www.esi-audio.com/products/midi_mate/" target="_blank">ESI MIDI Mate</a>):<br />
<code><br />
String[] outputs = de.humatic.mmj.MidiSystem.getOutputs();<br />
int index = 0;<br />
&nbsp;<br />
//  insert code to set correct index here...<br />
&nbsp;<br />
de.humatic.mmj.MidiOutput mo = &nbsp;&nbsp;&nbsp;&nbsp;de.humatic.mmj.MidiSystem.openMidiOutput(index);<br />
mo.sendMidi(msg);<br />
</code><br />
I&#8217;ve left out the code to determine the correct index as it is irrelevant. This could be a dropdown list in a GUI or some substring search or whatever. The following code tries to do the same thing using Snow Leopard libraries, but sends nothing at all:<br />
<code><br />
javax.sound.midi.SysexMessage sysexMsg;<br />
javax.sound.midi.Receiver receiver;<br />
javax.sound.midi.MidiDevice.Info[] dev;<br />
int index;<br />
javax.sound.midi.MidiDevice myOutPort;<br />
&nbsp;<br />
sysexMsg = new SysexMessage();<br />
sysexMsg.setMessage(msg, msg.length);<br />
dev = javax.sound.midi.MidiSystem.getMidiDeviceInfo();<br />
&nbsp;<br />
//  insert code to set correct index here...<br />
&nbsp;<br />
myOutPort =<br />
&nbsp;&nbsp;&nbsp;&nbsp;javax.sound.midi.MidiSystem.getMidiDevice(dev[index]);<br />
myOutPort.open();<br />
receiver = myOutPort.getReceiver();<br />
receiver.send(sysexMessage, -1);<br />
</code><br />
If you have succeeded in making this work, please let me know. MMJ development seems to have stopped so I&#8217;d kind of want to start using OSXs own stuff&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.teknopipo.nl/archives/677/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Wireshark on Snow Leopard</title>
		<link>http://www.teknopipo.nl/archives/673</link>
		<comments>http://www.teknopipo.nl/archives/673#comments</comments>
		<pubDate>Fri, 16 Apr 2010 10:57:36 +0000</pubDate>
		<dc:creator>teknopipo</dc:creator>
				<category><![CDATA[Telecom]]></category>
		<category><![CDATA[10.6]]></category>
		<category><![CDATA[osx]]></category>
		<category><![CDATA[snow leopard]]></category>
		<category><![CDATA[wireshark]]></category>

		<guid isPermaLink="false">http://www.teknopipo.nl/?p=673</guid>
		<description><![CDATA[Finally fixed a bug that&#8217;s been annoying me for months. I managed to get Wireshark up and running on OSX Snow Leopard &#8211; without any crappy workarounds such as running it inside a virtual XP machine. The video below by dangribbin explains it all. Summarizing the steps: Download and mount Wireshark for 10.5 Leopard Intel [...]]]></description>
			<content:encoded><![CDATA[<p>Finally fixed a bug that&#8217;s been annoying me for months. I managed to get Wireshark up and running on OSX Snow Leopard &#8211; without any crappy workarounds such as running it inside a virtual XP machine. The video below by <em>dangribbin</em> explains it all.</p>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="640" height="385" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube.com/v/IxeHm0BKdwc&amp;hl=en_US&amp;fs=1&amp;" /><param name="allowfullscreen" value="true" /><embed type="application/x-shockwave-flash" width="640" height="385" src="http://www.youtube.com/v/IxeHm0BKdwc&amp;hl=en_US&amp;fs=1&amp;" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<p>Summarizing the steps:</p>
<ol>
<li> Download and mount <a href="http://www.wireshark.org/download.html" target="_blank"><em>Wireshark for 10.5 Leopard Intel</em></a></li>
<li>Drag <em>Wireshark</em> to <em>Applications</em></li>
<li>Open a terminal and type:<br />
<em>defaults write com.apple.finder AppleShowAllFiles  YES<br />
killall Finder<br />
</em>- <em>com.apple.Finder</em> (i.e. Finder with a capital F) did not work for me!<br />
- For more info on <em>defaults </em>type <em>man defaults.</em></li>
<li>Create <em>/usr/local/bin/ </em>if you don&#8217;t already have one<em>.<br />
</em></li>
<li>Drag the <em>Command Line </em>utilities into <em>/usr/local/bin/.</em></li>
<li>Drag <em>ChmodBPF</em> folder to <em>Startup Items.</em></li>
<li>In the terminal type:<em><br />
sudo chown -R root:wheel ChmodBPF</em></li>
<li>Launch Wireshark</li>
<li>Add <em>/usr/share/snmp/mibs/</em> under <em>Edit </em>→<em> Preferences </em>→<em><strong></strong> Name Resolution </em>→<em> SMI (MIB and PIB) paths </em>→<em> Edit </em>→<em> New</em></li>
<li>Reboot, done!</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.teknopipo.nl/archives/673/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Setting up a home audio server</title>
		<link>http://www.teknopipo.nl/archives/129</link>
		<comments>http://www.teknopipo.nl/archives/129#comments</comments>
		<pubDate>Wed, 18 Mar 2009 17:35:16 +0000</pubDate>
		<dc:creator>teknopipo</dc:creator>
				<category><![CDATA[Audio]]></category>
		<category><![CDATA[Telecom]]></category>

		<guid isPermaLink="false">http://www.teknopipo.nl/?p=129</guid>
		<description><![CDATA[Over the years my iTunes library has been growing substantially, and so has my collection of computers and harddisks. As a result, my personal archive had become quite scattered. Documents, photos, videos, mp3s, it was everywhere! In my quest to archive everything to a big harddisk attached to my Ubuntu server, I came up with [...]]]></description>
			<content:encoded><![CDATA[<p>Over the years my iTunes library has been growing               substantially, and so has my collection of computers               and harddisks. As a result, my personal archive had               become quite scattered. Documents, photos, videos,               mp3s, it was everywhere! In my quest to archive               everything to a big harddisk attached to my Ubuntu               server, I came up with the plan to also have a               central music server. That would save a lot of space               on my laptop harddisk. Plus I would be able to listen               to my music wherever I was, in the house or in the               world!</p>
<p>In this article <span id="more-129"></span>I&#8217;ll describe how to setup a home               audio server on Ubuntu. I tried it on kernel               2.6.22-14, but it will probably work similarly on               other systems. The client audioplayer in my setup is               iTunes running on Mac OSX 10.4 (Tiger). There&#8217;s a               number of articles available online, describing how               to do this, but somehow none of them seemed to really               cut the mustard for me. I&#8217;ll start with a short               inventory:</p>
<p>- <a rel="self" href="http://ubuntuforums.org/showthread.php?t=42192">Running an iTunes server on                    Ubuntu</a><br />
- <a rel="self" href="http://www.onlamp.com/pub/wlg/6067">Streaming iTunes from Ubuntu</a><br />
- <a rel="self" href="http://jamiedumbill.com/index.php?page=28">Using Ubuntu to share with Firefly                    (mt-daap)</a><br />
- <a rel="self" href="http://sevitz.com/2005/03/how_to_share_your_music_via_itunes_on_the_net">How to share your music via iTunes on                    the Net</a></p>
<p>After some investigation and hacking, I               arrived at the following setup:</p>
<p><img class="alignnone size-full wp-image-130" title="homeaudio1" src="http://www.teknopipo.nl/wp-content/uploads/2009/03/homeaudio1.gif" alt="homeaudio1" width="450" height="222" /></p>
<p><strong>Step 1: Update and upgrade<br />
</strong>Make sure you got all the relevant               upgrades and updates for your Ubuntu machine, by               typing at a command prompt:</p>
<p><span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">sudo apt-get               update<br />
sudo apt-get upgrade</span><span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal; font-weight: bold;"><br />
</span><br />
<strong>Step 2: Format your external               harddisk</strong><br />
If you&#8217;re a Mac adept like me, you will want to               format your kickass external harddisc to Apple&#8217;s HFS+               filesystem. To do so, attach it to a Mac, open               Applications -&gt; Utilities -&gt; Disk Utility and               Erase the Disk using Volume Format HFS (&#8220;Mac OS               Extended&#8221;). I recommend <em>not</em> to use               journaling. Although it helps recovering your data in               case of a corrupt disk, I found that Ubuntu support               for HFS+ Journaled disks is still a bit shaky.</p>
<p><strong>Step 3: Move your music to central storage<br />
</strong>Now go attach your external disk to               all your computers, move or copy all your mp3s onto               it, and attach the disk to your Ubuntu machine.</p>
<p><strong>Step 4: Install a DAAP server<br />
</strong>iTunes speaks and listens to a               protocol called DAAP (Digital Audio Access Protocol)               for sharing media across a network. By default, DAAP               uses TCP port 3689. The DAAP server is the sofware               that will spit out your audio onto the network. We               will install <a rel="self" href="http://www.fireflymediaserver.org/">Firefly</a> on the Ubuntu machine for                    this purpose. Firefly, or mt-daap as it used to                    be called, requires some additional packages,                    install them by typing the following at a                    command prompt:</p>
<p><span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">sudo apt-get               install howl-utils libhowl-dev libhowl0</span><br />
<span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">sudo apt-get               install mt-daapd</span></p>
<p>Now you&#8217;re ready to start the server with:</p>
<p><span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">sudo mt-daapd               &amp;</span></p>
<p><strong>Step 5: Configure DAAP server<br />
</strong>Open a webbrowser and goto               http://your_ubuntu_machine:3689/<br />
If you installed correctly, the server will prompt               you with an authentication window. By default, don&#8217;t               specify a username and use mt-daapd as password.</p>
<p><img class="alignnone size-full wp-image-131" style="border: 1px solid black;" title="homeaudio2" src="http://www.teknopipo.nl/wp-content/uploads/2009/03/homeaudio2.jpg" alt="homeaudio2" width="450" height="268" /></p>
<p>Go to the <em>Configuration</em> tab and change the               default Admin password. It&#8217;s probably illegal to open               up your music collection online for the whole world               to see, so choose a Music password as well.<br />
Set the Music Folder to a directory on the harddisk               that you just stuffed with your music collection. I               started out with a small test directory first, but if               that works just scan your whole database. To verify               that Firefly actually found all your files, go to a               command prompt and check how many files you&#8217;ve really               got:</p>
<p><span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">find . -type f               | wc -l</span><br />
<strong><br />
</strong>When I was setting things up,               I found that I had to fiddle around with file               permissions and ownership before the Firefly admin               console would see them. <strong></strong></p>
<p><strong></strong><strong>Step 6: Test on local network<br />
</strong>Right now you should already be able               to connect to your music server within your private               network. Open up iTunes and check that a Shared               Playlist is shown:</p>
<p><img class="alignnone size-full wp-image-132" style="border: 1px solid black;" title="homeaudio3" src="http://www.teknopipo.nl/wp-content/uploads/2009/03/homeaudio3.jpg" alt="homeaudio3" width="450" height="186" /></p>
<p><strong>Step                    7: Port forwarding on router<br />
</strong>Go your router&#8217;s admin console and               setup a virtual server for port 3689. All incoming               traffic on port 3689 should be routed to your Ubuntu               machine.<strong></strong></p>
<p><strong>Step 8: Installing rendezvous proxy<br />
</strong>iTunes cannot find your shared               playlist from another network. You need to configure               a proxy on your client machine that will mimic a               shared playlist to iTunes, and connect to your home               network on the other side. You can use the rendezvous               proxy for this. <a rel="self" href="http://ileech.sourceforge.net/index.php?content=RendezvousProxy-Download">Get it here</a> or google for it <img src='http://www.teknopipo.nl/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />                     Download and mount the .dmg file and run the                    application contained in it. You should end up                    with a new icon in the taskbar.</p>
<p><img class="alignnone size-full wp-image-133" style="border: 1px solid black;" title="homeaudio4" src="http://www.teknopipo.nl/wp-content/uploads/2009/03/homeaudio4.jpg" alt="homeaudio4" width="271" height="74" /></p>
<p>Click on it, select                    <em>Preferences&#8230;</em> and then <em>Add                    Host</em>.<br />
<img class="alignnone size-full wp-image-134" style="border: 1px solid black;" title="homeaudio5" src="http://www.teknopipo.nl/wp-content/uploads/2009/03/homeaudio5.jpg" alt="homeaudio5" width="409" height="349" /></p>
<p>Fill in your home IP address and port 3689, type a               dummy host label and a descriptive Service Name, and               select <em>Service Type</em> as shown. <strong></strong></p>
<p><strong>Step 9:Test on remote network<br />
</strong>You&#8217;re all set! Fire up iTunes on your               laptop while lying on a sunny beach far away, using               the WiFi network of the local cocktail bar, and               listen to your favourite Slayer tracks while your               Ubuntu server is streaming from the comfort of your               home <img src='http://www.teknopipo.nl/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /><br />
<strong><br />
</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://www.teknopipo.nl/archives/129/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Introduction to jVoiceBridge</title>
		<link>http://www.teknopipo.nl/archives/94</link>
		<comments>http://www.teknopipo.nl/archives/94#comments</comments>
		<pubDate>Tue, 17 Mar 2009 05:12:53 +0000</pubDate>
		<dc:creator>teknopipo</dc:creator>
				<category><![CDATA[Telecom]]></category>

		<guid isPermaLink="false">http://www.teknopipo.nl/?p=94</guid>
		<description><![CDATA[Introduction The application jVoiceBridge is a software-only audio mixer that handles Voice over IP (VoIP) audio communication and mixing, for tasks such as conference calls, voice chat, speech detection, and audio for 3D virtual environments. Currently it is most commonly known for its use in the Wonderland project, a 3D virtual environment developed by Sun. [...]]]></description>
			<content:encoded><![CDATA[<h3>Introduction</h3>
<p>The application <a rel="external" href="https://jvoicebridge.dev.java.net/" target="_blank">jVoiceBridge</a> is a                    software-only audio mixer that handles Voice                    over IP (VoIP) audio communication and mixing,                    for tasks such as conference calls, voice chat,                    speech detection, and audio for 3D virtual                    environments. Currently it is most commonly                    known for its use in the <a rel="external" href="https://lg3d-wonderland.dev.java.net/" target="_blank">Wonderland</a> project, a 3D                    virtual environment developed by Sun.</p>
<p>In this article <span id="more-94"></span>I will give an introduction to the               design of the jVoiceBridge software. I am not               providing a user manual, nor will I be giving               detailed operating instructions; if you&#8217;re looking               for that information, have a look at the <a rel="external" href="http://wiki.java.net/bin/view/Communications/JVoiceBridge" target="_blank">jVoiceBridge WiKi</a>. Instead,                    I&#8217;ve been reverse engineering the source code                    and I will provide some diagrams and                    explanations which I drew up during my                    exploration. It won&#8217;t cover every detail, but it                    should be enough to a give you a general idea of                    how the code is structured.</p>
<p>Many thanks go out to Joe Provino from Sun for               patiently answering all my questions!</p>
<h3>Important terms and abbreviations</h3>
<table border="0" cellspacing="0" frame="void" rules="groups">
<colgroup>
<col width="150"></col>
<col width="350"></col>
</colgroup>
<tbody>
<tr>
<td align="left" valign="top"><em>Call:</em></td>
<td align="left" valign="top">a communication session                         between jVoiceBridge and a remote party. It                         is identified by a Call id.</td>
</tr>
<tr>
<td align="left" valign="top"><em>CallParticipant:</em></td>
<td align="left" valign="top">A CallParticipant is used to                         hold the parameters for a call.                          There&#8217;s one CallParticipant, one                         CallHandler and one ConferenceMember per                         call. The CallHandler handles the call                         setup and call status.  The                         ConferenceMember deals with the call being                         part of a conference. It has a MemberSender                         and a MemberReceiver.</td>
</tr>
<tr>
<td align="left" valign="top"><em>Conference:</em></td>
<td align="left" valign="top">a group of people talking to                         eachother. jVoiceBridge maintains a                         Conference by receiving data from all                         conferenceMembers, mixing it together, and                         outputting the mix to each member.                         ConferenceMembers may enhance their                         conferencing experience by creating private                         mixes or whispergroups.</td>
</tr>
<tr>
<td align="left" valign="top"><em>ConferenceMember:</em></td>
<td align="left" valign="top">someone participating in a                         conference. A ConferenceMember has a                         receiving part (MemberReceiver) and a                         sending part (MemberSender).</td>
</tr>
<tr>
<td align="left" valign="top"><em>ConferenceSender:</em></td>
<td align="left" valign="top">The job of the conference                         sender is to send a voice data packet to                         each conference member every 20 ms.</td>
</tr>
<tr>
<td align="left" valign="top"><em>ConferenceReceiver:</em></td>
<td align="left" valign="top">The ConferenceReceiver                         receives data from everyone who&#8217;s                         talking.</td>
</tr>
<tr>
<td align="left" valign="top"><em>DtmfSuppression:</em></td>
<td align="left" valign="top">DtmfSuppression means any                         keypresses will be filtered out of the                         conference mix. The static variable                         CallHandler.dtmfDetection defaults to                         true.  If the CallParticipant also has                         dtmfSuppression set to true (the default)                         then when a dtmf key is detected the                         member&#8217;s input buffer is flushed so that                         others won&#8217;t hear the dtmf key.</td>
</tr>
<tr>
<td align="left" valign="top"><em>Private Mix:</em></td>
<td align="left" valign="top">Each call has MixDescriptors                         which describe what audio the call should                         hear. A descriptor has information about                         the source of the audio and how loud and in                         what direction the call should hear the                         audio.<br />
In a simple conference, there&#8217;s a &#8220;common mix&#8221;                     to which the data from all calls in the                     conference are added.  In order to not                     hear yourself when you talk, your own audio                     needs to be subtracted out of the common mix                     when the data is sent to you. So you have a                     descriptor for the common mix with a volume                     level of one and another descriptor for your                     own audio source with a volume level of minus                     1.<br />
But let&#8217;s say you want to raise the volume of                     my audio because I speak too softly. This is                     what we call a private mix.  You would                     need another descriptor with my audio source                     and a volume level of say .2.  It&#8217;s .2                     because my audio is already in the common mix                     at a volume of 1.  So when everything is                     added together, the volume you hear from me                     will be 1.2.<br />
If there are a lot of private mixes, the common                     mix may not make any sense to maintain.                     jVoiceBridge supports this, too.  In that                     case, you only hear audio sources for which you                     have a private mix (i.e. a mix                     descriptor).</td>
</tr>
<tr>
<td align="left" valign="top"><em>Treatment:</em></td>
<td align="left" valign="top">an announcement which is                         played when a certain event occurs e.g.                         when you&#8217;re the first party in a                         conference.</td>
</tr>
<tr>
<td align="left" valign="top"><em>WhisperGroup:</em></td>
<td align="left" valign="top">people in a conference can                         create a WhisperGroup if they want to talk                         in private. Their audio will not be sent to                         the conference.</td>
</tr>
</tbody>
</table>
<h3>Overview</h3>
<p>The following pictures give an               overview of the most important classes and packages               related to handling commands which are received over               the telnet connection.</p>
<p><img class="aligncenter size-full wp-image-95" title="jvoicebridge1" src="http://www.teknopipo.nl/wp-content/uploads/2009/03/jvoicebridge1.png" alt="jvoicebridge1" width="541" height="475" /></p>
<p>The <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">RequestHandler</span> is               the main entry point into jVoiceBridge. As soon as               the bridge accepts a new telnet connection, it               creates a new <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">RequestHandler</span> thread for reading socket input data. The               <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">RequestHandler</span> dispatches the data to the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">RequestParser</span>,               until a newline is received. At that point, the               <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">RequestHandler</span> creates the appropriate <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">CallHandler</span> for               handling the call.<br />
A <em>request</em> is a command, followed by               parameters and separated by colons. The <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">RequestParser</span> distinguishes different types of requests. Some               requests are parsed and handled immediately               (<span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">parseImmediateRequest)</span>,               while others are parsed and executed upon reception               of a newLine (<span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">parseCallParameters</span>).<br />
If the request matches none of the immediate               commands, the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">parseImmediateRequest</span> method returns <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">false</span><em>,</em> and               <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">RequestParser</span> will               just try to parse call parameters from the supplied               input. Call parameters are collected in a               <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">CallParticipant</span> object.<br />
If none of these call parameters match the given               request, finally an attempt is made to parse the               request as a twoparty-call request. If that fails, an               exception is thrown (&#8220;Illegal request&#8221;).               Communication towards the end user is handled by the               <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">RequestHandler</span>&#8216;s               <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">writeToSocket</span> method.</p>
<p>The <a rel="external" href="http://wiki.java.net/bin/view/Communications/JVoiceBridge" target="_blank">jVoiceBridge WiKi</a> provides an                    extensive list of all immediate requests and all                    call parameters. Some requests are related to                    actual call behaviour &#8211; for example the                    <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">createConference</span> or <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">mute</span> requests.                    Others are bridge configuration commands, for                    example <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">defaultSipProxy</span> or <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">rtpTimeout</span>.<br />
To start understanding the design, I recommend to               focus on some important requests. The following               requests are dispatched by the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">RequestParser</span> to               static <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">ConferenceManager</span> methods:<span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;"><br />
</span></p>
<ul class="disc">
<li><span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">createConference</span></li>
<li><span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">createWhisperGroup</span></li>
<li><span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">destroyWhisperGroup</span></li>
<li><span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">endConference</span></li>
<li><span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">removeConference</span></li>
<li>recordConference</li>
<li><span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">playTreatmentToConference</span></li>
</ul>
<p>The following requests are dispatched by the               <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">RequestParser</span> to               static <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">CallHandler</span> methods:</p>
<ul class="disc">
<li><span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">mute</span></li>
<li><span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">muteWhisperGroup</span></li>
<li><span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">muteConference</span></li>
<li><span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">playTreatmentToCall</span></li>
</ul>
<p>The following requests are dispatched by the               <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">RequestParser</span> to a               specific <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">CallHandler</span> instance:</p>
<ul class="disc">
<li><span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">privateMix</span>:                 delegated to the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">ConferenceMember</span> of the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">CallHandler</span> identified by the supplied call id.</li>
<li><span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">removeCallFromWhisperGroup</span>:                 delegated to the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">ConferenceMember</span> of the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">CallHandler</span> of                 the supplied call id.</li>
<li><span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">addCallToWhisperGroup</span>:                 delegated to the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">CallHandler</span> for                 the supplied call id.</li>
<li><span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">whisper</span>:                 delegated to the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">ConferenceMember</span> of the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">CallHandler</span> of                 the supplied call id.</li>
</ul>
<p>The following requests are some examples of               bridge configuration commands:</p>
<ul class="disc">
<li><span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">rtpTimeout</span></li>
<li><span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">sendSipUriToProxy</span></li>
<li><span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">defaultSipProxy</span></li>
<li><span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">voIPGateways</span></li>
</ul>
<h3>An example: starting a new Conference</h3>
<p>I               recommend that you have the jVoiceBridge source code               in front of you while reading this section. I will               use a typical example to walk through the code: the               creation of a new conference. We start by imagining               that a user has started a telnet connection to the               bridge, and entered the following request:</p>
<blockquote><p>$telnet_prompt:&gt; createConference =                 testid:PCM/44100/2</p></blockquote>
<p>No conference with this id exists yet,               so a new <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">ConferenceManager</span> is created and added to the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">ConferenceManager</span>&#8216;s               static list of <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">ConferenceManager</span>s.               Media settings and name are set and <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">ConferenceSender</span> and <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">ConferenceReceiver</span> are created. The conference id is stored in the               <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">CallParticipant</span>.               The following sequence diagram illustrates this               behaviour.</p>
<p><img class="aligncenter size-full wp-image-96" title="jvoicebridge2" src="http://www.teknopipo.nl/wp-content/uploads/2009/03/jvoicebridge2.png" alt="jvoicebridge2" width="545" height="227" /></p>
<p>In case of <em>synchronous mode,</em> all that is               returned to the telnet client is &#8220;<span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">END &#8212; SUCCESS</span>&#8220;. If               <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">synchronousMode</span> is               false, <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">RequestHandler</span> will               only respond to the telnet client when one of its               <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">CallEventListener</span> methods is called.</p>
<blockquote><p>$telnet_prompt:&gt; (newline)</p></blockquote>
<p>The newline will cause the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">RequestHandler</span> to               do a <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">validateAndAdjustParameters</span> first. That will report to the user (among other               things) that no phone number was specified! The user               specifies one by typing:</p>
<blockquote><p>$telnet_prompt&gt; phoneNumber =                 sip:joe@host.com</p></blockquote>
<p>&#8230;followed by:</p>
<blockquote><p>telnet_prompt&gt; (newline)</p></blockquote>
<p><span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">RequestHandler</span> will               determine what to do next, by looking at the               <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">CallParticipant</span>.               Its <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">cp.remoteMediaInfo</span> is still <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">null</span>, <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">cp.migrateCall</span> is               <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">false</span>,               <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">secondPartyNumber</span> was not set (only set for a 2-party call request or a               call migration), so an <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">OutgoingCallHandler</span> is created and started.</p>
<h3>The OutgoingCallHandler</h3>
<p><span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;"><br />
</span>The following               picture shows some important classes which are               involved during creation of a conference.</p>
<p><img class="aligncenter size-full wp-image-97" title="jvoicebridge3" src="http://www.teknopipo.nl/wp-content/uploads/2009/03/jvoicebridge3.png" alt="jvoicebridge3" width="531" height="656" /></p>
<p><span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">OutgoingCallHandler</span> asks the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">ConferenceManager</span> for this <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">CallParticipant</span>&#8216;s               <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">conferenceManager</span> &#8211;               this had just been created. <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">OutgoingCallHandler</span> calls <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">conferenceManager.joinConference(cp)</span>,               upon which the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">conferenceManager</span> sets some audio treatments in the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">CallParticipant</span> and               creates a new <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">ConferenceMember</span> object for this <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">CallParticipant</span>.               The <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">ConferenceMember</span> is               then:</p>
<ul class="disc">
<li>added to the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">conferenceManager</span>&#8216;s                 list of conference members,</li>
<li>added to conferenceManager&#8217;s <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">ConferenceReceiver</span>,                 so it will be registered to a <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">java.nio.DatagramChannel</span>.                 Notice that the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">ConferenceReceiver</span> thread starts as soon as it&#8217;s created.</li>
<li>returned to the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">OutgoingCallHandler</span>.</li>
</ul>
<p>The <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">OutgoingCallHandler</span> maintains a static <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">Vector</span> of active               calls. It adds itself to this <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">Vector</span>, so the               right <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">CallHandler</span> can be               found later when a call is hung up.<br />
The described sequence of events is illustrated in               the following picture:</p>
<p><img class="aligncenter size-full wp-image-98" title="jvoicebridge4" src="http://www.teknopipo.nl/wp-content/uploads/2009/03/jvoicebridge4.png" alt="jvoicebridge4" width="529" height="354" /></p>
<p>The <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">OutgoingCallHandler</span> then examines if we&#8217;d specified any gateways (not in               this example) and calls <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">placeCall()</span>. The               following sequence diagram shows what happens then.</p>
<p><img class="aligncenter size-full wp-image-99" title="jvoicebridge5" src="http://www.teknopipo.nl/wp-content/uploads/2009/03/jvoicebridge5.png" alt="jvoicebridge5" width="534" height="475" /></p>
<p>The <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">Bridge</span>&#8216;s default               protocol is used, so a <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">SipTPCCallAgent</span> (<em>Third Party Call)</em> is created. Upon               construction, the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">SipTPCCallAgent</span> retrieves and remembers the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">MediaInfo</span> from the               <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">OutgoingCallHandler</span>&#8216;s               <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">conferenceManager</span>.               It creates a <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">SipUtil</span>, which in               turn constructs a <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">SdpManager</span> based on               the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">MediaInfo</span> passed in               (see below for more info).<br />
<strong><br />
</strong>Finally, the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">OutgoingCallHandler</span> calls <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">SipTPCCallAgent.initiateCall()</span>;</p>
<p><span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">SipTPCCAllAgent</span> changes to state <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">CallState.INVITED</span>,               and asks the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">OutgoingCallHandler</span> for its <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">memberReceiver</span>&#8216;s               <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">InetSocketAddress</span>.               This address and the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">CallParticipant</span> are               then passed to the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">SipUtil.sendInvite()</span> method. That method returns a <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">clientTransaction</span>,               which the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">SipTPCCallAgent</span> remembers. The <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">SipTPCCallAgent</span> adds itself as a listener for this call id to the               (<a rel="external" href="https://jain-sip.dev.java.net/" target="_blank">Jain</a>) <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">SIPServer</span>.<br />
<strong><em><br />
</em></strong>The <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">SipUtil</span> first               generates the SDP content. This is partially done by               the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">SdpManager</span>, which               in turn gets most of the information it needs from               the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">MediaInfo</span> object.               <strong><br />
</strong><br />
With this SDP, the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">SipUtil</span> then               populates a bunch of SIP headers (from, to ,               requestUri, Via-headers, etc), asks its <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">sipProvider</span> for a               new call id and a new <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">clientTransaction</span>,               and sends the INVITE. The To: field is set to               <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">cp.getPhoneNumber()</span><em>.</em></p>
<h3>The MediaInfo object</h3>
<p>The <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">com.sun.voip.MediaInfo</span> object is basicly a collection of supported <a rel="external" href="http://en.wikipedia.org/wiki/Real-time_Transport_Protocol" target="_blank">RTP</a> settings. It offers a                    static <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">findMediaInfo</span> method which can be used to find RTP settings                    based on a payload byte, or based on encoding,                    sampleRate and number of Channels.</p>
<h3>Adding other parties to the conference</h3>
<p>To add               other parties to the conference, first select the               conference</p>
<blockquote><p>$telnet_prompt&gt;conferenceId = [some_id]</p></blockquote>
<p>Then simply type in the phone number of               the person you&#8217;d like to be added:</p>
<blockquote><p>$telnet_prompt&gt; phoneNumber =                 sip:joe@host.com</p></blockquote>
<p>Complete your request with a newline:</p>
<blockquote><p>$telnet_prompt&gt; (newline)</p></blockquote>
<h3>Receiving, mixing and sending audio</h3>
<p>The               following sequence diagram illustrates the process of               sending and receiving audio in a conference.</p>
<p><img class="aligncenter size-full wp-image-100" title="jvoicebridge6" src="http://www.teknopipo.nl/wp-content/uploads/2009/03/jvoicebridge6.png" alt="jvoicebridge6" width="534" height="285" /></p>
<p>Each conference has a <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">ConferenceReceiver</span> for receiving socket data, which runs in a separate               <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">Thread</span>.               Attached to each socket is a list of <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">MemberReceiver</span>s,               corresponding to the parties in conference. This               mechanism uses <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;"><a rel="external" href="http://en.wikipedia.org/wiki/New_I/O" target="_blank">java.nio</a></span>, each                  <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">selectionKey</span> corresponds to a <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">MemberReceiver</span>.                  When data arrives on the socket, the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">ConferenceReceiver</span> dispatches the data to each <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">memberReceiver&#8217;</span>s                  <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">receive</span>()                  method, depending on the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">selectedKeys</span>.                  Each <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">memberReceiver</span> in turn calls its own <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">receiveMedia</span> method. Eventually the data is stored in                  <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">memberReceiver.currentContribution</span> variable, waiting to be mixed and sent.</p>
<p>The class diagram below shows the aforementioned               classes and their relations.</p>
<p><img class="aligncenter size-full wp-image-101" title="jvoicebridge7" src="http://www.teknopipo.nl/wp-content/uploads/2009/03/jvoicebridge7.png" alt="jvoicebridge7" width="532" height="431" /></p>
<p>The central object for mixing audio is the               <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">MixManager</span>. It               contains an <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">ArrayList</span> of               <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">mixDescriptors</span>,               which can be added and removed by calling               <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">addMix</span> and <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">removeMix</span>. A               <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">ConferenceMember</span> calls <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">mixmanager.addMix()</span> to add itself during its <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">initialize()</span> method. This happens when a call has been established               (by the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">SipTPCCallAgent</span>)               and we know the port at which the member               (<span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">CallParticipant</span>)               listens for data. At that moment, both the               <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">ConferenceMember&#8217;</span>s               <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">MemberSender</span> and               <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">MemberReceiver</span> are               also initialized.</p>
<p>Each conference has a <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">ConferenceSender</span> for sending data &#8211; but read my remark further down               about the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">loneSender</span>. The               <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">ConferenceSender</span> runs as a separate <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">Thread</span> and               continuously calls its own <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">sendDataToConferences()</span> method. When a list of all <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">MemberSender</span>s has               been constructed, the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">ConferenceSender</span> calls each member&#8217;s <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">sendData()</span> method.               That method calls the <strong>essential               method</strong> <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">memberSender.sendData(mixManager.mix())</span><em>,</em> which causes this <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">ConferenceMember&#8217;</span>s               <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">MixManager</span> to               gather all <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">mixDataSources</span>&#8216;               <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">currentContributions</span>,               mix them, after which each <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">memberSender</span> outputs it as an RTP stream to this member&#8217;s socket.</p>
<p>It appears that a member is always talking in some               whisper group.  For a whisper group with a               common mix, a member has a descriptor for the common               mix and a descriptor to subtract out its own data. If               the member wants to adjust the volume of some other               member, then it will have a descriptor for that other               member.<br />
For a whisper group without a common mix, a member               has descriptors for other members it wants to hear.               This is used in <a rel="external" href="http://lg3d-wonderland.dev.java.net/" target="_blank">Project Wonderland</a>, where an                    avatar should only hear others in range. If you                    and I are close enough to each other and not                    near anybody else, we&#8217;d have one descriptor for                    each other and that&#8217;s it.</p>
<h3>Questions and answers</h3>
<p><strong>Q</strong>: Who               owns a conference?<br />
<strong>A</strong>: There&#8217;s no concept of an               owner.  If you don&#8217;t explicitly create a               conference, it will be created when the first call               joins and destroyed when the last call leaves.                When you explicitly create a conference it stays               until someone destroys it.</p>
<p><strong>Q</strong>: Suppose Joe and Yvo are in a               conference with a bunch of other people, and I want               to create a whispergroup for the two of us because we               have some offline business to discuss. I guess I               should use <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">createWhisperGroup(conferenceId,               whisperGroupId)</span> and   <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">addCallToWhisperGroup(whisperGroupId,               callId)</span> telnet commands. But how do I know the               conferenceId and Yvo&#8217;s and Joe&#8217;s call ids?<br />
<strong>A</strong>: If you&#8217;re using telnet commands,               <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">conferenceInfo</span> (or               <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">ci</span>)               will display this information. If you&#8217;re doing this               programatically, you would probably want to specify               the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">callId</span> for each               call and you&#8217;ll have to pick something for the               <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">conferenceId</span> as               well.</p>
<p><strong>Q</strong>: Is SDP renegotiation supported?               Suppose I&#8217;m in a conference but I&#8217;m turning on my               webcam, I&#8217;d like to do a new handshake to renegotiate               SDP because I can now handle video. Or my broadband               connection suddenly deteriorated so i&#8217;d like a lower               samplerate for my audio. Is something like that               possible?<br />
<strong>A</strong>: I don&#8217;t think we ever fully               supported re-INVITE.  With <a rel="external" href="https://lg3d-wonderland.dev.java.net/" target="_blank">project wonderland</a> we have an                    <em>Audio Quality</em> setting.  That                    changes the settings and hangs up the call and                    places the call again.  So we&#8217;re managing                    that at a higher level than the bridge.</p>
<p><strong>Q:</strong> What happens exactly when an               announcement is played to a conference? Is a               treatment &#8220;just another call&#8221; ?<br />
<strong>A:</strong> A treatment is an <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">AudioSource</span> so it               can be used as the audio source in a <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">MixDescriptor</span>. To               play a treatment to a call, the treatment gets added               to the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">ConferenceMember</span>&#8216;s               <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">memberTreatments</span> <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">ArrayList</span>. When the               next treatment is started, a mix descriptor is added               for the member with the treatment as the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">AudioSource</span>. When               the member&#8217;s <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">saveContribution</span> method is called, the current treatment&#8217;s               <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">saveContribution</span> method is called. When it comes time to mix, the mix               manager just goes through all the mix descriptors               like always. When the treatment finishes, the mix               descriptor for the treatment is removed.</p>
<p><strong>Q:</strong> How does the integrated <a rel="external" href="http://www.ietf.org/rfc/rfc3489.txt" target="_blank">STUN</a> server work?<br />
<strong>A:</strong> We modified the NIST SIP Stack so               that it multiplexes the SIP port (usually 5060) with               STUN. If data is received on the SIP Port and the               first short is 0001 (STUN Binding Request), then the               STUN server replies.</p>
<p><strong>Q:</strong> What does <em>call migration</em> mean?<strong><br />
A:</strong> It&#8217;s just a way to transfer a call to               another phone without leaving the conference. If I&#8217;m               at work using my office extension, I can migrate to               my cell phone and people in the conference won&#8217;t               notice except for the change in audio quality.</p>
<h3>Points of improvement and other details</h3>
<p>The               following issues were just some things I noticed               while I was investigating the code. Some of them are               points for improvement:</p>
<ul class="disc">
<li>Some data is actually handled by the                 <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">RequestHandler</span> and <em>not</em> dispatched to the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">RequestParser</span>,                 for example the &#8220;<span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">CANCEL</span>&#8221; request,                 which is dispatched straight to the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">OutgoingCallHandler</span> or a &#8220;<span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">DETACH</span>&#8221; request,                 which just closes the socket.</li>
<li>Some <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">CallHandler</span> methods are static while others are non-static. The                 non-static methods are invoked by e.g. the                 <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">RequestParser</span> after looking up the correct <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">CallHandler</span> instance, based on a call id which was passed as a                 command parameter. Some static methods, however, do                 exactly the same thing, e.g. <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">recordFromMember</span>.</li>
<li>There is no decent exception handling in the                 <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">RequestParser</span> yet. Any exception which occurs while parsing the                 supplied parameters is caught and rethrown as a                 <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">ParseException</span>.                 However, all <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">ParseExceptions</span> are caught on the highest level and ignored, not                 even logged. This is due to the way the parser                 works, it&#8217;s just a fallthrough mechanism trying to                 parse commands as the previous one failed.</li>
<li>The initial INVITE that is sent out by the                 <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">SipUtil</span> contains                 a hardcoded CSeq value of 1.</li>
<li>There is the concept of the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">loneSender</span>, which                 means a single <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">ConferenceSender</span> is used to send data to all members of <em>all                 conferences</em>. Joe: &#8220;<em>We tried having a                 separate sender thread for each conference.                  Then we decided it would be better to have one                 thread set up the work to be done and then fire off                 as many threads as there are processors to do the                 the actual sending.  This is the way we&#8217;ve                 been running.&#8221;</em></li>
<li><span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">SipUtil</span> tries to                 determine the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">remoteAddress</span> from the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">CallParticipant</span> by looking at its <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">phoneNumber</span>.                 However, the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">remoteAddress</span> variable is not used!</li>
<li>The <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">MixManager</span> uses a                 static <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">WhisperGroup.mixData()</span> method for doing the actual mixing of audio, even                 when there aren&#8217;t actually any whispergroups. A bit                 confusing.</li>
<li>I think there is always at least one                 <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">WhisperGroup</span>: the                 <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">conferenceWhisperGroup</span>,                 created when the <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">WGmanager</span> is                 constructed. A <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">WGManager</span> is                 constructed when a <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">ConferenceManager</span> is constructed.</li>
<li>The <span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal;">migrateToBridge</span> request seems to offer cool functionality to                 migrate a call to another jVoiceBridge instance,                 but it may not actually work&#8230;</li>
</ul>
<h3>Points for further study</h3>
<p>If this walkthrough               was useful, as a next step you could try and answer               the following questions. If you have the answers,               please let me know <img src='http://www.teknopipo.nl/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<ul class="disc">
<li>Examine threading. How many threads are                 actually running at any one point in time?</li>
<li>Event handling. Which event listeners have been                 defined, how do they work? Which events can be                 reported and handled inside the bridge?</li>
<li></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.teknopipo.nl/archives/94/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Adding PHP support to SailFin</title>
		<link>http://www.teknopipo.nl/archives/83</link>
		<comments>http://www.teknopipo.nl/archives/83#comments</comments>
		<pubDate>Tue, 17 Mar 2009 05:02:56 +0000</pubDate>
		<dc:creator>teknopipo</dc:creator>
				<category><![CDATA[Telecom]]></category>

		<guid isPermaLink="false">http://www.teknopipo.nl/?p=83</guid>
		<description><![CDATA[Finally it is now a breeze to enable PHP on SailFin. PHP is a server-side scripting language which has quite a large user base in the web development community. PHP code is embedded in HTML and sent to a webserver for interpretation. The webserver therefore needs to run a PHP interpreter. The guys from Caucho [...]]]></description>
			<content:encoded><![CDATA[<p>Finally it is now a breeze to enable PHP on SailFin.             PHP is a server-side scripting language which has quite             a large user base in the web development community. PHP             code is embedded in HTML and sent to a webserver for             interpretation. The webserver therefore needs to run a             PHP interpreter. The guys from <a rel="external" href="http://www.caucho.com/" target="_blank">Caucho Technology</a> have made a                  100% Java implementation of such an interpreter,                  called <a rel="external" href="http://quercus.caucho.com/" target="_blank">Quercus</a>. Quercus is delivered                  as a .war file and as such it can be ran on any                  Java application server &#8211; such as SailFin.</p>
<p>Quercus is <span id="more-83"></span>not only an interpreter, it also offers PHP             extensions allowing you to call server-side Java code             directly from within your PHP script. The Caucho             website offers some <a rel="external" href="http://quercus.caucho.com/quercus-3.1/doc/quercus.xtp" target="_blank">documentation</a> on how to do                  that; this opens interesting possibilities on                  SailFin. You can now use JSR289 functionality                  directly from within PHP. For example, if you&#8217;re                  running a PHP guestbook, you could extend it to                  include SIP dial-out functionality.</p>
<p>To deploy Quercus, <a rel="external" href="http://quercus.caucho.com/" target="_blank">download the latest version</a>,                  open the SailFin admin console, select                  <em>Applications,</em> then <em>Web                  Applications</em>, then <em>Deploy&#8230;</em> and                  point to the Quercus .war file you just                  downloaded. If all goes well, your admin console                  should look something like this:</p>
<p><img class="aligncenter size-full wp-image-88" title="phpsailfin1" src="http://www.teknopipo.nl/wp-content/uploads/2009/03/phpsailfin1.jpg" alt="phpsailfin1" width="509" height="353" /></p>
<p><img src="file:///Users/teknopipo/Library/Caches/TemporaryItems/moz-screenshot.jpg" alt="" /></p>
<p>To verify that your PHP engine             is working, point your browser to the default PHP             script that comes with the Quercus interpreter:             <a rel="external" href="http://localhost:8080/quercus-3.1.6/" target="_blank">http://localhost:8080/quercus-3.1.6/</a> (your HTTP port or Quercus version might of course                be different). You should get the following screen:</p>
<p style="text-align: center;"><img class="aligncenter size-full wp-image-89" title="phpsailfin21" src="http://www.teknopipo.nl/wp-content/uploads/2009/03/phpsailfin21.jpg" alt="phpsailfin21" width="509" height="353" /></p>
<p style="text-align: left;">Now go try out some PHP             applications on your SailFin server; for example, you             could run your own <a rel="external" href="http://www.mediawiki.org/" target="_blank">MediaWiki</a> on your local SailFin                server! To do so, <a rel="external" href="http://www.mediawiki.org/wiki/Manual:Downloading_MediaWiki" target="_blank">download the latest MediaWiki                distribution</a> and unzip it in the Quercus                interpreter root directory (assuming your running                the default out-of-the-box domain called                <em>domain1</em>):</p>
<p style="text-align: center;"><span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 10px; line-height: normal; font-size-adjust: none; font-stretch: normal;">[SailFin             installdir]/domains/domain1/applications/j2ee-modules/quercus-3.1.6/</span></p>
<p style="text-align: left;">It&#8217;s probably a good idea             to create a subdirectory for any PHP applications you             try out, so for example:</p>
<p style="text-align: center;"><span style="font-family: Courier,mono; font-style: normal; font-variant: normal; font-weight: normal; font-size: 10px; line-height: normal; font-size-adjust: none; font-stretch: normal;">[SailFin             installdir]/domains/domain1/applications/j2ee-modules/quercus-3.1.6/wiki/</span></p>
<p style="text-align: left;">And that&#8217;s that, you now             have a PHP wiki running on SailFin. Try it by pointing             your browser to: <a rel="external" href="http://localhost:8080/quercus-3.1.6/wiki/" target="_blank">http://localhost:8080/quercus-3.1.6/wiki/</a></p>
<p>Of course you will need to complete other steps,             depending on the type of PHP application you&#8217;re             developing or trying out. In the case of MediaWiki, you             will need to setup a MySql server and create the             appropriate JDBC objects in SailFin. I might describe             how to do that in a later blog.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.teknopipo.nl/archives/83/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

