Examples

This page contains practical examples of using SimpleSIP.

Basic Call Example

Simple outbound call:

from simplesip import SimpleSIPClient
import time

def basic_call_example():
    client = SimpleSIPClient("1001", "password", "192.168.1.100")

    try:
        print("Connecting...")
        client.connect()
        time.sleep(2)  # Wait for registration

        print("Making call...")
        client.make_call("1002")

        # Wait for connection
        while client.call_state.value != 'connected':
            if client.call_state.value == 'idle':
                print("Call failed")
                return
            time.sleep(0.1)

        print("Call connected!")
        input("Press Enter to hang up...")

    finally:
        client.disconnect()

if __name__ == "__main__":
    basic_call_example()

Audio Streaming Example

Full duplex audio streaming:

from simplesip import SimpleSIPClient
import pyaudio
import threading
import time
import audioop

class AudioCallClient:
    def __init__(self, username, password, server):
        self.client = SimpleSIPClient(username, password, server)
        self.audio = None
        self.input_stream = None
        self.output_stream = None
        self.running = False

        # Audio config
        self.CHUNK = 160
        self.FORMAT = pyaudio.paInt16
        self.CHANNELS = 1
        self.RATE = 8000

    def audio_callback(self, pcm_data, format_type):
        """Handle received audio"""
        if self.output_stream and format_type == 'pcm':
            self.output_stream.write(pcm_data)

    def audio_capture_thread(self):
        """Capture and send audio"""
        while self.running:
            if self.client.call_state.value in ['connected', 'streaming']:
                try:
                    # Read from microphone
                    pcm_data = self.input_stream.read(self.CHUNK,
                                                    exception_on_overflow=False)

                    # Send audio
                    self.client.send_audio(pcm_data)

                except Exception as e:
                    print(f"Audio error: {e}")

            time.sleep(0.02)  # 20ms intervals

    def start_call(self, destination):
        try:
            # Set up audio callback
            self.client.set_audio_callback(self.audio_callback, 'pcm')

            # Connect
            print("Connecting...")
            self.client.connect()
            time.sleep(2)

            # Make call
            print(f"Calling {destination}...")
            self.client.make_call(destination)

            # Wait for connection
            while self.client.call_state.value not in ['connected', 'streaming']:
                if self.client.call_state.value == 'idle':
                    print("Call failed")
                    return
                time.sleep(0.1)

            print(f"Call connected! Codec: {self.client.negotiated_codec}")

            # Set up audio streams
            self.audio = pyaudio.PyAudio()

            self.input_stream = self.audio.open(
                format=self.FORMAT,
                channels=self.CHANNELS,
                rate=self.RATE,
                input=True,
                frames_per_buffer=self.CHUNK
            )

            self.output_stream = self.audio.open(
                format=self.FORMAT,
                channels=self.CHANNELS,
                rate=self.RATE,
                output=True,
                frames_per_buffer=self.CHUNK
            )

            # Start audio capture
            self.running = True
            audio_thread = threading.Thread(target=self.audio_capture_thread, daemon=True)
            audio_thread.start()

            print("Audio streaming active. Press Enter to hang up...")
            input()

        finally:
            self.cleanup()

    def cleanup(self):
        self.running = False

        if self.input_stream:
            self.input_stream.close()
        if self.output_stream:
            self.output_stream.close()
        if self.audio:
            self.audio.terminate()

        self.client.disconnect()

# Usage
if __name__ == "__main__":
    client = AudioCallClient("1001", "password", "192.168.1.100")
    client.start_call("1002")

Call Status Monitoring

Monitor call status and events:

from simplesip import SimpleSIPClient, CallState
import time

def monitor_call_status():
    client = SimpleSIPClient("1001", "password", "192.168.1.100")

    try:
        client.connect()
        time.sleep(2)

        client.make_call("1002")

        last_state = None

        while client.running:
            current_state = client.call_state

            # Log state changes
            if current_state != last_state:
                status = client.get_call_status()
                print(f"State changed: {current_state.value}")
                print(f"  Call ID: {status['call_id']}")
                print(f"  Remote RTP: {status['remote_rtp']}")
                print(f"  Codec: {client.negotiated_codec}")
                print(f"  Audio buffer: {status['audio_buffer_size']}")
                print("-" * 40)

            last_state = current_state

            if current_state == CallState.IDLE:
                break

            time.sleep(0.5)

    finally:
        client.disconnect()

if __name__ == "__main__":
    monitor_call_status()

Multiple Calls Example

Handle multiple simultaneous calls:

from simplesip import SimpleSIPClient
import threading
import time

class MultiCallClient:
    def __init__(self):
        self.clients = {}

    def create_client(self, name, username, password, server):
        """Create a new SIP client"""
        client = SimpleSIPClient(username, password, server)
        self.clients[name] = client
        return client

    def make_call(self, client_name, destination):
        """Make a call using specified client"""
        if client_name in self.clients:
            client = self.clients[client_name]

            def call_thread():
                try:
                    client.connect()
                    time.sleep(2)
                    client.make_call(destination)

                    while client.call_state.value != 'idle':
                        time.sleep(1)

                except Exception as e:
                    print(f"Call error on {client_name}: {e}")

            thread = threading.Thread(target=call_thread, daemon=True)
            thread.start()

    def disconnect_all(self):
        """Disconnect all clients"""
        for client in self.clients.values():
            try:
                client.disconnect()
            except:
                pass

# Usage
if __name__ == "__main__":
    multi_client = MultiCallClient()

    # Create multiple clients
    multi_client.create_client("alice", "1001", "pass1", "server.com")
    multi_client.create_client("bob", "1002", "pass2", "server.com")

    # Make calls
    multi_client.make_call("alice", "9001")
    multi_client.make_call("bob", "9002")

    # Keep running
    try:
        time.sleep(60)  # Run for 1 minute
    finally:
        multi_client.disconnect_all()

DTMF Example

Send DTMF tones during a call:

from simplesip import SimpleSIPClient
import time

def dtmf_example():
    client = SimpleSIPClient("1001", "password", "192.168.1.100")

    try:
        client.connect()
        time.sleep(2)

        client.make_call("1002")

        # Wait for connection
        while client.call_state.value != 'connected':
            time.sleep(0.1)

        print("Call connected! Sending DTMF tones...")

        # Send DTMF sequence
        dtmf_sequence = "1234*0#"

        for digit in dtmf_sequence:
            print(f"Sending DTMF: {digit}")
            client.send_dtmf(digit)
            time.sleep(0.5)  # Wait between tones

        print("DTMF sequence complete")
        input("Press Enter to hang up...")

    finally:
        client.disconnect()

if __name__ == "__main__":
    dtmf_example()

These examples demonstrate the key features of SimpleSIP. Adapt them to your specific use case!