sip_helper 0.1.2
sip_helper: ^0.1.2 copied to clipboard
A lightweight SIP/VoIP library for Flutter. SIP protocol (UDP), RTP audio transport, G.711 A-law codec, and Windows audio via WinMM FFI.
sip_helper #
A lightweight SIP/VoIP library for Dart. Implements the SIP protocol over UDP with G.711 A-law (PCMA) codec and RTP audio transport for real-time voice calls.
Features #
- SIP Protocol - Full SIP/UDP implementation (REGISTER, INVITE, BYE, CANCEL, OPTIONS, ACK)
- SIP Digest Auth - MD5 challenge-response authentication (RFC 2617)
- RTP Audio - RTP/AVP transport for real-time audio streaming
- G.711 A-law Codec - PCMA encoder/decoder (ITU-T G.711)
- Windows Audio - Native WinMM API (waveOut/waveIn) via Dart FFI
- Bluetooth Support - Automatic A2DP to HFP profile switching for call audio
- Audio Device Selection - Enumerate and select input/output devices
- Gain Controls - Adjustable input/output gain
- Ring Tones - 5 built-in synthesized ring tones
- Ringback Tone - Standard 425Hz ringback for outgoing calls
- DTMF - In-call DTMF tone generation
- Audio Levels - Real-time input/output level computation for UI visualization
Platform Support #
| Platform | Status |
|---|---|
| Windows | Supported (WinMM FFI) |
| macOS | Not yet supported |
| Linux | Not yet supported |
Audio capture and playback use the Windows Multimedia (WinMM) API via
dart:ffi. Other platforms will require platform-specific audio backends.
Getting Started #
Installation #
Add to your pubspec.yaml:
dependencies:
sip_helper: ^0.1.0
Basic Usage #
import 'package:sip_helper/sip_helper.dart';
void main() async {
// Optional: receive log output
sipLogger = print;
// Configure SIP account
final config = SipConfiguration(
server: 'pbx.example.com',
username: '1001',
password: 'secret',
displayName: 'John Doe',
);
// Initialize and connect
final sip = SipHelper.instance;
await sip.initialize(config);
await sip.connect();
// Listen for events
sip.connectionStateStream.listen((connected) {
print('Registered: $connected');
});
sip.incomingCallStream.listen((call) {
print('Incoming call from ${call.callerNumber}');
sip.answerCall(call.callId!);
});
// Make a call
await sip.makeCall('1002');
}
Architecture #
lib/
sip_helper.dart # Barrel export
src/
sip_helper_service.dart # Orchestrator (SipHelper)
logging.dart # Pluggable logger
models/
sip_configuration.dart # SIP account config
call_info.dart # Call state model
sip/
udp_sip_client.dart # SIP protocol implementation
sip_call.dart # Active call tracking
rtp/
rtp_session.dart # RTP packet send/receive
codec/
pcma_encoder.dart # G.711 A-law encoder
pcma_decoder.dart # G.711 A-law decoder
audio/
sound_service.dart # Tone generation + voice playback
audio_player_service.dart # PCMA decode + upsample pipeline
microphone_service.dart # Microphone capture
audio_level.dart # Real-time level computation
platform/
windows/
win32_audio.dart # WinMM FFI bindings
Audio Pipeline #
Outgoing (Mic → Network):
WinMM waveIn (8kHz PCM16) → Input Gain → PCMA Encode → RTP Send
Incoming (Network → Speaker):
RTP Receive → PCMA Decode (8kHz PCM16) → Upsample 2x (16kHz) → Output Gain → WinMM waveOut
API Reference #
SipHelper (Orchestrator) #
The main entry point. Wires together SIP signaling, RTP audio, and platform audio services.
final sip = SipHelper.instance;
// Lifecycle
await sip.initialize(config); // Wire up all services
await sip.connect(); // Register with SIP server
await sip.disconnect(); // Unregister
// Call management
await sip.makeCall('1002'); // Outgoing call
await sip.answerCall(callId); // Answer incoming
await sip.hangupCall(callId); // Hang up
// Event streams
sip.connectionStateStream // Stream<bool>
sip.incomingCallStream // Stream<CallInfo>
sip.callStateStream // Stream<String> (callId:state)
sip.errorStream // Stream<String>
// Sub-services
sip.soundService // Ring tones, voice playback, gain
sip.microphoneService // Mic capture, input gain
sip.audioLevelService // Real-time audio levels
sip.rtpSession // RTP transport
SipConfiguration #
SipConfiguration(
server: 'pbx.example.com',
username: '1001',
password: 'secret',
displayName: 'John Doe', // Optional
port: 5060, // Default: 5060
transport: 'UDP', // Default: UDP
autoRegister: true, // Default: true
registerInterval: 600, // Seconds, default: 600
)
Audio Device Selection #
// List available devices
final outputs = WinAudioDevices.getOutputDevices();
final inputs = WinAudioDevices.getInputDevices();
// Select devices by index
sip.soundService.setOutputDevice(0);
sip.microphoneService.setInputDevice(0);
// Adjust gain
sip.soundService.setOutputGain(5.0); // 500%
sip.microphoneService.setInputGain(1.0); // 100%
Ring Tones #
sip.soundService.setRingTone(RingTone.chime); // Default
sip.soundService.setRingTone(RingTone.classic);
sip.soundService.setRingTone(RingTone.soft);
sip.soundService.setRingTone(RingTone.alert);
sip.soundService.setRingTone(RingTone.melody);
// Preview
sip.soundService.previewRingTone(RingTone.melody);
Logging #
// Route all sip_helper logs to your logger
sipLogger = (message) => myLogger.info(message);
// Or simply use print
sipLogger = print;
Requirements #
- Dart SDK >= 3.0.0
- Windows 10/11 for audio features (WinMM API)
- SIP Server — Asterisk, FreeSWITCH, or any RFC 3261 compliant server
License #
MIT License - see LICENSE for details.