FreeSWITCH 1.8
上QQ阅读APP看书,第一时间看更新

Voicemail

The first application we will discuss is the voicemail application. This application is useful to add right after the bridge application as a second option, executed in cases where the call was not completed. We can do this with one of those special variables that we were discussing earlier. Let's look at a version of our last extension that also allows us to leave a voicemail:

<extension name="example 4"> 
<condition field="destination_number" expression="^2000$"> 
<action application="set" 
            data="hangup_after_bridge=true"/> 
<action application="bridge" data="user/2000"/> 
<action application="voicemail" 
            data="default ${domain} 2000"/> 
</condition> 
</extension> 

Here, we see two uses of channel variables. First, we set hangup_after_bridge=true telling the system to hang up once we have have successfully bridged the call to another phone and to disregard the rest of the instructions. We are using the domain variable in brackets prefixed with a dollar sign, ${domain}. This is a special variable that defaults to the auto-configured domain name, which comes from the XML configuration.

In this example, we check if someone is dialing 2000. We then try to bridge the call to the user which endpoint is registered to extension 2000. If the call fails or if there is no answer (for example, if the bridge attempt has failed, so we do not execute the hangup after the bridge), we will continue to the next instruction, which is to execute the voicemail application. We provide the information the application needs to know (for example, which domain the voicemail belongs to) and which extension the voicemail is for, so the application knows how to handle the situation. Next, the voicemail application plays the pre-recorded greeting or generates one using the Say module's interface, which we briefly discussed earlier. It then plays short sound files one after each other to make a voice say something like The person at extension 2 0 0 0 is not available, please leave a message. Next, mod_voicemail prompts you to record a message. As an additional feature, if you are not convinced with your recording, you can listen and re-record it as many times as you wish. Once you finally commit, a FreeSWITCH MESSAGE_WAITING event is fired into the core event system queue, which is picked up by mod_sofia by way of an event consumer, and the event information is translated into SIP-in this case a SIP NOTIFY message that lets the SIP phone know that there is a message waiting. A blinking lamp (Message Waiting Indicator (MWI)) lights upon the receiving phone.

In this example, not only have we seen how to play a greeting, record a message, and transform it into a voicemail for a user, we have also met an important part of the FreeSWITCH core-the event system. The FreeSWITCH event system is not an additional module interface like the previous examples, it is a core engine feature that you can use to bind to named events and react accordingly when an event is received. In other words, throughout the FreeSWITCH core, there are events that are sent and received. Modules can bind to (that is listen for) various events. They can also fire events into the event engine; other modules can listen for those events. You can think of it as similar to other queuing systems such as RabbitMQ (actually, there is a module to interface the internal event system of a FreeSWITCH server with RabbitMQ, so you can integrate it into an enterprise queuing system, and/or having multiple FreeSWITCH servers be parts of the same big, distributed queue). As we discussed, the Sofia SIP module binds to (subscribes to) the event designated for MESSAGE_WAITING information. This allows our mod_voicemail module to interact with mod_sofia without either system having any knowledge about the other's existence. The event is blindly fired by mod_voicemail (fire and forget, in military parlance), intercepted (received, because has subscribed to) by mod_sofia, and translated into the proper SIP message-all courtesy of the event system.

There are several challenges with such a complex system of concatenating sounds when considering all of the possible languages it may need to support, as well as what files to play for the automated messages and how they are strung together. The Say module supplies a nice way to string files together, but it is limited to something specific, such as spelling a word, counting something, or saying a certain date. The way we overcome this is by defining a more complex layer on top of the Say module called Phrase Macros. Phrase Macros are a collection of XML expressions that pull out a list of arguments by matching a regular expression and executing a string of commands. This is very similar to how the XML Dialplan works, only custom-tailored for IVR scenarios. For example, when mod_voicemail asks you to record your message, rather than coding in the string of files to make it say what you want, the code just calls a phrase macro called voicemail_record_message. This arbitrary series of sound bites is defined in the Phrase Macro section in the XML configuration allowing us, the administrators, to edit the phrase without modifying the Voicemail IVR program:

<macro name="voicemail_record_message"> 
<input pattern="^(.*)$"> 
<match> 
<action function= "play-file"  
        data="voicemail/vm-record_message.wav"/> 
</match> 
</input> 
</macro> 

When mod_voicemail executes the voicemail_record_message macro, it first matches the pattern, which, in this case, is to match everything, because this particular macro has no use for input (that is, whatever input you give it, is not used). If the macro did use the input, the pattern matching could be used to play different sound bites based on different input. Once a match is found, the XML match tag is parsed for action tags just like in our Dialplan example. This macro only plays the file vm-record_message.wav, but more complicated macros, like the ones for verifying your recording or telling you how many messages you have in your inbox, may use combinations of various Say actions and play many different audio files. Phrase Macros are discussed in detail in Chapter 6, XML Dialplan, and used extensively in Chapter 8, Lua FreeSWITCH Scripting.

Here too, we can see co-operation between various parts of FreeSWITCH architecture: the phrase system, the audio file, and the Say modules loaded by the core are used together to enable powerful functionalities. The Say modules are written specifically for a particular language or voice within a language. We can programmatically request to say the current time and have it translated into Spanish or Russian sounds by the proper Say module based on input variables. The Phrase Macro system is a great way to put a layer of abstraction into your code, which can be easily tweaked later by system administrators. For example, if we wanted to make a small IVR that asks us to dial a four-digit number, then reads it back and hangs up, we could make one macro called myapp_ask_for_digits and the other called myapp_read_digits. In our code, we would execute these macros by name-the former when it is time to ask for the digits and the later to read back the digits by passing in the value we entered. Once this is in place, a less-experienced individual (for example, a local administrator) could implement the XML files to play the proper sounds. She can use the Say modules to read back the number, and it should all be working in multiple languages with no further coding necessary. Voicemail is just one example of using FreeSWITCH as an application server. There are endless possibilities when we use FreeSWITCH to connect real-time communication with computers.