lapinozz
lapinozz

Reputation: 310

(Bluez) How to get bluetooth headset buttons input?

I have a bluetooth headset connected to a linux device. I would like to programmatically receive the play/pause/next/previous/volUp/volDown button press.

After some research I found out that I can interact with Bluez with dbus. I tried to register a MediaPlayer using this script https://github.com/bluez/bluez/blob/master/test/example-player But when I inspect dbus there's no new player, and it doesn't seem to have changed anything.

I also tried to use the Gatt services, but I can't find org.bluez.GattService1 anywhere.

What would be the best way to get the inputs? Is there something wrong with my Bluez?

Background: My goal is to have a audio input and audio output both connected via bluetooth to a rpi. I did manage to do this and have the sound from the input play on the output. Now I would like to forward the inputs too.

Upvotes: 5

Views: 6754

Answers (2)

samsi
samsi

Reputation: 51

I'm late to the party, but the Arch Linux Wiki provides good instructions for this:
https://wiki.archlinux.org/index.php/Bluetooth_headset#Configuration_via_CLI

Install bluez-utils and run mpris-proxy. This will forward the commands to the mpris2 interface, where it can be picked up by your media player.

Upvotes: 2

ukBaz
ukBaz

Reputation: 7984

I have looked into this a bit and discovered some things but not reached a full conclusion. I thought I would share it here in the hope that someone can edit/improve the answer.

I have connected up a Bluetooth headset to my Raspberry Pi and DBus interfaces of interest seem to be org.bluez.MediaControl1 and org.bluez.MediaTransport1

(venv) pi@raspberrypi:~/stack_overflow $ busctl tree 'org.bluez'
└─/org
  └─/org/bluez
    ├─/org/bluez/hci0
    │ ├─/org/bluez/hci0/dev_74_5C_4B_F8_6D_95
    │ │ └─/org/bluez/hci0/dev_74_5C_4B_F8_6D_95/fd2
    └─/org/bluez/test

(venv) pi@raspberrypi:~/stack_overflow $ busctl introspect 'org.bluez' '/org/bluez/hci0/dev_74_5C_4B_F8_6D_95'
NAME                                TYPE      SIGNATURE RESULT/VALUE                             FLAGS
org.bluez.Device1                   interface -         -                                        -
.CancelPairing                      method    -         -                                        -
.Connect                            method    -         -                                        -
.ConnectProfile                     method    s         -                                        -
.Disconnect                         method    -         -                                        -
.DisconnectProfile                  method    s         -                                        -
.Pair                               method    -         -                                        -
.Adapter                            property  o         "/org/bluez/hci0"                        emits-change
.Address                            property  s         "74:5C:4B:F8:6D:95"                      emits-change
.AddressType                        property  s         "public"                                 emits-change
.AdvertisingData                    property  a{yv}     -                                        emits-change
.AdvertisingFlags                   property  ay        -                                        emits-change
.Alias                              property  s         "Jabra Move SE v1.0.0"                   emits-change writable
.Appearance                         property  q         -                                        emits-change
.Blocked                            property  b         false                                    emits-change writable
.Class                              property  u         2360324                                  emits-change
.Connected                          property  b         true                                     emits-change
.Icon                               property  s         "audio-card"                             emits-change
.LegacyPairing                      property  b         false                                    emits-change
.ManufacturerData                   property  a{qv}     -                                        emits-change
.Modalias                           property  s         -                                        emits-change
.Name                               property  s         "Jabra Move SE v1.0.0"                   emits-change
.Paired                             property  b         true                                     emits-change
.RSSI                               property  n         -                                        emits-change
.ServiceData                        property  a{sv}     -                                        emits-change
.ServicesResolved                   property  b         true                                     emits-change
.Trusted                            property  b         false                                    emits-change writable
.TxPower                            property  n         -                                        emits-change
.UUIDs                              property  as        5 "00001108-0000-1000-8000-00805f9b34fb… emits-change
org.bluez.MediaControl1             interface -         -                                        -
.FastForward                        method    -         -                                        deprecated
.Next                               method    -         -                                        deprecated
.Pause                              method    -         -                                        deprecated
.Play                               method    -         -                                        deprecated
.Previous                           method    -         -                                        deprecated
.Rewind                             method    -         -                                        deprecated
.Stop                               method    -         -                                        deprecated
.VolumeDown                         method    -         -                                        deprecated
.VolumeUp                           method    -         -                                        deprecated
.Connected                          property  b         true                                     emits-change
.Player                             property  o         -                                        emits-change
org.freedesktop.DBus.Introspectable interface -         -                                        -
.Introspect                         method    -         s                                        -
org.freedesktop.DBus.Properties     interface -         -                                        -
.Get                                method    ss        v                                        -
.GetAll                             method    s         a{sv}                                    -
.Set                                method    ssv       -                                        -
.PropertiesChanged                  signal    sa{sv}as  -                                        -

(venv) pi@raspberrypi:~/stack_overflow $ busctl introspect 'org.bluez' '/org/bluez/hci0/dev_74_5C_4B_F8_6D_95/fd2'
NAME                                TYPE      SIGNATURE RESULT/VALUE                            FLAGS
org.bluez.MediaTransport1           interface -         -                                       -
.Acquire                            method    -         hqq                                     -
.Release                            method    -         -                                       -
.TryAcquire                         method    -         hqq                                     -
.Codec                              property  y         0                                       emits-change
.Configuration                      property  ay        4 17 21 2 51                            emits-change
.Delay                              property  q         -                                       emits-change
.Device                             property  o         "/org/bluez/hci0/dev_74_5C_4B_F8_6D_95" emits-change
.State                              property  s         "idle"                                  emits-change
.UUID                               property  s         "0000110A-0000-1000-8000-00805F9B34FB"  emits-change
.Volume                             property  q         -                                       emits-change writ
org.freedesktop.DBus.Introspectable interface -         -                                       -
.Introspect                         method    -         s                                       -
org.freedesktop.DBus.Properties     interface -         -                                       -
.Get                                method    ss        v                                       -
.GetAll                             method    s         a{sv}                                   -
.Set                                method    ssv       -                                       -
.PropertiesChanged                  signal    sa{sv}as  -                                       -
lines 1-19/19 (END)

The org.bluez.MediaControl1 has deprecated next to it and org.bluez.MediaTransport1 is documented at: https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/media-api.txt#n587

org.bluez.MediaTransport1 has a volume property, but when I try to read it there is an error:

(venv) pi@raspberrypi:~/stack_overflow $ busctl get-property 'org.bluez' '/org/bluez/hci0/dev_74_5C_4B_F8_6D_95/fd2' 'org.bluez.MediaTransport1' Volume
No such property 'Volume'

But I can read other properties fine:

(venv) pi@raspberrypi:~/stack_overflow $ busctl get-property 'org.bluez' '/org/bluez/hci0/dev_74_5C_4B_F8_6D_95/fd2' 'org.bluez.MediaTransport1' State
s "active"

I have been using this bit of code to hold it in the Active state while I introspect the interfaces.

import os
from gi.repository import GLib
from pydbus import SystemBus
from time import sleep

dev_addr = '74:5C:4B:F8:6D:95'

bluez_service = 'org.bluez'
adapter_path = '/org/bluez/hci0'
device_path = f"{adapter_path}/dev_{dev_addr.replace(':', '_')}"

bus = SystemBus()
mngr = bus.get(bluez_service, '/')
adapter = bus.get(bluez_service, adapter_path)

def get_media_transport_path(dev_path):
    mng_objs = mngr.GetManagedObjects()
    for dev_objs in mng_objs:
        if dev_objs.startswith(dev_path):
            state = mng_objs[dev_objs].get('org.bluez.MediaTransport1', {}).get('State', False)
            print('State', state)
            if state:
                return dev_objs

mt_path = get_media_transport_path(device_path)
mt = bus.get(bluez_service, mt_path)
mt_data = mt.Acquire()
print('Acquire', mt_data)
print('GetAll', mt.GetAll('org.bluez.MediaTransport1'))
print('Transport Device', mt.Device)
print('Transport state', mt.State)

sleep(20)
mt.Release()
print('Transport State', mt.State)

My next investigation was going to be around the File Descriptor returned by Acquire however my DBus library of choice has an issue around fd's https://github.com/LEW21/pydbus/pull/86

Upvotes: 3

Related Questions