web-dev-qa-db-fra.com

Existe-t-il un moyen de détecter si un appel skype est en cours? (dbus? utilisation de pulseaudio?)

J'ai construit un petit gadget qui est suspendu à la porte de mon bureau. Je peux l'éclairer via un script sur mon ordinateur pour indiquer que je suis occupé et que personne ne devrait y entrer. J'aimerais exécuter ce script, signalant k.a. que je suis occupé, chaque fois que je participe à un appel Skype.

Y at-il un moyen de détecter si je suis dans un appel Skype et exécuter un script alors?

Je pensais utiliser dbus et surveiller l’utilisation de pulseaudio, mais je ne savais pas par où commencer. Quelqu'un peut-il me diriger dans la bonne direction? L'idéal serait une chose de type écouteur d'interruption ou d'événement en python.

Modifier:

Il y a une question connexe qui n'est pas silencieuse et ne fonctionne pas avec ma version d'Ubuntu (16.04).

mplugd semble également prometteur.

2
con-f-use

C'est bon je l'ai. C'est toujours difficile sur les bords et seulement testé sur Ubuntu 16.04 avec Python 2.7 mais peu importe:

#!/usr/bin/python
# This monitors pulseaudio streams via a dbus event-listener.
#
# On Ubuntu to enable pulseaudio dbus support:
#
#   echo -e '.ifexists module-dbus-protocol.so\nload-module module-dbus-protocol\n.endif' >> ~/.Pulse/pulse/default.pa
#   # globally: /etc/Pulse/default.pa
#
# And restart pulseaudio:
#
#   pkill pulseaudio; pulseaudio
#

from __future__ import division, print_function, unicode_literals
import dbus, os, gobject, logging
from dbus.mainloop.glib import DBusGMainLoop
from logging import info, debug, error, warning as warn
#logging.getLogger().setLevel(logging.DEBUG)

skypestream = []
cstr = 'org.PulseAudio.Core1'

# convert byte array to string
def dbus2str(db):
    if type(db)==dbus.Struct:
        return str(Tuple(dbus2str(i) for i in db))
    if type(db)==dbus.Array:
        return "".join([dbus2str(i) for i in db])
    if type(db)==dbus.Dictionary:
        return dict((dbus2str(k), dbus2str(v)) for k, v in db.items())
    if type(db)==dbus.String:
        return db+''
    if type(db)==dbus.UInt32:
        return str(db+0)
    if type(db)==dbus.Byte:
        return chr(db)
    if type(db)==dbus.Boolean:
        return db==True
    if type(db)==dict:
        return dict((dbus2str(k), dbus2str(v)) for k, v in db.items())
    return "(%s:%s)" % (type(db), db)


def sig_handler(path=None, sender=None, msg=None):
    debug( '\n\npath: %s\n%s\n\nsender: %s\n%s\n\nmsg: %s\n%s\n\n',
        path, dir(path), sender, dir(sender), msg, dir(msg) )
    mem = msg.get_member()
    dbus_pstreams = (
        dbus.Interface(
            Pulse_bus.get_object(object_path=path),
            dbus_interface='org.freedesktop.DBus.Properties'
        ) for path in core1.Get(
            cstr,
            'PlaybackStreams',
            dbus_interface='org.freedesktop.DBus.Properties' )
        )

    pstreams = {}
    for pstream in dbus_pstreams:
        try:
            pstreams[pstream.Get(cstr+'.Stream', 'Index')] =  pstream
        except dbus.exceptions.DBusException:
            pass
    if pstreams:
        for stream in pstreams.keys():
            plist = pstreams[stream].Get(cstr+'.Stream', 'PropertyList')
            appname = dbus2str(plist.get('application.name', None))
            if mem == 'PlaybackStreamRemoved' and path in skypestream:
                skypestream.remove(path)
                print('no-skype')
            if appname.find('Skype') > -1:
                if mem == 'NewPlaybackStream':
                    skypestream.append(path)
                    print('busy', appname)


def Pulse_bus_address():
    address = None
    if 'Pulse_DBUS_SERVER' in os.environ:
        address = os.environ['Pulse_DBUS_SERVER']
    else:
        bus = dbus.SessionBus()
        server_lookup = bus.get_object("org.PulseAudio1",
            "/org/pulseaudio/server_lookup1")
        address = server_lookup.Get("org.PulseAudio.ServerLookup1",
            "Address", dbus_interface="org.freedesktop.DBus.Properties")
        debug(address)
    if not address: raise RuntimeError('No pulseaudio dbus address found!')
    return address


if __== "__main__":
    DBusGMainLoop(set_as_default=True)

    loop = gobject.MainLoop()

    Pulse_bus = dbus.connection.Connection(Pulse_bus_address())
    core1 = Pulse_bus.get_object(object_path='/org/pulseaudio/core1')

    core1.ListenForSignal(cstr+'.NewPlaybackStream', dbus.Array(signature="o"))
    core1.ListenForSignal(cstr+'.PlaybackStreamRemoved', dbus.Array(signature="o"))

    Pulse_bus.add_signal_receiver(sig_handler, message_keyword='msg')

    loop.run()
1
con-f-use

Cela n’est peut-être pas parfait, mais c’est un bon prototype Shell qui utilise pactl pour la surveillance.

Voici une partie de la sortie lorsqu'un appel est en cours d'exécution:

pactl list source-outputs

_Source Output #2
    Driver: protocol-native.c
    Owner Module: 8
    Client: 11
    Source: 2
    Sample Specification: s16le 2ch 44100Hz
    Channel Map: front-left,front-right
    Format: pcm, format.sample_format = "\"s16le\""  format.rate = "44100"  format.channels = "2"  format.channel_map = "\"front-left,front-right\""
    Corked: no
    Mute: no
    Volume: front-left: 65536 / 100% / 0.00 dB,   front-right: 65536 / 100% / 0.00 dB
            balance 0.00
    Buffer Latency: 0 usec
    Source Latency: 66 usec
    Resample method: n/a
    Properties:
        application.icon_name = "chromium-browser"
        media.name = "RecordStream"
        application.name = "Chrome input"
        native-protocol.peer = "UNIX socket client"
        native-protocol.version = "30"
        application.process.id = "17053"
        application.process.user = "sneetsher"
        application.process.Host = "sneetsher-blueskies"
        application.process.binary = "skypeforlinux"
        window.x11.display = ":0.0"
        application.language = "en_US.UTF-8"
        application.process.machine_id = "00074bc0a72a47d49284ce5b9bcda899"
        application.process.session_id = "c4"
        module-stream-restore.id = "source-output-by-application-name:Chrome input"
_

pactl list sink-inputs

_Sink Input #166
    Driver: protocol-native.c
    Owner Module: 8
    Client: 16
    Sink: 1
    Sample Specification: float32le 2ch 44100Hz
    Channel Map: front-left,front-right
    Format: pcm, format.sample_format = "\"float32le\""  format.rate = "44100"  format.channels = "2"  format.channel_map = "\"front-left,front-right\""
    Corked: no
    Mute: no
    Volume: front-left: 65536 / 100% / 0.00 dB,   front-right: 65536 / 100% / 0.00 dB
            balance 0.00
    Buffer Latency: 51519 usec
    Sink Latency: 11124 usec
    Resample method: copy
    Properties:
        application.icon_name = "chromium-browser"
        media.name = "Playback"
        application.name = "Skype for Linux Beta"
        native-protocol.peer = "UNIX socket client"
        native-protocol.version = "30"
        application.process.id = "17053"
        application.process.user = "sneetsher"
        application.process.Host = "sneetsher-blueskies"
        application.process.binary = "skypeforlinux"
        window.x11.display = ":0.0"
        application.language = "en_US.UTF-8"
        application.process.machine_id = "00074bc0a72a47d49284ce5b9bcda899"
        application.process.session_id = "c4"
        module-stream-restore.id = "sink-input-by-application-name:Skype for Linux Beta"

Sink Input #167
    Driver: protocol-native.c
    Owner Module: 8
    Client: 17
    Sink: 1
    Sample Specification: float32le 2ch 44100Hz
    Channel Map: front-left,front-right
    Format: pcm, format.sample_format = "\"float32le\""  format.rate = "44100"  format.channels = "2"  format.channel_map = "\"front-left,front-right\""
    Corked: no
    Mute: no
    Volume: front-left: 65536 / 100% / 0.00 dB,   front-right: 65536 / 100% / 0.00 dB
            balance 0.00
    Buffer Latency: 28480 usec
    Sink Latency: 11061 usec
    Resample method: copy
    Properties:
        application.icon_name = "chromium-browser"
        media.name = "Playback"
        application.name = "Skype for Linux Beta"
        native-protocol.peer = "UNIX socket client"
        native-protocol.version = "30"
        application.process.id = "17053"
        application.process.user = "sneetsher"
        application.process.Host = "sneetsher-blueskies"
        application.process.binary = "skypeforlinux"
        window.x11.display = ":0.0"
        application.language = "en_US.UTF-8"
        application.process.machine_id = "00074bc0a72a47d49284ce5b9bcda899"
        application.process.session_id = "c4"
        module-stream-restore.id = "sink-input-by-application-name:Skype for Linux Beta"
_
1
user.dz