linux.sipsoftphone/utils/benachrichtigung.py
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

110 lines
3.8 KiB
Python

"""Anruf-Benachrichtigung - KDE Plasma Notification mit Annehmen/Ablehnen."""
try:
import dbus
DBUS_VERFUEGBAR = True
except ImportError:
DBUS_VERFUEGBAR = False
class AnrufBenachrichtigung:
"""KDE-Benachrichtigung mit Action-Buttons über D-Bus.
Nutzt org.freedesktop.Notifications für native KDE Plasma
Benachrichtigungen mit Annehmen/Ablehnen-Buttons.
"""
def __init__(self):
self._notification_id = 0
self._callback_annehmen = None
self._callback_ablehnen = None
self._bus = None
self._interface = None
if not DBUS_VERFUEGBAR:
return
try:
self._bus = dbus.SessionBus()
proxy = self._bus.get_object(
"org.freedesktop.Notifications",
"/org/freedesktop/Notifications",
)
self._interface = dbus.Interface(
proxy, "org.freedesktop.Notifications"
)
# Signal-Handler für Button-Klicks
self._bus.add_signal_receiver(
self._on_action,
signal_name="ActionInvoked",
dbus_interface="org.freedesktop.Notifications",
)
# Signal wenn Notification geschlossen wird
self._bus.add_signal_receiver(
self._on_closed,
signal_name="NotificationClosed",
dbus_interface="org.freedesktop.Notifications",
)
except dbus.DBusException:
self._interface = None
def anruf_anzeigen(self, anrufer, callback_annehmen=None, callback_ablehnen=None):
"""Benachrichtigung für eingehenden Anruf anzeigen.
Args:
anrufer: Anrufer-Nummer oder Name
callback_annehmen: Funktion bei Klick auf "Annehmen"
callback_ablehnen: Funktion bei Klick auf "Ablehnen"
"""
if not self._interface:
return
self._callback_annehmen = callback_annehmen
self._callback_ablehnen = callback_ablehnen
try:
self._notification_id = self._interface.Notify(
"SIP Softphone", # App-Name
0, # Replaces-ID (0 = neue Notification)
"call-start", # Icon (Freedesktop-Icon-Name)
f"Eingehender Anruf", # Titel
f"Anruf von {anrufer}", # Text
["annehmen", "Annehmen", "ablehnen", "Ablehnen"], # Actions
{
"urgency": dbus.Byte(2), # Critical - bleibt stehen
"category": "im.received",
"desktop-entry": "sipwebapp",
},
0, # Timeout: 0 = kein Auto-Close (Critical)
)
except dbus.DBusException:
pass
def schliessen(self):
"""Benachrichtigung schließen (z.B. wenn Anruf endet)."""
if self._interface and self._notification_id:
try:
self._interface.CloseNotification(self._notification_id)
except dbus.DBusException:
pass
self._notification_id = 0
self._callback_annehmen = None
self._callback_ablehnen = None
def _on_action(self, notif_id, action_id):
"""D-Bus Signal: Button wurde geklickt."""
if notif_id != self._notification_id:
return
if action_id == "annehmen" and self._callback_annehmen:
self._callback_annehmen()
elif action_id == "ablehnen" and self._callback_ablehnen:
self._callback_ablehnen()
self._notification_id = 0
def _on_closed(self, notif_id, reason):
"""D-Bus Signal: Notification wurde geschlossen."""
if notif_id == self._notification_id:
self._notification_id = 0