PHP AGI Documentation

1. Introduction

PHP AGI (Asterisk Gateway Interface) is a powerful library that allows PHP scripts to interact with Asterisk, the open-source PBX system. This documentation provides detailed information on using the PHP AGI library to create dynamic Asterisk dialplan applications.

PHP AGI provides two main classes:

  • AGI: For creating interactive voice response (IVR) applications
  • AGI_AsteriskManager: For administrative interaction with the Asterisk Manager Interface

This library allows you to create sophisticated telephony applications such as:

  • Interactive voice menus
  • Call routing systems
  • Voicemail systems
  • Call queues
  • Custom conferencing solutions
  • And much more

2. Basic Concepts

PHP AGI scripts are typically invoked by Asterisk when a call reaches a specific point in the dialplan. The script then takes control of the call flow, allowing dynamic interaction with the caller.

A typical PHP AGI script follows this structure:


answer();

// Your application logic here

$agi->hangup();
?>
                

3. AGI Class Reference

Core Methods

Constructor


$agi = new AGI($config=NULL, $optconfig=array(), $socket=NULL);
                    

Example:


$agi = new AGI(); // Use default config
                    

answer()

Answers the channel if not already answered.

Example:


$agi->answer();
                    

hangup($channel='')

Hangs up the specified channel or current channel if none specified.

Example:


$agi->hangup(); // Hang up current channel
                    

Audio Playback

stream_file($filename, $escape_digits='', $offset=0)

Plays an audio file to the caller, returning if any escape digit is pressed.

Example:


$result = $agi->stream_file('welcome', '123'); // Play welcome.gsm, allow 1, 2, 3 to interrupt
if($result['result'] > 0) {
    $digit = chr($result['result']);
    echo "User pressed: $digit";
}
                    

say_digits($digits, $escape_digits='')

Says the given digit string.

Example:


$agi->say_digits('12345'); // Will say "one two three four five"
                    

say_number($number, $escape_digits='')

Says the given number.

Example:


$agi->say_number('1234'); // Will say "one thousand two hundred thirty four"
                    

say_time($time=NULL, $escape_digits='')

Says the given time.

Example:


$agi->say_time(time()); // Says current time
                    

text2wav($text, $escape_digits='', $frequency=8000)

Uses festival to convert text to speech.

Example:


$agi->text2wav('Welcome to our system. Please press a key.', '12345');
                    

User Input

get_data($filename, $timeout=NULL, $max_digits=NULL)

Plays a file and gets digits from the user.

Example:


$result = $agi->get_data('enter-account-number', 5000, 10); // 5 second timeout, max 10 digits
$account = $result['result'];
                    

wait_for_digit($timeout=-1)

Waits for a DTMF digit.

Example:


$result = $agi->wait_for_digit(3000); // Wait 3 seconds for a digit
if($result['result'] > 0) {
    $digit = chr($result['result']);
    echo "User pressed: $digit";
}
                    

Variables

get_variable($variable)

Gets the value of a channel variable.

Example:


$result = $agi->get_variable('CALLERID(num)');
$callerid = $result['data'];
                    

get_full_variable($variable)

Gets the value of a variable with variable substitution.

Example:


$result = $agi->get_full_variable('${CHANNEL}');
$channel = $result['data'];
                    

set_variable($variable, $value)

Sets a channel variable.

Example:


$agi->set_variable('CUSTOM_VAR', 'Hello World');
                    

Call Control

exec($application, $options = '')

Executes an Asterisk application.

Example:


$agi->exec('Dial', 'SIP/1234,30,tT'); // Dial extension 1234 with a 30 second timeout
                    

channel_status($channel='')

Gets the status of a channel.

Example:


$result = $agi->channel_status();
echo "Channel status: {$result['data']}";
                    

set_context($context)

Sets the context for call continuation.

Example:


$agi->set_context('another-menu');
                    

set_extension($extension)

Sets the extension for call continuation.

Example:


$agi->set_extension('s');
                    

set_priority($priority)

Sets the priority for call continuation.

Example:


$agi->set_priority(1);
                    

Database Access

database_get($family, $key)

Gets a value from the Asterisk database.

Example:


$result = $agi->database_get('users', 'john');
$john_data = $result['data'];
                    

database_put($family, $key, $value)

Stores a value in the Asterisk database.

Example:


$agi->database_put('users', 'john', 'active');
                    

database_del($family, $key)

Deletes a key from the Asterisk database.

Example:


$agi->database_del('users', 'john');
                    

database_deltree($family, $keytree='')

Deletes a family or keytree from the Asterisk database.

Example:


$agi->database_deltree('users'); // Delete all users
                    

4. AsteriskManager Class Reference

Connection Methods

Constructor


$manager = new AGI_AsteriskManager($config=NULL, $optconfig=array());
                    

Example:


$manager = new AGI_AsteriskManager();
                    

connect($server=NULL, $username=NULL, $secret=NULL, $events='on')

Connects to the Asterisk Manager Interface.

Example:


$manager->connect('localhost', 'admin', 'password');
                    

disconnect()

Disconnects from the Asterisk Manager Interface.

Example:


$manager->disconnect();
                    

Event Handling

add_event_handler($event, $callback)

Adds an event handler for a specified event type.

Example:


function handle_hangup($event, $parameters, $server, $port) {
    echo "Call on {$parameters['Channel']} was hung up\n";
}

$manager->add_event_handler('Hangup', 'handle_hangup');
                    

5. AMI Actions Reference

The Asterisk Manager Interface provides numerous actions for managing an Asterisk server. Here's a comprehensive list of the most commonly used actions supported by the AGI_AsteriskManager class:

Call Management

AbsoluteTimeout($channel, $timeout)

Sets the maximum duration of a call.


$manager->AbsoluteTimeout('SIP/1001-00000001', 300); // Limit call to 5 minutes
                    

Hangup($channel)

Hangs up a specified channel.


$manager->Hangup('SIP/1001-00000001');
                    

Originate($params)

Initiates a new call.


$params = array(
    'Channel' => 'SIP/1001',
    'Context' => 'default',
    'Exten' => '1234',
    'Priority' => 1,
    'CallerID' => 'Test <1234>',
    'Timeout' => 30000
);
$manager->Originate($params);
                    

Redirect($channel, $extrachannel, $exten, $context, $priority)

Redirects a channel to a new extension.


$manager->Redirect('SIP/1001-00000001', '', '1000', 'default', 1);
                    

Monitor($channel, $file=NULL, $format=NULL, $mix=NULL)

Starts recording a channel.


$manager->Monitor('SIP/1001-00000001', 'recording', 'wav', true);
                    

StopMonitor($channel)

Stops recording a channel.


$manager->StopMonitor('SIP/1001-00000001');
                    

Channel Variables

GetVar($channel, $variable, $actionid=NULL)

Gets the value of a channel variable.


$result = $manager->GetVar('SIP/1001-00000001', 'CALLERID(num)');
                    

SetVar($channel, $variable, $value)

Sets a channel variable.


$manager->SetVar('SIP/1001-00000001', 'CUSTOM_VAR', 'Hello World');
                    

Queues

Queues()

Lists all queues.


$queues = $manager->Queues();
                    

QueueStatus($actionid=NULL)

Gets the status of all queues.


$status = $manager->QueueStatus();
                    

QueueAdd($queue, $interface, $penalty=0)

Adds an interface to a queue.


$manager->QueueAdd('support', 'SIP/1001', 2);
                    

QueueRemove($queue, $interface)

Removes an interface from a queue.


$manager->QueueRemove('support', 'SIP/1001');
                    

Conference Management

ConfbridgeList($conference)

Lists participants in a conference.


$participants = $manager->ConfbridgeList('1234');
                    

ConfbridgeKick($conference, $channel)

Kicks a participant from a conference.


$manager->ConfbridgeKick('1234', 'SIP/1001-00000001');
                    

ConfbridgeMute($conference, $channel)

Mutes a participant in a conference.


$manager->ConfbridgeMute('1234', 'SIP/1001-00000001');
                    

ConfbridgeUnmute($conference, $channel)

Unmutes a participant in a conference.


$manager->ConfbridgeUnmute('1234', 'SIP/1001-00000001');
                    

ConfbridgeStartRecord($conference, $recordFile)

Starts recording a conference.


$manager->ConfbridgeStartRecord('1234', '/var/recordings/conference-1234.wav');
                    

ConfbridgeStopRecord($conference)

Stops recording a conference.


$manager->ConfbridgeStopRecord('1234');
                    

ConfbridgeLock($conference)

Locks a conference.


$manager->ConfbridgeLock('1234');
                    

ConfbridgeUnlock($conference)

Unlocks a conference.


$manager->ConfbridgeUnlock('1234');
                    

MeetMe Conference Management

MeetmeList($conference)

Lists participants in a MeetMe conference.


$participants = $manager->MeetmeList('1234');
                    

MeetmeMute($meetme, $usernum)

Mutes a MeetMe conference participant.


$manager->MeetmeMute('1234', '1');
                    

MeetmeUnmute($meetme, $usernum)

Unmutes a MeetMe conference participant.


$manager->MeetmeUnmute('1234', '1');
                    

SIP Management

SIPpeers()

Lists SIP peers.


$peers = $manager->SIPpeers();
                    

System Commands

Command($command, $actionid=NULL)

Executes an Asterisk CLI command.


$result = $manager->Command('core show channels');
echo $result['data'];
                    

Reload($module=NULL, $actionid=NULL)

Reloads Asterisk or a specific module.


$manager->Reload(); // Reload all of Asterisk
$manager->Reload('chan_sip.so'); // Reload just the SIP channel driver
                    

Database Management

database_show($family='')

Shows all entries in the Asterisk database.


$db = $manager->database_show(); // All entries
$users = $manager->database_show('users'); // Just users family
                    

database_put($family, $key, $value)

Adds an entry to the Asterisk database.


$manager->database_put('users', 'john', 'active');
                    

database_get($family, $key)

Gets an entry from the Asterisk database.


$status = $manager->database_get('users', 'john');
                    

database_del($family, $key)

Deletes an entry from the Asterisk database.


$manager->database_del('users', 'john');
                    

database_deltree($family)

Deletes a family from the Asterisk database.


$manager->database_deltree('users');
                    

Agent Management

Agents()

Lists all agents.


$agents = $manager->Agents();
                    

AgentLogoff($agent, $soft)

Logs off an agent.


$manager->AgentLogoff('1001', true); // Soft logout - doesn't hang up active calls
                    

Other Actions

Events($eventmask)

Controls which events are sent to the manager connection.


$manager->Events('call'); // Only receive call-related events
$manager->Events('off'); // Turn off events
$manager->Events('on'); // Receive all events
                    

Ping()

Pings the Asterisk server.


$response = $manager->Ping();
                    

MailboxCount($mailbox, $actionid=NULL)

Checks mailbox message count.


$count = $manager->MailboxCount('1001@default');
                    

MailboxStatus($mailbox, $actionid=NULL)

Checks mailbox status.


$status = $manager->MailboxStatus('1001@default');
                    

6. AMI Events Reference

The Asterisk Manager Interface generates numerous events that your application can handle. Here's a list of common events:

Call Events

Newchannel

Triggered when a new channel is created.


function handle_newchannel($event, $parameters, $server, $port) {
    echo "New channel created: {$parameters['Channel']} for {$parameters['CallerIDNum']}\n";
}
$manager->add_event_handler('Newchannel', 'handle_newchannel');
                    

Hangup

Triggered when a channel is hung up.


function handle_hangup($event, $parameters, $server, $port) {
    echo "Channel hung up: {$parameters['Channel']} with cause: {$parameters['Cause']}\n";
}
$manager->add_event_handler('Hangup', 'handle_hangup');
                    

Dial

Triggered when a dial starts.


function handle_dial($event, $parameters, $server, $port) {
    echo "Dialing from {$parameters['Channel']} to {$parameters['Destination']}\n";
}
$manager->add_event_handler('Dial', 'handle_dial');
                    

Bridge

Triggered when two channels are bridged.


function handle_bridge($event, $parameters, $server, $port) {
    echo "Channels bridged: {$parameters['Channel1']} and {$parameters['Channel2']}\n";
}
$manager->add_event_handler('Bridge', 'handle_bridge');
                    

Unbridge

Triggered when two channels are unbridged.


function handle_unbridge($event, $parameters, $server, $port) {
    echo "Channels unbridged: {$parameters['Channel1']} and {$parameters['Channel2']}\n";
}
$manager->add_event_handler('Unbridge', 'handle_unbridge');
                    

Queue Events

QueueMemberStatus

Triggered when a queue member's status changes.


function handle_queuememberstatus($event, $parameters, $server, $port) {
    echo "Queue member {$parameters['MemberName']} status changed to: {$parameters['Status']}\n";
}
$manager->add_event_handler('QueueMemberStatus', 'handle_queuememberstatus');
                    

QueueMemberAdded

Triggered when a queue member is added.


function handle_queuememberadded($event, $parameters, $server, $port) {
    echo "Queue member {$parameters['MemberName']} added to queue: {$parameters['Queue']}\n";
}
$manager->add_event_handler('QueueMemberAdded', 'handle_queuememberadded');
                    

QueueMemberRemoved

Triggered when a queue member is removed.


function handle_queuememberremoved($event, $parameters, $server, $port) {
    echo "Queue member {$parameters['MemberName']} removed from queue: {$parameters['Queue']}\n";
}
$manager->add_event_handler('QueueMemberRemoved', 'handle_queuememberremoved');
                    

QueueCallerJoin

Triggered when a caller joins a queue.


function handle_queuecallerjoin($event, $parameters, $server, $port) {
    echo "Caller {$parameters['CallerIDNum']} joined queue: {$parameters['Queue']}\n";
}
$manager->add_event_handler('QueueCallerJoin', 'handle_queuecallerjoin');
                    

QueueCallerLeave

Triggered when a caller leaves a queue.


function handle_queuecallerleave($event, $parameters, $server, $port) {
    echo "Caller {$parameters['CallerIDNum']} left queue: {$parameters['Queue']}\n";
}
$manager->add_event_handler('QueueCallerLeave', 'handle_queuecallerleave');
                    

Conference Events

ConfbridgeJoin

Triggered when a participant joins a conference.


function handle_confbridgejoin($event, $parameters, $server, $port) {
    echo "User {$parameters['CallerIDNum']} joined conference: {$parameters['Conference']}\n";
}
$manager->add_event_handler('ConfbridgeJoin', 'handle_confbridgejoin');
                    

ConfbridgeLeave

Triggered when a participant leaves a conference.


function handle_confbridgeleave($event, $parameters, $server, $port) {
    echo "User {$parameters['CallerIDNum']} left conference: {$parameters['Conference']}\n";
}
$manager->add_event_handler('ConfbridgeLeave', 'handle_confbridgeleave');
                    

ConfbridgeMute

Triggered when a participant is muted.


function handle_confbridgemute($event, $parameters, $server, $port) {
    echo "User {$parameters['CallerIDNum']} was muted in conference: {$parameters['Conference']}\n";
}
$manager->add_event_handler('ConfbridgeMute', 'handle_confbridgemute');
                    

ConfbridgeUnmute

Triggered when a participant is unmuted.


function handle_confbridgeunmute($event, $parameters, $server, $port) {
    echo "User {$parameters['CallerIDNum']} was unmuted in conference: {$parameters['Conference']}\n";
}
$manager->add_event_handler('ConfbridgeUnmute', 'handle_confbridgeunmute');
                    

System Events

Reload

Triggered when Asterisk is reloaded.


function handle_reload($event, $parameters, $server, $port) {
    echo "Asterisk reloaded\n";
}
$manager->add_event_handler('Reload', 'handle_reload');
                    

Shutdown

Triggered when Asterisk is shutting down.


function handle_shutdown($event, $parameters, $server, $port) {
    echo "Asterisk shutting down\n";
}
$manager->add_event_handler('Shutdown', 'handle_shutdown');
                    

Registry

Triggered when a trunk registers or unregisters.


function handle_registry($event, $parameters, $server, $port) {
    echo "Registry: {$parameters['Channel']} - {$parameters['Status']}\n";
}
$manager->add_event_handler('Registry', 'handle_registry');
                    

Monitoring All Events

To monitor all events, you can use the '*' wildcard:


function handle_all_events($event, $parameters, $server, $port) {
    echo "Event: $event\n";
    foreach($parameters as $key => $value) {
        echo "  $key: $value\n";
    }
    echo "\n";
}
$manager->add_event_handler('*', 'handle_all_events');
                    

7. Examples

Real-Time Call Monitor


connect('localhost', 'admin', 'password');

// Array to store active channels
$active_channels = array();

// Handle new channels
function handle_newchannel($event, $params, $server, $port) {
    global $active_channels;
    $channel = $params['Channel'];
    $callerid = isset($params['CallerIDNum']) ? $params['CallerIDNum'] : 'unknown';
    $active_channels[$channel] = array(
        'callerid' => $callerid,
        'starttime' => time(),
        'state' => $params['ChannelState']
    );
    echo "New call from $callerid on $channel\n";
}

// Handle channel state changes
function handle_newstate($event, $params, $server, $port) {
    global $active_channels;
    $channel = $params['Channel'];
    if(isset($active_channels[$channel])) {
        $active_channels[$channel]['state'] = $params['ChannelState'];
        echo "Channel $channel changed to state: " . $params['ChannelState'] . "\n";
    }
}

// Handle hangups
function handle_hangup($event, $params, $server, $port) {
    global $active_channels;
    $channel = $params['Channel'];
    if(isset($active_channels[$channel])) {
        $duration = time() - $active_channels[$channel]['starttime'];
        echo "Call from {$active_channels[$channel]['callerid']} on $channel ended after $duration seconds\n";
        unset($active_channels[$channel]);
    }
}

// Register event handlers
$manager->add_event_handler('Newchannel', 'handle_newchannel');
$manager->add_event_handler('Newstate', 'handle_newstate');
$manager->add_event_handler('Hangup', 'handle_hangup');

// Main loop - just keep the script running to receive events
echo "Real-time call monitoring started. Press Ctrl+C to exit.\n";
while(true) {
    // Display active calls every 10 seconds
    sleep(10);
    echo "\nActive Calls: " . count($active_channels) . "\n";
    foreach($active_channels as $channel => $info) {
        $duration = time() - $info['starttime'];
        echo "  $channel: {$info['callerid']} - Duration: $duration seconds, State: {$info['state']}\n";
    }
}

// Disconnect (this line won't be reached in this example)
$manager->disconnect();
?>
                    

IVR with Database Access


answer();

// Get caller ID for logging
$result = $agi->get_variable('CALLERID(num)');
$callerid = $result['data'];

// Welcome message
$agi->text2wav("Welcome to our customer service system. Please enter your 4-digit customer ID.");

// Get customer ID
$customer_id = '';
while(strlen($customer_id) != 4) {
    $result = $agi->get_data('beep', 5000, 4);
    $customer_id = $result['result'];
    if(strlen($customer_id) != 4) {
        $agi->text2wav("Sorry, please enter exactly 4 digits for your customer ID.");
    }
}

// Look up customer in Asterisk database
$result = $agi->database_get('customers', $customer_id);
if($result['result'] == 1) {
    $customer_data = $result['data'];
    $agi->text2wav("Hello, valued customer. Your account balance is $customer_data dollars.");

    // Present menu options
    $agi->text2wav("Press 1 for billing, press 2 for technical support, or press 3 to speak with an agent.");
    $option = '';
    while($option == '') {
        $result = $agi->wait_for_digit(5000);
        if($result['result'] > 0) {
            $option = chr($result['result']);
        } else {
            $agi->text2wav("Sorry, I didn't receive your selection. Please try again.");
        }
    }

    // Handle menu options
    switch($option) {
        case '1':
            $agi->text2wav("Transferring you to billing.");
            $agi->set_variable("CUSTOMER_ID", $customer_id);
            $agi->exec('Goto', 'billing,s,1');
            break;
        case '2':
            $agi->text2wav("Transferring you to technical support.");
            $agi->set_variable("CUSTOMER_ID", $customer_id);
            $agi->exec('Goto', 'techsupport,s,1');
            break;
        case '3':
            $agi->text2wav("Please hold while we connect you with an agent.");
            $agi->set_variable("CUSTOMER_ID", $customer_id);
            $agi->exec('Queue', 'customer_service');
            break;
        default:
            $agi->text2wav("Invalid option. Please call back. Goodbye.");
            break;
    }
} else {
    $agi->text2wav("Sorry, we couldn't find your customer record. Please call our office during business hours for assistance.");
}

$agi->hangup();
?>
                    

Queue Management Dashboard


connect('localhost', 'admin', 'password');

// Initialize queue stats
$queues = array();
$agents = array();

// Process queue status
$queue_status = $manager->QueueStatus();
if(isset($queue_status['events'])) {
    foreach($queue_status['events'] as $event) {
        if($event['Event'] == 'QueueParams') {
            // Queue information
            $queue_name = $event['Queue'];
            $queues[$queue_name] = array(
                'calls' => $event['Calls'],
                'max_wait' => $event['Holdtime'],
                'completed' => $event['Completed'],
                'abandoned' => $event['Abandoned'],
                'service_level' => $event['ServiceLevel'],
                'members' => array()
            );
        } else if($event['Event'] == 'QueueMember') {
            // Queue member (agent) information
            $queue_name = $event['Queue'];
            $member_name = $event['Name'];

            if(!isset($queues[$queue_name]['members'])) {
                $queues[$queue_name]['members'] = array();
            }

            $queues[$queue_name]['members'][$member_name] = array(
                'interface' => $event['Location'],
                'status' => $event['Status'],
                'paused' => $event['Paused'],
                'calls_taken' => $event['CallsTaken'],
                'last_call' => $event['LastCall']
            );

            // Also track agent across all queues
            if(!isset($agents[$member_name])) {
                $agents[$member_name] = array(
                    'queues' => array(),
                    'total_calls' => 0
                );
            }

            $agents[$member_name]['queues'][] = $queue_name;
            $agents[$member_name]['total_calls'] += $event['CallsTaken'];
        }
    }
}

// Display queue statistics
echo "Queue Statistics:\n";
echo "===============================\n\n";

foreach($queues as $name => $data) {
    echo "Queue: $name\n";
    echo "  Active calls: {$data['calls']}\n";
    echo "  Max wait time: {$data['max_wait']} seconds\n";
    echo "  Completed: {$data['completed']}\n";
    echo "  Abandoned: {$data['abandoned']}\n";
    echo "  Service level: {$data['service_level']}%\n";
    echo "  Agents: " . count($data['members']) . "\n";

    echo "  Agent List:\n";
    foreach($data['members'] as $agent => $agent_data) {
        $status = ($agent_data['status'] == '1') ? 'Available' : 'Unavailable';
        $paused = ($agent_data['paused'] == '1') ? ' (Paused)' : '';
        echo "    $agent: $status$paused, Calls taken: {$agent_data['calls_taken']}\n";
    }

    echo "\n";
}

// Display agent summary
echo "Agent Summary:\n";
echo "===============================\n\n";

foreach($agents as $name => $data) {
    echo "Agent: $name\n";
    echo "  Queues: " . implode(', ', $data['queues']) . "\n";
    echo "  Total calls taken: {$data['total_calls']}\n\n";
}

// Get active channels (current calls)
$result = $manager->Command('core show channels concise');
$channels = explode("\n", $result['data']);

echo "Current Calls:\n";
echo "===============================\n\n";

$call_count = 0;
foreach($channels as $channel) {
    if(strpos($channel, '!') !== false) {
        $call_count++;
        $parts = explode('!', $channel);
        if(count($parts) >= 8) {
            $chan_name = $parts[0];
            $caller_id = $parts[7];
            $duration = $parts[1];
            $application = $parts[5];

            echo "Channel: $chan_name\n";
            echo "  Caller ID: $caller_id\n";
            echo "  Duration: $duration seconds\n";
            echo "  Application: $application\n\n";
        }
    }
}

echo "Total active calls: $call_count\n";

// Check SIP registry status
$result = $manager->Command('sip show registry');
echo "\nSIP Registry Status:\n";
echo "===============================\n\n";
echo $result['data'] . "\n";

$manager->disconnect();
?>
                    

Conference Room Management


connect('localhost', 'admin', 'password');

// Function to list conference participants
function list_participants($manager, $conference_id) {
    $participants = $manager->ConfbridgeList($conference_id);
    if(empty($participants)) {
        echo "No participants in conference $conference_id\n";
        return;
    }

    echo "Conference $conference_id participants:\n";
    foreach($participants as $participant) {
        $muted = ($participant['Muted'] == 'Yes') ? ' (MUTED)' : '';
        echo "  {$participant['CallerIDName']} <{$participant['CallerIDNum']}> on channel {$participant['Channel']}$muted\n";
    }
}

// Function to display conference menu
function display_menu() {
    echo "\n";
    echo "Conference Management Menu:\n";
    echo "1. List conferences\n";
    echo "2. List participants in a conference\n";
    echo "3. Mute a participant\n";
    echo "4. Unmute a participant\n";
    echo "5. Kick a participant\n";
    echo "6. Lock a conference\n";
    echo "7. Unlock a conference\n";
    echo "8. Start recording a conference\n";
    echo "9. Stop recording a conference\n";
    echo "0. Exit\n";
    echo "Enter selection: ";
}

// Main loop
echo "Conference Management System\n";
echo "===========================\n";

while(true) {
    display_menu();
    $choice = trim(fgets(STDIN));

    switch($choice) {
        case '1': // List conferences
            $conferences = $manager->ConfbridgeListRooms();
            if(empty($conferences)) {
                echo "No active conferences\n";
            } else {
                echo "Active conferences:\n";
                foreach($conferences as $conf) {
                    $locked = ($conf['Locked'] == 'Yes') ? ' (LOCKED)' : '';
                    echo "  Conference: {$conf['Conference']} - {$conf['Parties']} participants$locked\n";
                }
            }
            break;

        case '2': // List participants
            echo "Enter conference ID: ";
            $conf_id = trim(fgets(STDIN));
            list_participants($manager, $conf_id);
            break;

        case '3': // Mute a participant
            echo "Enter conference ID: ";
            $conf_id = trim(fgets(STDIN));

            list_participants($manager, $conf_id);

            echo "Enter channel to mute: ";
            $channel = trim(fgets(STDIN));

            $result = $manager->ConfbridgeMute($conf_id, $channel);
            if($result['Response'] == 'Success') {
                echo "Participant muted successfully\n";
            } else {
                echo "Failed to mute participant: {$result['Message']}\n";
            }
            break;

        case '4': // Unmute a participant
            echo "Enter conference ID: ";
            $conf_id = trim(fgets(STDIN));

            list_participants($manager, $conf_id);

            echo "Enter channel to unmute: ";
            $channel = trim(fgets(STDIN));

            $result = $manager->ConfbridgeUnmute($conf_id, $channel);
            if($result['Response'] == 'Success') {
                echo "Participant unmuted successfully\n";
            } else {
                echo "Failed to unmute participant: {$result['Message']}\n";
            }
            break;

        case '5': // Kick a participant
            echo "Enter conference ID: ";
            $conf_id = trim(fgets(STDIN));

            list_participants($manager, $conf_id);

            echo "Enter channel to kick: ";
            $channel = trim(fgets(STDIN));

            $result = $manager->ConfbridgeKick($conf_id, $channel);
            if($result['Response'] == 'Success') {
                echo "Participant kicked successfully\n";
            } else {
                echo "Failed to kick participant: {$result['Message']}\n";
            }
            break;

        case '6': // Lock a conference
            echo "Enter conference ID: ";
            $conf_id = trim(fgets(STDIN));

            $result = $manager->ConfbridgeLock($conf_id);
            if($result['Response'] == 'Success') {
                echo "Conference locked successfully\n";
            } else {
                echo "Failed to lock conference: {$result['Message']}\n";
            }
            break;

        case '7': // Unlock a conference
            echo "Enter conference ID: ";
            $conf_id = trim(fgets(STDIN));

            $result = $manager->ConfbridgeUnlock($conf_id);
            if($result['Response'] == 'Success') {
                echo "Conference unlocked successfully\n";
            } else {
                echo "Failed to unlock conference: {$result['Message']}\n";
            }
            break;

        case '8': // Start recording
            echo "Enter conference ID: ";
            $conf_id = trim(fgets(STDIN));

            $filename = "/var/recordings/conf-$conf_id-" . time() . ".wav";
            $result = $manager->ConfbridgeStartRecord($conf_id, $filename);
            if($result['Response'] == 'Success') {
                echo "Conference recording started: $filename\n";
            } else {
                echo "Failed to start recording: {$result['Message']}\n";
            }
            break;

        case '9': // Stop recording
            echo "Enter conference ID: ";
            $conf_id = trim(fgets(STDIN));

            $result = $manager->ConfbridgeStopRecord($conf_id);
            if($result['Response'] == 'Success') {
                echo "Conference recording stopped\n";
            } else {
                echo "Failed to stop recording: {$result['Message']}\n";
            }
            break;

        case '0': // Exit
            echo "Exiting...\n";
            $manager->disconnect();
            exit(0);

        default:
            echo "Invalid selection. Please try again.\n";
    }
}
?>