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: /// /// ///
/// 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 } }