Mendengarkan notifikasi libnotify yang masuk menggunakan DBus

9

Saya mencoba memfilter setiap notifikasi melalui espeak. Namun, sepertinya saya tidak bisa menemukan cara untuk mendapatkan badan notifikasi dari skrip python, atau bahkan apa signal_name untuk mendengarkan.

bus.add_signal_receiver(espeak,
                    dbus_interface="org.freedesktop.Notifications",
                    signal_name="??")

Mencoba ke Google untuk ini sepertinya hanya menghasilkan hasil yang melibatkan membuat pemberitahuan baru, jadi saya benar-benar bingung sekarang.

Adakah yang bisa membantu saya dengan ini?

Singkatnya, yang saya inginkan adalah mendengarkan notifikasi yang masuk menggunakan python, dan mendapatkan atribut "body" dari notifikasi.

mesin
sumber
1
Tampaknya pemberitahuan tidak menghasilkan sinyal yaitu, dbus-monitor "type='signal',interface='org.freedesktop.Notifications'"menunjukkan apa-apa selain dbus-monitor "interface='org.freedesktop.Notifications'"menunjukkan pemberitahuan (jenisnya adalah 'method_call' bukan 'sinyal').
jfs

Jawaban:

11

Agar ini selalu terbarui: dari dbus 1.5.sesuatu parameter tambahan diperlukan saat menambahkan string kecocokan dengan bus.add_match_string_non_blockinguntuk memastikan kami menerima semuanya.

Kode yang dihasilkan adalah sebagai berikut:

import glib
import dbus
from dbus.mainloop.glib import DBusGMainLoop

def notifications(bus, message):
    print [arg for arg in message.get_args_list()]

DBusGMainLoop(set_as_default=True)

bus = dbus.SessionBus()
bus.add_match_string_non_blocking("eavesdrop=true, interface='org.freedesktop.Notifications', member='Notify'")
bus.add_message_filter(notifications)

mainloop = glib.MainLoop()
mainloop.run()
joost
sumber
Jika saya ingin memanggil metode dbus lain yang berbeda di dalam filter pemberitahuan, itu tidak berfungsi. Semua saya dapatkan unable to connect to session bus: Operation was cancelled. Kami beralih buske filter.
Khurshid Alam
1
Pada instalasi Python saya (Python 3, Ubuntu) saya harus from gi.repository import GLib as glibmembuat ini berfungsi.
Owen
6

Yang Anda maksud dengan pemberitahuan adalah "gelembung OSD" yang dikirim beberapa perangkat lunak, seperti mengubah volume, obrolan IM, dll? Anda ingin membuat program python untuk menangkapnya?

Yah, Tanya Ubuntu bukan QA seorang programmer, dan pengembangan perangkat lunak sedikit di luar cakupan, tapi di sini ada sedikit kode yang saya lakukan untuk menangkap gelembung notifikasi:

import glib
import dbus
from dbus.mainloop.glib import DBusGMainLoop

def notifications(bus, message):
    if message.get_member() == "Notify":
        print [arg for arg in message.get_args_list()]

DBusGMainLoop(set_as_default=True)

bus = dbus.SessionBus()
bus.add_match_string_non_blocking("interface='org.freedesktop.Notifications'")
bus.add_message_filter(notifications)

mainloop = glib.MainLoop()
mainloop.run()

Biarkan ini berjalan di terminal, lalu buka jendela terminal lain dan uji:

notify-send --icon=/usr/share/pixmaps/debian-logo.png "My Title" "Some text body"

Dan program akan menampilkan ini:

[dbus.String(u'notify-send'), dbus.UInt32(0L), dbus.String(u'/usr/share/pixmaps/debian-logo.png'), dbus.String(u'My Title'), dbus.String(u'Some text body'),...

Seperti yang mungkin sudah Anda duga, message.get_args_list()[0]adalah pengirim, [2] untuk ikon, [3] untuk ringkasan dan [4] untuk teks isi.

Untuk arti bidang lainnya, periksa dokumen spesifikasi resmi

MestreLion
sumber
Sepertinya tidak berfungsi lagi pada atau sebelum 16.04. Jawaban Joost di bawah memang memperbaikinya.
Catskul
3

Saya kesulitan mendapatkan contoh lain untuk benar-benar berfungsi, tetapi pada akhirnya saya sampai di sana. Berikut ini contoh kerjanya:

import glib
import dbus
from dbus.mainloop.glib import DBusGMainLoop

def print_notification(bus, message):
  keys = ["app_name", "replaces_id", "app_icon", "summary",
          "body", "actions", "hints", "expire_timeout"]
  args = message.get_args_list()
  if len(args) == 8:
    notification = dict([(keys[i], args[i]) for i in range(8)])
    print notification["summary"], notification["body"]

loop = DBusGMainLoop(set_as_default=True)
session_bus = dbus.SessionBus()
session_bus.add_match_string("type='method_call',interface='org.freedesktop.Notifications',member='Notify',eavesdrop=true")
session_bus.add_message_filter(print_notification)

glib.MainLoop().run()

Jika Anda ingin melihat contoh kerja yang lebih rinci, saya sarankan melihat Notifications.py di proyek recent_notifications .

kzar
sumber