linux.sipsoftphone/README.md
data 48ddb4b4af Initiales Release: SIP Softphone für FreePBX/Asterisk
PySide6/PJSUA2-basiertes Desktop-Softphone mit:
- SIP-Telefonie (Anrufe, DTMF, Halten, Transfer, Konferenz)
- CardDAV-Kontaktsync mit Write-Back (Multi-Account)
- Kontaktverwaltung mit Suche und Bearbeiten-Dialog
- Anrufliste mit Namensauflösung
- Favoriten-Panel (manuell + häufig angerufen)
- BLF-Panel (SIP Presence Monitoring)
- Responsives Layout (kompakt/erweitert)
- Click-to-Call (tel:/sip: URI via D-Bus)
- KDE-Integration (Tray, Benachrichtigungen)
- PipeWire/PulseAudio Audio-Routing
- AppImage Build-Support (PyInstaller + appimagetool)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 13:18:54 +01:00

244 lines
8.4 KiB
Markdown

# SIP Softphone
Desktop-SIP-Softphone für FreePBX/Asterisk auf Linux (KDE/PipeWire).
Basiert auf **PJSUA2** (SIP-Stack) und **PySide6** (Qt-GUI). Verbindet sich über SIP/UDP direkt mit der Telefonanlage.
## Features
- **SIP-Telefonie**: Anrufe tätigen/annehmen, DTMF, Halten, Transfer, Konferenz
- **Kontaktverwaltung**: Lokale Kontakte + CardDAV-Sync (Nextcloud, Multi-Account)
- **CardDAV Write-Back**: Kontakte bearbeiten und auf den Server zurückschreiben
- **Anrufliste**: Verlauf mit Richtung, Dauer, Kontaktnamens-Auflösung
- **Favoriten**: Manuelle Favoriten + häufig angerufene Nummern (automatisch)
- **BLF-Panel**: Besetzt-Lampenfeld (Presence-Monitoring via SIP SUBSCRIBE)
- **Kontaktsuche**: Live-Suche im Wählfeld nach Name/Firma
- **Responsives Layout**: Kompakt (nur Wählfeld) oder Breit (Wählfeld + Tabs)
- **Click-to-Call**: `tel:` und `sip:` URI-Handler via D-Bus Single-Instance
- **KDE-Integration**: System-Tray, D-Bus-Benachrichtigungen mit Annehmen/Ablehnen
- **PipeWire-Audio**: Natives PipeWire/PulseAudio-Routing, separates Klingelton-Gerät
- **AppImage**: Komplett unabhängiges Paket (kein Python/Qt auf dem Zielsystem nötig)
## Screenshots
```
┌──────────────────────────────────────────────┐
│ [Registriert] 00:42 SIP Softphone │
├──────────────┬───────────────────────────────┤
│ │ Favoriten│Verlauf│Kontakte│BLF │
│ [Nummer...] ├───────────────────────────────┤
│ │ ★ Max Mustermann │
│ [1] [2] [3]│ +49 40 555 1234 │
│ [4] [5] [6]│ ★ Büro Hauptnummer │
│ [7] [8] [9]│ +49 40 555 0000 │
│ [*] [0] [#]│ │
│ │ Häufig angerufen │
│ │ Lieferant Meyer │
├──────────────┴───────────────────────────────┤
│ [ Anrufen ] │
│ Mik: ═══════════ Lsp: ═══════════ │
└──────────────────────────────────────────────┘
```
## Voraussetzungen
### System
- Linux x86_64 (getestet: Manjaro KDE)
- PipeWire oder PulseAudio
- Python 3.10+ (für Entwicklung)
### Python-Pakete
```
PySide6>=6.6.0
vobject>=0.9.6 # vCard-Parsing für CardDAV
requests>=2.28.0 # HTTP-Client für CardDAV
```
### pjsua2 (SIP-Stack)
Auf Arch/Manjaro via AUR:
```bash
yay -S python-pjproject
```
### Optional
- `dbus-python`: Vorinstalliert auf KDE-Systemen (für Benachrichtigungen + Click-to-Call)
## Installation
### Aus Quellcode (Entwicklung)
```bash
git clone https://git.data-it-solution.de/data/linux.sipsoftphone.git
cd linux.sipsoftphone
pip install -r requirements.txt
python3 main.py
```
### Als AppImage (empfohlen)
```bash
# AppImage bauen
./build_appimage.sh
# Starten
chmod +x dist/SipSoftphone-x86_64.AppImage
./dist/SipSoftphone-x86_64.AppImage
```
Das AppImage bündelt Python, Qt, pjsua2 und alle Abhängigkeiten. Auf dem Zielsystem wird nichts weiter benötigt.
## Verwendung
### Erster Start
1. App starten → Login-Dialog erscheint
2. SIP-Zugangsdaten eingeben (Server, Extension, Passwort, Port)
3. Nach erfolgreicher Registrierung: Status wechselt zu grün "Registriert"
### Anrufe
| Aktion | Bedienung |
|--------|-----------|
| Anruf starten | Nummer eingeben + Enter oder "Anrufen"-Button |
| Kontakt anrufen | Name im Wählfeld tippen → Vorschlag doppelklicken |
| Annehmen | "Annehmen"-Button, F5, oder KDE-Benachrichtigung |
| Auflegen | "Auflegen"-Button oder F6 |
| Stummschalten | F7 |
| Halten | F8 |
| DTMF im Gespräch | Zifferntasten drücken (Wählfeld wechselt automatisch) |
### CardDAV-Kontakte
Über **Einstellungen → CardDAV** können mehrere Accounts konfiguriert werden (z.B. Nextcloud):
- URL: `https://nextcloud.example.de/remote.php/dav`
- Benutzername + Passwort
- Automatischer Sync im Hintergrund
Kontakte können im Detail-Dialog bearbeitet und per CardDAV zurückgeschrieben werden.
### Favoriten
- Im Kontakt-Detail-Dialog: "Favorit"-Button zum Pinnen/Entpinnen
- Häufig angerufene Nummern werden automatisch angezeigt
- Klick auf Favorit → Anruf wird gestartet
### Click-to-Call (URI-Handler)
```bash
# tel: URI
python3 main.py tel:+49123456789
# sip: URI
python3 main.py sip:200@server
# Als Standard-Handler registrieren (KDE)
xdg-mime default sipwebapp.desktop x-scheme-handler/tel
xdg-mime default sipwebapp.desktop x-scheme-handler/sip
```
Bei laufender Instanz wird der Anruf per D-Bus an die bestehende App weitergeleitet.
### Responsives Layout
- **Schmal (<650px)**: Nur Wählfeld mit Kontaktsuche
- **Breit (≥650px)**: Wählfeld links + Tabs rechts (Favoriten, Verlauf, Kontakte, BLF)
## Projektstruktur
```
SipWebApp/
├── main.py # Einstiegspunkt, D-Bus Single-Instance
├── requirements.txt # Python-Abhängigkeiten
├── sipwebapp.spec # PyInstaller Build-Konfiguration
├── build_appimage.sh # AppImage Build-Skript
├── sip/
│ ├── engine.py # PJSUA2-Endpoint mit Qt-Integration
│ ├── account.py # SIP-Account (Registrierung, Presence)
│ └── call.py # SIP-Call (Medien, DTMF, Transfer)
├── ui/
│ ├── hauptfenster.py # Hauptfenster (Layout, Signale, SIP-Events)
│ ├── waehlfeld.py # Wähltastatur + Kontaktsuche
│ ├── kontakte.py # Kontakttabelle + Detail/Bearbeiten-Dialoge
│ ├── anrufliste.py # Anrufverlauf mit Namensauflösung
│ ├── favoriten_panel.py # Manuelle + automatische Favoriten
│ ├── blf_panel.py # Besetzt-Lampenfeld (SIP Presence)
│ ├── einstellungen.py # Einstellungs-Dialog (Audio, CardDAV, BLF)
│ └── login_dialog.py # SIP-Login-Dialog
├── utils/
│ ├── config_manager.py # JSON-Konfiguration (~/.config/sipwebapp/)
│ ├── carddav.py # CardDAV-Sync + Write-Back (vobject/requests)
│ ├── audio_manager.py # PipeWire/PulseAudio Geräte-Verwaltung
│ ├── klingelton.py # Klingelton über separates Audio-Gerät
│ └── benachrichtigung.py # KDE D-Bus Desktop-Benachrichtigungen
└── resources/
├── sipwebapp.desktop # XDG Desktop-Entry
├── icons/phone.svg # App-Icon
└── sounds/klingelton.wav # Standard-Klingelton
```
## Architektur
### SIP-Integration (PJSUA2)
PJSUA2 wird im **Single-Thread-Modus** betrieben:
- `threadCnt=0`: Keine eigenen Worker-Threads
- `mainThreadOnly=True`: Alle Callbacks im Qt-Hauptthread
- `QTimer` pollt `libHandleEvents(0)` alle 50ms
So werden Race-Conditions und Qt-Crash-Probleme vermieden.
### Audio-Routing
PJSUA2 nutzt das `pulse`-Device. PipeWire übernimmt das Routing:
- Mikrofon/Lautsprecher: Konfigurierbar in den Einstellungen
- Klingelton: Separates Ausgabegerät (z.B. eingebaute Lautsprecher)
- Lautstärke: Mikrofon + Lautsprecher über Slider (0-200%)
### Konfiguration
Gespeichert unter `~/.config/sipwebapp/config.json`:
- SIP-Zugangsdaten (Server, Extension, Passwort)
- Audio-Geräte (Aufnahme, Wiedergabe, Klingelton)
- CardDAV-Accounts (Multi-Account)
- BLF-Extensions
- Favoriten (manuell gepinnt)
## AppImage bauen
Voraussetzungen auf dem Build-System:
- Python 3.14+
- `python-pjproject` (AUR)
- Internetzugang (lädt appimagetool + pip-Pakete)
```bash
./build_appimage.sh
```
Das Skript:
1. Erstellt ein Python-venv mit allen Abhängigkeiten
2. Kopiert pjsua2-Bindings + alle nativen Shared Libraries
3. Bündelt alles mit PyInstaller
4. Packt als AppImage (appimagetool)
Ergebnis: `dist/SipSoftphone-x86_64.AppImage` (~90 MB)
## Tastatur-Shortcuts
| Taste | Aktion |
|-------|--------|
| F5 | Anruf annehmen |
| F6 | Auflegen |
| F7 | Stummschalten |
| F8 | Halten/Fortsetzen |
| Escape | Nummernfeld leeren |
| Enter | Nummer wählen |
| 0-9, *, # | DTMF-Ziffern (Numpad-kompatibel) |
## Lizenz
Proprietär - ALLES WATT LÄUFT (Eduard Wisch)