全部博文(2005)
分类:
2009-12-08 16:33:22
This page contains audio service usage examples. The API description is available at .
Note that there are a few approaches for a2dp (alsa, gstreamer, pulse?), maybe two for sco (alsa, pulse?). Alsa is the simplest and should support the greater variety of audio clients directly.
(these are valid for bluez-utils-3.16 or newer)
Note: you will not need bluetooth-alsa, plugz, btsco or the like for audio to work. They are obsolete.
pcm.bluetooth {where 00:11:22:33:44:55 is the Bluetooth address of your headset (use for example hcitool scan to find it)
type bluetooth
device 00:11:22:33:44:55
}
pcm.bluetoothraw {
type bluetooth
device 00:11:22:33:44:55
}
pcm.bluetooth {
type plug
slave {
pcm bluetoothraw
}
}
Append this lines to ~/.asoundrc:
pcm.bluetooth {
type bluetooth
device "XX:XX:XX:XX:XX:XX" #optional, connects to specific device instead the default one
profile "auto" #optional, supported profiles are: auto, hifi and voice
}
See also the workaround in the previous section.
arecord -D bluetooth -f S16_LE | aplay -D bluetooth -f S16_LE
gst-launch -v alsasrc device=bluetooth ! audioconvert ! audioresample ! alsasink device=bluetooth sync=false
options->preferences->Audio->Current Output Plugin->ALSA
Output Plugin Preferences->Device Settings->audio device: "bluetooth"
if you can't see the audio device form there, you can force the bluetooth output by modifying your audacious property file
~/.config/audacious/config. Modify the "pcm_device" value by "pcm_device=bluetooth"
xmms is known to have some issues, please use its successor audacious instead
options->preferences->Output Plugin->Configure: "bluetooth"
preferences->Plugins->Output->Select ALSA->Preferences->Audio device: "bluetooth"->Advanced->disable mmap mode
mplayer -ao alsa:device=bluetooth
play --device=bluetooth file.mp3
Amarok configuration -> Engine -> Select: "alsa"
then
replace "default" with "bluetooth" in either "mono" or "stereo" field
to route the sound to bluetooth:
gconftool -t string -s /system/gstreamer/0.10/default/musicaudiosink "alsasink device=bluetooth"
to route the sound to normal speakers:
gconftool -t string -s /system/gstreamer/0.10/default/musicaudiosink "autoaudiosink"
Menu Settings -> xine Engine Parameters -> audio -> Expert Options tab
Change "device.alsa_default_device" (mono) and "device.alsa_front_device" (stereo) from "default" to "bluetooth"
Currently only available for a2dp.
It is not necessary to create a virtual device as in alsa, configuration can be change via element properties:
Element Properties:
name : The name of the object
flags: readable, writable
String. Default: null Current: "a2dpsink0"
preroll-queue-len : Number of buffers to queue during preroll
flags: readable, writable
Unsigned Integer. Range: 0 - 4294967295 Default: 0 Current: 0
sync : Sync on the clock
flags: readable, writable
Boolean. Default: true Current: true
max-lateness : Maximum number of nanoseconds that a buffer can be late before it is dropped (-1 unlimited)
flags: readable, writable
Integer64. Range: -1 - 9223372036854775807 Default: -1 Current: -1
qos : Generate Quality-of-Service events upstream
flags: readable, writable
Boolean. Default: false Current: false
device : Bluetooth remote device address
flags: readable, writable
String. Default: null Current: null
Element Properties:
name : The name of the object
flags: readable, writable
String. Default: null Current: "sbcenc0"
mode : Encoding mode
flags: readable, writable
Enum "GstSbcMode" Current: 0, "auto"
(0): auto - Auto
(1): mono - Mono
(2): dual - Dual Channel
(3): stereo - Stereo
(4): joint - Joint Stereo
allocation : Allocation mode
flags: readable, writable
Enum "GstSbcAllocation" Current: 0, "auto"
(0): auto - Auto
(1): loudness - Loudness
(2): snr - SNR
blocks : Blocks
flags: readable, writable
Integer. Range: 0 - 2147483647 Default: 0 Current: 0
subbands : Sub Bands
flags: readable, writable
Integer. Range: 0 - 2147483647 Default: 0 Current: 0
To transmit with SBC
gst-launch -v ... ! decodebin ! audioconvert ! audioresample ! sbcenc ! a2dpsink device=XX:XX:XX:XX:XX:XX
To send mp3 data directly
gst-launch filesrc location=! mp3parse ! a2dpsink device=XX:XX:XX:XX:XX:XX
Sending mp3 data directly is preferable on low powered systems, such as embedded devices, rather than decoding from mp3 and re-encoding as sbc. (To diagnose problems, try passing --gst-debug a2dpsink:5,avdtpsink:5 to gst-launch. Sometimes the mp3parse element from the gst-plugins-ugly package is incompatible with bluez due to the way it reports channels. Different versions and/or manual patching may be required)
to route the sound to bluetooth:
gconftool -t string -s /system/gstreamer/0.10/default/musicaudiosink "sbcenc ! a2dpsink device=XX:XX:XX:XX:XX:XX"
to route the sound to normal speakers:
gconftool -t string -s /system/gstreamer/0.10/default/musicaudiosink "autoaudiosink"
Older versions of pulse without the native bluetooth module can use the alsa plugin:
Make audio service autostart. (Autostart=true in /etc/bluetooth/audio.service) (not required for bluez 4.x)
.asoundrc:
pcm.headset {
type bluetooth
device "XX:XX:XX:XX:XX:XX"
profile "voice"
}
Manually run:
pactl load-module module-alsa-sink device=headset
pactl load-module module-alsa-source device=headset
Then use pavucontrol to make the headset sink/source the default
Newer versions of pulse have a native Bluetooth sink which works *only* with Bluez 4.x. You need pulse 0.9.14 (FIXME: maybe 0.9.13 works too?) and later, and they have to have module-bluetooth-discover and module-bluetooth-device compiled, and they have to match the version of BlueZ you are running.
That last point is so important it's worth repeating: You *must* have matching bluez and pulseaudio versions, because the API for communicating between pulse and bluez is still under active development. If you fail to do this, everything will seem to work up to the point of making "beep" sounds as your headset is connected...except there will be error messages instead of audio.
Here's a compatibility table to get you started:
bluez 4.0-26: FIXME: not sure when pulse/bluez starts working...0.9.13? 4.18?
bluez 4.27-33: pulse 0.9.14
bluez 4.34-38: pulse 0.9.15
bluez 4.39+: FIXME: if these versions are released, please test and update this page! Thanks in advance!
You'll also need a non-ancient kernel (2.6.24 works, and it's older than anything the BlueZ developers are willing to support), the kernel needs to be built with Bluetooth support, you'll need a compatible bluetooth adapter, and you need to pair your headset first...which you'll need for the ALSA and gstreamer plugins as well.
Also, it is a good idea to make sure pulse is working properly with a more conventional sound device on your setup, and strip down your Pulse configuration to the bare minimum set of modules that you actually use before attempting to use it with Bluetooth. Chances are good that if an obscure Pulse module bug causes your pulseaudio daemon to crash with an ordinary sound card, it'll continue to make your pulseaudio daemon crash with a bluetooth audio device.
There are two ways to get the bluetooth sink running in pulse: automatic detection with module-bluetooth-discover, or manually with module-bluetooth-device.
The manual method: from pacmd, the pulseaudio -C command line, or from .pulse/default.pa:
# $HOME/.pulse/default.pa
# Load the sink module. We use the name "fred" here, but any valid Pulse sink name will work.
# Also note we've set the default profile to 'a2dp'. Use 'hsp' for headset (telephone) audio.
load-module module-bluetooth-device profile=a2dp sink_name=fred address=XX:XX:XX:XX:XX:XX
# Make the module default (you can do this with any other pulse tool as well, e.g. pavucontrol)
set-default-sink fred
# Set the card profile (in case you left out profile= above - pulse 0.9.15 only)
set-card-profile fred a2dp
Some important notes about the manual method:
The automatic method: Load module-bluetooth-discover, then connect with gnome-bluetooth or dbus commands.
# $HOME/.pulse/default.pa
# Load module-bluetooth-discover
load-module module-bluetooth-discover
# Note we do NOT have to load-module module-bluetooth-device here.
Once the pulseaudio daemon is configured and running with module-bluetooth-device, you can (in theory) connect to the headset any way you like: use gnome-bluetooth, press the "connect" button on the headset, etc. Pulseaudio should detect the headset connection and automatically create a pulseaudio sink. You then use pavucontrol or similar to configure it as the default sink and/or move streams to it.
# Use dbus-send from the command line to connect to the headset:
$ dbus-send --print-reply --system --dest=org.bluez / org.bluez.Manager.DefaultAdapter
method return sender=:1.18141 -> dest=:1.18218 reply_serial=2
object path "/org/bluez/4189/hci0"
$ dbus-send --print-reply --system --dest=org.bluez /org/bluez/4189/hci0 org.bluez.Adapter.FindDevice string:00:15:0E:A0:6C:C8
method return sender=:1.18141 -> dest=:1.18221 reply_serial=2
object path "/org/bluez/4189/hci0/dev_00_15_0E_A0_6C_C8"
$ dbus-send --print-reply --system --dest=org.bluez /org/bluez/4189/hci0/dev_00_15_0E_A0_6C_C8 org.bluez.AudioSink.Connect
method return sender=:1.18141 -> dest=:1.18226 reply_serial=2
# Use pacmd to set the default sink and enable a2dp
$ pacmd "set-default-sink bluez_sink.00_15_0E_A0_6C_C8"
$ pacmd "set-card-profile bluez_sink.00_15_0E_A0_6C_C8 a2dp"
Depending on what profile you want, the interface name in the last dbus-send command will be different:
org.bluez.AudioSink.Connect - connects via A2DP (stereo audio)
org.bluez.Headset.Connect - connects via HSP/HFP (mono headset with mic)
org.bluez.Audio.Connect - connects to both (select which to use via the pulse card profile)
Regardless of which method you use, after the Connect call, module-bluetooth-discover in the pulseaudio daemon should automatically load the module-bluetooth-device module. Pulse 0.9.13 and 0.9.14 used a name based on the "friendly name" of the device (which is a string like "TRI_BH102 v2.2"). Pulse 0.9.15 uses a name based on the Bluetooth address such as "bluez_sink.00_15_0E_A0_6C_C8".
Pulse 0.9.15 probably won't work until you set the card profile.
The examples from here to the end of the page are only for programmers who need to automate device creation, service startup, etc. Stop reading now if you're just trying to get the basics working.
Note this section does not apply to bluez 4.x, where the audio service is a plugin that runs in bluetoothd.
When a client wants to start the audio service or discover the audio service bus "id", the ActivateService method should be called.
import dbus
bus = dbus.SystemBus()
bmgr = dbus.Interface(bus.get_object('org.bluez', '/org/bluez'), 'org.bluez.Manager')
bus_id = bmgr.ActivateService('audio')
# All serial service messages should be sent to this address
print bus_id
Service activation from command line:
$dbus-send --system --type=method_call --print-reply --dest=org.bluez \
/org/bluez org.bluez.Manager.ActivateService string:audio
Note that much of this section does not apply to bluez 4.x, which uses org.bluez..Connect.
A2DP (Advanced Audio Distribution Profile) is intended for high quality stereo audio applications.
For A2DP there is no need to specifically request a "playing" state. The bluetooth alsa plugin will automatically do this when some application tries to use it. If no device is connected, the default device will be connected to, otherwise the first found connected device will be used.
import dbus
bus = dbus.SystemBus()
manager = dbus.Interface(bus.get_object('org.bluez', '/org/bluez'), 'org.bluez.Manager')
bus_id = manager.ActivateService('audio')
audio = dbus.Interface(bus.get_object(bus_id, '/org/bluez/audio'), 'org.bluez.audio.Manager')
path = audio.CreateDevice('00:11:22:33:44:55')
#audio.ChangeDefaultDevice(path) #change the device to be used by default
sink = dbus.Interface (bus.get_object(bus_id, path), 'org.bluez.audio.Sink')
sink.Connect()
The ":X.Y" in the following examples is the unique bus name of the audio service. You get it in the reply to the ActivateService method call:
$dbus-send --system --print-reply --dest=org.bluez /org/bluez org.bluez.Manager.ActivateService string:audio
* CreateDevice:
$dbus-send --system --type=method_call --print-reply --dest=":X.Y" \
/org/bluez/audio org.bluez.audio.Manager.CreateDevice string:00:11:22:33:44:55
* Connect (replace device_object_path with return value from last call):
$dbus-send --system --type=method_call --print-reply --dest=":X.Y" \
"device_object_path" org.bluez.audio.Sink.Connect
Note this section does not apply to bluez 4.x, which uses org.bluez.Headset.Connect.
The Headset Profile is intended for two-way low-latency audio applications such as VoIP.
import dbus
bus = dbus.SystemBus()
manager = dbus.Interface(bus.get_object('org.bluez', '/org/bluez'), 'org.bluez.Manager')
bus_id = manager.ActivateService('audio')
audio = dbus.Interface(bus.get_object(bus_id, '/org/bluez/audio'), 'org.bluez.audio.Manager')
path = audio.CreateHeadset('00:11:22:33:44:55')
#audio.ChangeDefaultHeadset(path) #change the device to be used by default
headset = dbus.Interface (bus.get_object(bus_id, path), 'org.bluez.audio.Headset')
#Connect and Play are not required in PCM mode
headset.Connect()
headset.Play()
* CreateHeadset:
$dbus-send --system --type=method_call --print-reply --dest=":X.Y" \
/org/bluez/audio org.bluez.audio.Manager.CreateHeadset string:00:11:22:33:44:55
* Connect:
$dbus-send --system --type=method_call --print-reply --dest=":X.Y" \
"device_object_path" org.bluez.audio.Headset.Connect
* Play:
$dbus-send --system --type=method_call --print-reply --dest=":X.Y" \
"device_object_path" org.bluez.audio.Headset.Play