最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

audio - A2DP source being deactivated during playback - Stack Overflow

programmeradmin2浏览0评论

I'm using a raspberry pi3 as a bluetooth speaker and I followed the guide linked here

I used to have avrcp disabled and everything worked fine but i decided to use avrcp because I wanted to control media played on the device connected. I'm using this python script that the guide suggested

#!/usr/bin/python

import os
import sys
import logging
import logging.handlers
import signal
import dbus
import dbus.service
import dbus.mainloop.glib

try:
    import gobject
except ImportError:
    from gi.repository import GObject as gobject

LOG_NAME = 'avrcp-volume-watcher'
LOG_LEVEL = logging.INFO
#LOG_LEVEL = logging.DEBUG
LOG_FORMAT = '%(name)s[%(process)d]: %(message)s'

# Increase VOLUME_MAX if you experience saturation issues. Standard value is 127
#VOLUME_MAX = 127
VOLUME_MAX = 141
#VOLUME_MAX = 159

def shutdown(signum, frame):
    mainloop.quit()

def pa_source_number(address):
    """ Returns the Pulseaudio source number matching bluetooth address

    Args:
        address(string) : bluetooth address formatted as AA:BB:CC:DD:EE:FF

    Returns:
        int: pulseaudio source number

    """

    stream = os.popen('pactl list short sources | grep bluez_source.{}'.format(address.replace(':', '_')))
    pulseaudio_source = stream.read()

    if pulseaudio_source == '':
        # Cannot find source in pulseaudio source list
        logger.debug(u'Cannot find pulseaudio A2DP source {}'.format(address))
        return

    # Pulseaudio source number is the first field in a \t seperated string
    pa_source_number = pulseaudio_source.split('\t')[0]
    logger.debug(u'Pulseaudio A2DP source {} is #{}'.format(address, pa_source_number))
    return pa_source_number

def pa_set_volume(address, volume):
    """ Set the volume of the pulseaudio source bound to the A2DP interface

    If A2DP interface is idle, pulseaudio source does not exist, do nothing

    Args:
        address(string) : bluetooth address formatted as AA:BB:CC:DD:EE:FF
        volume(int) : volume level 0-127

    """

    # Let's find the pulseaudio source matching address and set its volume
    pa_source = pa_source_number(address)
    if pa_source:
        logger.debug(u'Running pactl set-source-volume {} {}'.format(pa_source, format(float(volume) / VOLUME_MAX, '.2f')))
        os.system('pactl set-source-volume {} {}'.format(pa_source, format(float(volume) / VOLUME_MAX, '.2f')))
    else:
        logger.debug(u'Skipping volume change')

def device_property_changed(interface, properties, invalidated, path):
    """ Check for changes in .bluez object tree

    Check for Volume change event and State = active event
    Retrieve the volume value and set pulseaudio source accordingly

    Args:
        interface(string) : name of the dbus interface where changes occured
        properties(dict) : list of all parameters changed and their new value
        invalidated(array) : list of properties invalidated
        path(string) : path of the dbus object that triggered the call
    """

    if interface == '.bluez.MediaTransport1':
        bus = dbus.SystemBus()
        mediatransport_object = bus.get_object('.bluez', path)
        mediatransport_properties_interface = dbus.Interface(mediatransport_object, '.freedesktop.DBus.Properties')
        device_path = mediatransport_properties_interface.Get('.bluez.MediaTransport1', 'Device')
        device_object = bus.get_object('.bluez', device_path)
        device_properties_interface = dbus.Interface(device_object, '.freedesktop.DBus.Properties')
        name = device_properties_interface.Get('.bluez.Device1', 'Name')
        address = device_properties_interface.Get('.bluez.Device1', 'Address')
        if 'State' in properties:
            state = properties['State']
            logger.info(u'Bluetooth A2DP source: {} ({}) is now {}'.format(name, address, state))
            if state == 'active':
                codec =  mediatransport_properties_interface.Get('.bluez.MediaTransport1', 'Codec')
                logger.debug(u'Bluetooth A2DP source: {} ({}) codec is {}'.format(name, address, int(codec)))
                volume = mediatransport_properties_interface.Get('.bluez.MediaTransport1', 'Volume')
                logger.debug(u'Bluetooth A2DP source: {} ({}) volume is {}'.format(name, address, volume))
                pa_set_volume(address, volume)
        elif 'Volume' in properties:
            volume = properties['Volume']
            logger.debug(u'Bluetooth A2DP source: {} ({}) volume is now {}'.format(name, address, volume))
            pa_set_volume(address, volume)
        elif 'Codec' in properties:
            codec = properties['Codec']
            logger.debug(u'Bluetooth A2DP source: {} ({}) codec is {}'.format(name, address, int(codec)))


if __name__ == '__main__':

    # shut down on a TERM signal
    signal.signal(signal.SIGTERM, shutdown)

    # Create logger
    logger = logging.getLogger(LOG_NAME)
    logger.setLevel(LOG_LEVEL)

    # Choose between /var/log/syslog or current stdout
    ch = logging.handlers.SysLogHandler(address = '/dev/log')
#    ch = logging.StreamHandler()
    ch.setFormatter(logging.Formatter(fmt=LOG_FORMAT))
    logger.addHandler(ch)
    logger.info('Started')

    # Get the system bus
    try:
        dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
        bus = dbus.SystemBus()
    except Exception as ex:
        logger.error('Unable to get the system dbus: "{0}". Exiting. Is dbus running?'.format(ex.message))
        sys.exit(1)

    # listen for PropertyChanged signal on .bluez
    bus.add_signal_receiver(
        device_property_changed,
        bus_name='.bluez',
        signal_name='PropertiesChanged',
        dbus_interface='.freedesktop.DBus.Properties',
        path_keyword='path'
        )

    try:
        mainloop = gobject.MainLoop()
        mainloop.run()
    except KeyboardInterrupt:
        pass
    except:
        logger.error('Unable to run the gobject main loop')
        sys.exit(1)

    logger.info('Shutting down')
    sys.exit(0)

when i connect and start playing some music it works fine, until I change the volume and sometimes the code gives the error

Cannot find pulseaudio A2DP source <address of my bt device> in fact if I try to use the command pactl list short sources

it only outputs

0   alsa_output.platform-bcm2835_audio.analog-stereo.monitor    module-  alsa-card.c    s16le 2ch 44100Hz   IDLE
1   alsa_output.platform-3f902000.hdmi.hdmi-stereo.monitor  module-alsa-card.c  s16le 2ch 44100Hz   IDLE

To fix this i need to switch track or pause, wait sometime and then play again. I guess this works because the pulse audio process detects the device as a source

发布评论

评论列表(0)

  1. 暂无评论