using System;
namespace AsterNET.FastAGI
{
///
/// The BaseAGIScript provides some convinience methods to make it easier to
/// write custom AGIScripts.
/// Just extend it by your own AGIScripts.
///
public abstract class AGIScript
{
#region Answer()
///
/// Answers the channel.
///
protected internal void Answer()
{
this.Channel.SendCommand(new Command.AnswerCommand());
}
#endregion
#region Hangup()
///
/// Hangs the channel up.
///
protected internal void Hangup()
{
this.Channel.SendCommand(new Command.HangupCommand());
}
#endregion
#region SetAutoHangup
///
/// Cause the channel to automatically hangup at the given number of seconds in the future.
/// 0 disables the autohangup feature.
///
protected internal void SetAutoHangup(int time)
{
this.Channel.SendCommand(new Command.SetAutoHangupCommand(time));
}
#endregion
#region SetCallerId
///
/// Sets the caller id on the current channel.
/// The raw caller id to set, for example "John Doe<1234>".
///
protected internal void SetCallerId(string callerId)
{
this.Channel.SendCommand(new Command.SetCallerIdCommand(callerId));
}
#endregion
#region PlayMusicOnHold()
///
/// Plays music on hold from the default music on hold class.
///
protected internal void PlayMusicOnHold()
{
this.Channel.SendCommand(new Command.SetMusicOnCommand());
}
#endregion
#region PlayMusicOnHold(string musicOnHoldClass)
///
/// Plays music on hold from the given music on hold class.
///
/// the music on hold class to play music from as configures in Asterisk's .
protected internal void PlayMusicOnHold(string musicOnHoldClass)
{
this.Channel.SendCommand(new Command.SetMusicOnCommand(musicOnHoldClass));
}
#endregion
#region StopMusicOnHold()
///
/// Stops playing music on hold.
///
protected internal void StopMusicOnHold()
{
this.Channel.SendCommand(new Command.SetMusicOffCommand());
}
#endregion
#region GetChannelStatus
///
/// Returns the status of the channel.
/// Return values:
///
/// - 0 Channel is down and available
///
- 1 Channel is down, but reserved
///
- 2 Channel is off hook
///
- 3 Digits (or equivalent) have been dialed
///
- 4 Line is ringing
///
- 5 Remote end is ringing
///
- 6 Line is up
///
- 7 Line is busy
///
///
///
/// the status of the channel.
///
protected internal int GetChannelStatus()
{
AGIChannel channel = this.Channel;
channel.SendCommand(new Command.ChannelStatusCommand());
return channel.LastReply.ResultCode;
}
#endregion
#region GetData(string file)
///
/// Plays the given file and waits for the user to enter DTMF digits until he
/// presses '#'. The user may interrupt the streaming by starting to enter
/// digits.
///
/// the name of the file to play
/// a String containing the DTMF the user entered
protected internal string GetData(string file)
{
AGIChannel channel = this.Channel;
channel.SendCommand(new Command.GetDataCommand(file));
return channel.LastReply.GetResult();
}
#endregion
#region GetData(string file, int timeout)
///
/// Plays the given file and waits for the user to enter DTMF digits until he
/// presses '#' or the timeout occurs. The user may interrupt the streaming
/// by starting to enter digits.
///
/// the name of the file to play
/// the timeout in milliseconds to wait for user input.
/// 0 means standard timeout value, -1 means "ludicrous time"
/// (essentially never times out).
/// a String containing the DTMF the user entered
protected internal string GetData(string file, long timeout)
{
AGIChannel channel = this.Channel;
channel.SendCommand(new Command.GetDataCommand(file, timeout));
return channel.LastReply.GetResult();
}
#endregion
#region GetData(string file, int timeout, int maxDigits)
///
/// Plays the given file and waits for the user to enter DTMF digits until he
/// presses '#' or the timeout occurs or the maximum number of digits has
/// been entered. The user may interrupt the streaming by starting to enter
/// digits.
///
/// the name of the file to play
/// the timeout in milliseconds to wait for user input.
/// 0 means standard timeout value, -1 means "ludicrous time"
/// (essentially never times out).
/// the maximum number of digits the user is allowed to enter
/// a String containing the DTMF the user entered
protected internal string GetData(string file, long timeout, int maxDigits)
{
AGIChannel channel = this.Channel;
channel.SendCommand(new Command.GetDataCommand(file, timeout, maxDigits));
return channel.LastReply.GetResult();
}
#endregion
#region GetOption(string file, string escapeDigits)
///
/// Plays the given file, and waits for the user to press one of the given
/// digits. If none of the esacpe digits is pressed while streaming the file
/// it waits for the default timeout of 5 seconds still waiting for the user
/// to press a digit.
///
/// the name of the file to stream, must not include extension.
/// contains the digits that the user is expected to press.
/// the DTMF digit pressed or 0x0 if none was pressed.
protected internal char GetOption(string file, string escapeDigits)
{
AGIChannel channel = this.Channel;
channel.SendCommand(new Command.GetOptionCommand(file, escapeDigits));
return channel.LastReply.ResultCodeAsChar;
}
#endregion
#region GetOption(string file, string escapeDigits, int timeout)
///
/// Plays the given file, and waits for the user to press one of the given
/// digits. If none of the esacpe digits is pressed while streaming the file
/// it waits for the specified timeout still waiting for the user to press a
/// digit.
///
/// the name of the file to stream, must not include extension.
/// contains the digits that the user is expected to press.
/// the timeout in seconds to wait if none of the defined esacpe digits was presses while streaming.
/// the DTMF digit pressed or 0x0 if none was pressed.
protected internal char GetOption(string file, string escapeDigits, int timeout)
{
AGIChannel channel = this.Channel;
channel.SendCommand(new Command.GetOptionCommand(file, escapeDigits, timeout));
return channel.LastReply.ResultCodeAsChar;
}
#endregion
#region Exec(string application)
///
/// Executes the given command.
///
/// the name of the application to execute, for example "Dial".
/// the return code of the application of -2 if the application was not found.
protected internal int Exec(string application)
{
AGIChannel channel = this.Channel;
channel.SendCommand(new Command.ExecCommand(application));
return channel.LastReply.ResultCode;
}
#endregion
#region Exec(string application, string options)
///
/// Executes the given command.
///
/// the name of the application to execute, for example "Dial".
/// the parameters to pass to the application, for example "SIP/123".
/// the return code of the application of -2 if the application was not found.
protected internal int Exec(string application, string options)
{
AGIChannel channel = this.Channel;
channel.SendCommand(new Command.ExecCommand(application, options));
return channel.LastReply.ResultCode;
}
#endregion
#region SetContext
///
/// Sets the context for continuation upon exiting the application.
///
protected internal void SetContext(string context)
{
this.Channel.SendCommand(new Command.SetContextCommand(context));
}
#endregion
#region SetExtension
///
/// Sets the extension for continuation upon exiting the application.
///
protected internal void SetExtension(string extension)
{
this.Channel.SendCommand(new Command.SetExtensionCommand(extension));
}
#endregion
#region SetPriority(int priority)
///
/// Sets the priority for continuation upon exiting the application.
///
protected internal void SetPriority(int priority)
{
this.Channel.SendCommand(new Command.SetPriorityCommand(priority));
}
#endregion
#region SetPriority(string label priority)
///
/// Sets the label for continuation upon exiting the application.
///
protected internal void SetPriority(string label)
{
this.Channel.SendCommand(new Command.SetPriorityCommand(label));
}
#endregion
#region StreamFile(string file)
///
/// Plays the given file.
///
/// name of the file to play.
protected internal void StreamFile(string file)
{
this.Channel.SendCommand(new Command.StreamFileCommand(file));
}
#endregion
#region StreamFile(string file, string escapeDigits)
///
/// Plays the given file and allows the user to escape by pressing one of the given digit.
///
/// name of the file to play.
/// a String containing the DTMF digits that allow the user to escape.
/// the DTMF digit pressed or 0x0 if none was pressed.
protected internal char StreamFile(string file, string escapeDigits)
{
AGIChannel channel = this.Channel;
channel.SendCommand(new Command.StreamFileCommand(file, escapeDigits));
return channel.LastReply.ResultCodeAsChar;
}
#endregion
#region SayDigits(string digits)
///
/// Says the given digit string.
///
/// the digit string to say.
protected internal void SayDigits(string digits)
{
this.Channel.SendCommand(new Command.SayDigitsCommand(digits));
}
#endregion
#region SayDigits(string digits, string escapeDigits)
///
/// Says the given number, returning early if any of the given DTMF number
/// are received on the channel.
///
/// the digit string to say.
/// a String containing the DTMF digits that allow the user to escape.
/// the DTMF digit pressed or 0x0 if none was pressed.
protected internal char SayDigits(string digits, string escapeDigits)
{
AGIChannel channel = this.Channel;
channel.SendCommand(new Command.SayDigitsCommand(digits, escapeDigits));
return channel.LastReply.ResultCodeAsChar;
}
#endregion
#region SayNumber(string number)
///
/// Says the given number.
///
/// the number to say.
protected internal void SayNumber(string number)
{
this.Channel.SendCommand(new Command.SayNumberCommand(number));
}
#endregion
#region SayNumber(string number, string escapeDigits)
///
/// Says the given number, returning early if any of the given DTMF number
/// are received on the channel.
///
/// the number to say.
/// a String containing the DTMF digits that allow the user to escape.
/// the DTMF digit pressed or 0x0 if none was pressed.
protected internal char SayNumber(string number, string escapeDigits)
{
AGIChannel channel = this.Channel;
channel.SendCommand(new Command.SayNumberCommand(number, escapeDigits));
return channel.LastReply.ResultCodeAsChar;
}
#endregion
#region SayPhonetic(string text)
///
/// Says the given character string with phonetics.
///
/// the text to say.
protected internal void SayPhonetic(string text)
{
this.Channel.SendCommand(new Command.SayPhoneticCommand(text));
}
#endregion
#region SayPhonetic(string text, string escapeDigits)
///
/// Says the given character string with phonetics, returning early if any of
/// the given DTMF number are received on the channel.
///
/// the text to say.
/// a String containing the DTMF digits that allow the user to escape.
/// the DTMF digit pressed or 0x0 if none was pressed.
protected internal char SayPhonetic(string text, string escapeDigits)
{
AGIChannel channel = this.Channel;
channel.SendCommand(new Command.SayPhoneticCommand(text, escapeDigits));
return channel.LastReply.ResultCodeAsChar;
}
#endregion
#region SayAlpha(string text)
///
/// Says the given character string.
///
/// the text to say.
protected internal void SayAlpha(string text)
{
this.Channel.SendCommand(new Command.SayAlphaCommand(text));
}
#endregion
#region SayAlpha(string text, string escapeDigits)
///
/// Says the given character string, returning early if any of the given DTMF
/// number are received on the channel.
///
/// the text to say.
/// a String containing the DTMF digits that allow the user to escape.
/// the DTMF digit pressed or 0x0 if none was pressed.
protected internal char SayAlpha(string text, string escapeDigits)
{
AGIChannel channel = this.Channel;
channel.SendCommand(new Command.SayAlphaCommand(text, escapeDigits));
return channel.LastReply.ResultCodeAsChar;
}
#endregion
#region SayTime(long time)
///
/// Says the given time.
///
/// the time to say in seconds since 00:00:00 on January 1, 1970.
protected internal void SayTime(long time)
{
this.Channel.SendCommand(new Command.SayTimeCommand(time));
}
#endregion
#region SayTime(long time, string escapeDigits)
///
/// Says the given time, returning early if any of the given DTMF number are
/// received on the channel.
///
/// the time to say in seconds since 00:00:00 on January 1, 1970.
/// a String containing the DTMF digits that allow the user to escape.
/// the DTMF digit pressed or 0x0 if none was pressed.
protected internal char SayTime(long time, string escapeDigits)
{
AGIChannel channel = this.Channel;
channel.SendCommand(new Command.SayTimeCommand(time, escapeDigits));
return channel.LastReply.ResultCodeAsChar;
}
#endregion
#region GetVariable(string name)
///
/// Returns the value of the given channel variable.
///
/// the name of the variable to retrieve.
/// the value of the given variable or null if not set.
protected internal string GetVariable(string name)
{
AGIChannel channel = this.Channel;
channel.SendCommand(new Command.GetVariableCommand(name));
if (channel.LastReply.ResultCode != 1)
return null;
return channel.LastReply.Extra;
}
#endregion
#region SetVariable(string name, string value_Renamed)
///
/// Sets the value of the given channel variable to a new value.
///
/// the name of the variable to retrieve.
/// the new value to set.
protected internal void SetVariable(string name, string val)
{
this.Channel.SendCommand(new Command.SetVariableCommand(name, val));
}
#endregion
#region WaitForDigit(int timeout)
///
/// Waits up to 'timeout' milliseconds to receive a DTMF digit.
///
/// timeout the milliseconds to wait for the channel to receive a DTMF digit, -1 will wait forever.
/// the DTMF digit pressed or 0x0 if none was pressed.
protected internal char WaitForDigit(int timeout)
{
AGIChannel channel = this.Channel;
channel.SendCommand(new Command.WaitForDigitCommand(timeout));
return channel.LastReply.ResultCodeAsChar;
}
#endregion
#region GetFullVariable(string name)
///
/// Returns the value of the current channel variable, unlike getVariable()
/// this method understands complex variable names and builtin variables.
/// Available since Asterisk 1.2.
///
/// the name of the variable to retrieve.
/// the value of the given variable or null if not et.
protected internal string GetFullVariable(string name)
{
AGIChannel channel = this.Channel;
channel.SendCommand(new Command.GetFullVariableCommand(name));
if (channel.LastReply.ResultCode != 1)
return null;
return channel.LastReply.Extra;
}
#endregion
#region GetFullVariable(string name, string channel)
///
/// Returns the value of the given channel variable.
/// Available since Asterisk 1.2.
///
/// the name of the variable to retrieve.
/// the name of the channel.
/// the value of the given variable or null if not set.
protected internal string GetFullVariable(string name, string channelName)
{
AGIChannel channel = this.Channel;
channel.SendCommand(new Command.GetFullVariableCommand(name, channelName));
if (channel.LastReply.ResultCode != 1)
return null;
return channel.LastReply.Extra;
}
#endregion
#region SayDateTime(...)
///
/// Says the given time.
/// Available since Asterisk 1.2.
///
/// the time to say in seconds elapsed since 00:00:00 on January 1, 1970, Coordinated Universal Time (UTC)
protected internal void SayDateTime(long time)
{
this.Channel.SendCommand(new Command.SayDateTimeCommand(time));
}
///
/// Says the given time and allows interruption by one of the given escape digits.
/// Available since Asterisk 1.2.
///
/// the time to say in seconds elapsed since 00:00:00 on January 1, 1970, Coordinated Universal Time (UTC)
/// the digits that allow the user to interrupt this command or null for none.
/// the DTMF digit pressed or 0x0 if none was pressed.
protected internal char SayDateTime(long time, string escapeDigits)
{
AGIChannel channel = this.Channel;
channel.SendCommand(new Command.SayDateTimeCommand(time, escapeDigits));
return channel.LastReply.ResultCodeAsChar;
}
///
/// Says the given time in the given format and allows interruption by one of the given escape digits.
/// Available since Asterisk 1.2.
///
/// the time to say in seconds elapsed since 00:00:00 on January 1, 1970, Coordinated Universal Time (UTC)
/// the digits that allow the user to interrupt this command or null for none.
/// the format the time should be said in
/// the DTMF digit pressed or 0x0 if none was pressed.
protected internal char SayDateTime(long time, string escapeDigits, string format)
{
AGIChannel channel = this.Channel;
channel.SendCommand(new Command.SayDateTimeCommand(time, escapeDigits, format));
return channel.LastReply.ResultCodeAsChar;
}
///
/// Says the given time in the given format and timezone and allows interruption by one of the given escape digits.
/// Available since Asterisk 1.2.
///
/// the time to say in seconds elapsed since 00:00:00 on January 1, 1970, Coordinated Universal Time (UTC)
/// the digits that allow the user to interrupt this command or null for none.
/// the format the time should be said in
/// the timezone to use when saying the time, for example "UTC" or "Europe/Berlin".
/// the DTMF digit pressed or 0x0 if none was pressed.
protected internal char SayDateTime(long time, string escapeDigits, string format, string timezone)
{
AGIChannel channel = this.Channel;
channel.SendCommand(new Command.SayDateTimeCommand(time, escapeDigits, format, timezone));
return channel.LastReply.ResultCodeAsChar;
}
#endregion
#region DatabaseGet(string family, string key)
///
/// Retrieves an entry in the Asterisk database for a given family and key.
///
/// the family of the entry to retrieve.
/// key the key of the entry to retrieve.
/// the value of the given family and key or null if there is no such value.
protected internal string DatabaseGet(string family, string key)
{
AGIChannel channel = this.Channel;
channel.SendCommand(new Command.DatabaseGetCommand(family, key));
if (channel.LastReply.ResultCode != 1)
return null;
return channel.LastReply.Extra;
}
#endregion
#region DatabasePut(string family, string key, string value)
///
/// Adds or updates an entry in the Asterisk database for a given family, key and value.
///
/// the family of the entry to add or update.
/// the key of the entry to add or update.
/// the new value of the entry.
protected internal void DatabasePut(string family, string key, string value)
{
this.Channel.SendCommand(new Command.DatabasePutCommand(family, key, value));
}
#endregion
#region DatabaseDel(string family, string key)
///
/// Deletes an entry in the Asterisk database for a given family and key.
///
/// the family of the entry to delete.
/// the key of the entry to delete.
protected internal void DatabaseDel(string family, string key)
{
this.Channel.SendCommand(new Command.DatabaseDelCommand(family, key));
}
#endregion
#region DatabaseDelTree(String family)
///
/// Deletes a whole family of entries in the Asterisk database.
///
/// the family to delete.
protected internal void DatabaseDelTree(string family)
{
this.Channel.SendCommand(new Command.DatabaseDelTreeCommand(family));
}
#endregion
#region DatabaseDelTree(string family, string keytree)
///
/// Deletes all entries of a given family in the Asterisk database that have a key that starts with a given prefix.
///
/// the family of the entries to delete.
/// the prefix of the keys of the entries to delete.
protected internal void DatabaseDelTree(string family, string keytree)
{
this.Channel.SendCommand(new Command.DatabaseDelTreeCommand(family, keytree));
}
#endregion
#region Verbose(string message, int level)
///
/// Sends a message to the Asterisk console via the verbose message system.
///
/// the message to send
/// the verbosity level to use. Must be in [1..4]
public void Verbose(string message, int level)
{
this.Channel.SendCommand(new Command.VerboseCommand(message, level));
}
#endregion
#region RecordFile(...)
///
/// Record to a file until a given dtmf digit in the sequence is received.
/// Returns -1 on hangup or error.
/// The format will specify what kind of file will be recorded. The timeout is
/// the maximum record time in milliseconds, or -1 for no timeout. Offset samples
/// is optional, and if provided will seek to the offset without exceeding the
/// end of the file. "maxSilence" is the number of seconds of maxSilence allowed
/// before the function returns despite the lack of dtmf digits or reaching
/// timeout.
///
/// the name of the file to stream, must not include extension.
/// the format of the file to be recorded, for example "wav".
/// contains the digits that allow the user to end recording.
/// the maximum record time in milliseconds, or -1 for no timeout.
/// result code
protected internal int RecordFile(string file, string format, string escapeDigits, int timeout)
{
AGIChannel channel = this.Channel;
channel.SendCommand(new Command.RecordFileCommand(file, format, escapeDigits, timeout));
return channel.LastReply.ResultCode;
}
///
/// Record to a file until a given dtmf digit in the sequence is received.
/// Returns -1 on hangup or error.
/// The format will specify what kind of file will be recorded. The timeout is
/// the maximum record time in milliseconds, or -1 for no timeout. Offset samples
/// is optional, and if provided will seek to the offset without exceeding the
/// end of the file. "maxSilence" is the number of seconds of maxSilence allowed
/// before the function returns despite the lack of dtmf digits or reaching
/// timeout.
///
/// the name of the file to stream, must not include extension.
/// the format of the file to be recorded, for example "wav".
/// contains the digits that allow the user to end recording.
/// the maximum record time in milliseconds, or -1 for no timeout.
/// the offset samples to skip.
/// true if a beep should be played before recording.
/// The amount of silence (in seconds) to allow before returning despite the lack of dtmf digits or reaching timeout.
/// result code
protected internal int RecordFile(string file, string format, string escapeDigits, int timeout, int offset, bool beep, int maxSilence)
{
AGIChannel channel = this.Channel;
channel.SendCommand(new Command.RecordFileCommand(file, format, escapeDigits, timeout, offset, beep, maxSilence));
return channel.LastReply.ResultCode;
}
#endregion
#region ControlStreamFile(...)
///
/// Plays the given file, allowing playback to be interrupted by the given
/// digits, if any, and allows the listner to control the stream.
/// If offset is provided then the audio will seek to sample offset before play
/// starts.
/// Returns 0 if playback completes without a digit being pressed, or the ASCII
/// numerical value of the digit if one was pressed, or -1 on error or if the
/// channel was disconnected.
/// Remember, the file extension must not be included in the filename.
/// Available since Asterisk 1.2
///
///
/// the name of the file to stream, must not include extension.
/// result code
protected internal int ControlStreamFile(string file)
{
AGIChannel channel = this.Channel;
channel.SendCommand(new Command.ControlStreamFileCommand(file));
return channel.LastReply.ResultCode;
}
///
/// Plays the given file, allowing playback to be interrupted by the given
/// digits, if any, and allows the listner to control the stream.
/// If offset is provided then the audio will seek to sample offset before play
/// starts.
/// Returns 0 if playback completes without a digit being pressed, or the ASCII
/// numerical value of the digit if one was pressed, or -1 on error or if the
/// channel was disconnected.
/// Remember, the file extension must not be included in the filename.
/// Available since Asterisk 1.2
///
///
/// the name of the file to stream, must not include extension.
/// contains the digits that allow the user to interrupt this command.
/// result code
protected internal int ControlStreamFile(string file, string escapeDigits)
{
AGIChannel channel = this.Channel;
channel.SendCommand(new Command.ControlStreamFileCommand(file, escapeDigits));
return channel.LastReply.ResultCode;
}
///
/// Plays the given file, allowing playback to be interrupted by the given
/// digits, if any, and allows the listner to control the stream.
/// If offset is provided then the audio will seek to sample offset before play
/// starts.
/// Returns 0 if playback completes without a digit being pressed, or the ASCII
/// numerical value of the digit if one was pressed, or -1 on error or if the
/// channel was disconnected.
/// Remember, the file extension must not be included in the filename.
/// Available since Asterisk 1.2
///
///
/// the name of the file to stream, must not include extension.
/// contains the digits that allow the user to interrupt this command.
/// the offset samples to skip before streaming.
/// result code
protected internal int ControlStreamFile(string file, string escapeDigits, int offset)
{
AGIChannel channel = this.Channel;
channel.SendCommand(new Command.ControlStreamFileCommand(file, escapeDigits, offset));
return channel.LastReply.ResultCode;
}
///
/// Plays the given file, allowing playback to be interrupted by the given
/// digits, if any, and allows the listner to control the stream.
/// If offset is provided then the audio will seek to sample offset before play
/// starts.
/// Returns 0 if playback completes without a digit being pressed, or the ASCII
/// numerical value of the digit if one was pressed, or -1 on error or if the
/// channel was disconnected.
/// Remember, the file extension must not be included in the filename.
/// Available since Asterisk 1.2
///
///
/// the name of the file to stream, must not include extension.
/// contains the digits that allow the user to interrupt this command.
/// the offset samples to skip before streaming.
/// the digit for fast forward.
/// the digit for rewind.
/// the digit for pause and unpause.
/// result code
protected internal int ControlStreamFile(string file, string escapeDigits, int offset, string forwardDigit, string rewindDigit, string pauseDigit)
{
AGIChannel channel = this.Channel;
channel.SendCommand(new Command.ControlStreamFileCommand(file, escapeDigits, offset, forwardDigit, rewindDigit, pauseDigit));
return channel.LastReply.ResultCode;
}
#endregion
#region SendCommand(Command.AGICommand command)
///
/// Sends the given command to the channel attached to the current thread.
///
/// the command to send to Asterisk
/// the reply received from Asterisk
/// AGIException if the command could not be processed properly
private AGIReply SendCommand(Command.AGICommand command)
{
return this.Channel.SendCommand(command);
}
#endregion
#region Channel
protected internal AGIChannel Channel
{
get
{
AGIChannel channel = AGIConnectionHandler.Channel;
if (channel == null)
throw new SystemException("Trying to send command from an invalid thread");
return channel;
}
}
#endregion
#region Service(AGIRequest param1, AGIChannel param2);
public abstract void Service(AGIRequest param1, AGIChannel param2);
#endregion
}
}