2024-05-25 01:52:26

by Arun Raghavan

[permalink] [raw]
Subject: [PATCH BlueZ,v8 0/5] ASHA plugin

Hello,
This is v8 of the ASHA plugin patch set:

* I've now refactored things so that fd management is all in the
profile code, rather than shared code
* In the process, there is bt_asha_device struct, so the transport
only interacts with that, and access to the shared bt_asha struct is
more cleanly mediated by shared code
* Absorbed the connection parameter update into the first two patches
for easier rebase

Cheers,
Arun

Arun Raghavan (5):
src/shared: Add initial implementation for an ASHA profile
profiles/audio: Add an ASHA plugin
test: Add a script to test ASHA
gitignore: Add compile_commands.json
gitignore: Add __pycache__

.gitignore | 3 +
Makefile.am | 3 +-
Makefile.plugins | 5 +
configure.ac | 4 +
lib/uuid.h | 3 +
profiles/audio/asha.c | 533 +++++++++++++++++++++++++++++++++++++
profiles/audio/asha.h | 38 +++
profiles/audio/media.c | 30 +++
profiles/audio/media.h | 2 +
profiles/audio/transport.c | 194 +++++++++++++-
src/shared/asha.c | 368 +++++++++++++++++++++++++
src/shared/asha.h | 64 +++++
test/simple-asha | 166 ++++++++++++
13 files changed, 1410 insertions(+), 3 deletions(-)
create mode 100644 profiles/audio/asha.c
create mode 100644 profiles/audio/asha.h
create mode 100644 src/shared/asha.c
create mode 100644 src/shared/asha.h
create mode 100755 test/simple-asha

--
2.45.1



2024-05-25 01:52:37

by Arun Raghavan

[permalink] [raw]
Subject: [PATCH BlueZ,v8 3/5] test: Add a script to test ASHA

Plays out an audio file to the device. Depends on GStreamer for media
file reading and decoding (specifically, gstreamer core,
gst-plugins-base, gst-ffmpeg, and gst-python, or equivalent packages).
---
test/simple-asha | 166 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 166 insertions(+)
create mode 100755 test/simple-asha

diff --git a/test/simple-asha b/test/simple-asha
new file mode 100755
index 000000000..c90f8a12b
--- /dev/null
+++ b/test/simple-asha
@@ -0,0 +1,166 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
+import os
+import signal
+import sys
+
+import dbus
+import dbus.service
+import dbus.mainloop.glib
+
+import gi
+
+gi.require_version("Gst", "1.0")
+gi.require_version("GLib", "2.0")
+from gi.repository import GLib, Gst
+
+import bluezutils
+
+mainloop = None
+pipeline = None
+seqnum: int = 0
+
+
+def signal_handler(_sig, _frame):
+ print("Got interrupt")
+ mainloop.quit()
+
+
+signal.signal(signal.SIGINT, signal_handler)
+
+
+def usage():
+ print(f"Usage: simple-asha <remote addr> <audio file name> (optional volume 0-127)")
+
+
+def start_playback(fd: int, omtu: int):
+ global mainloop, pipeline
+ pktsize = 161
+
+ if omtu < pktsize:
+ print("Weird mtu", omtu)
+
+ outdata = bytearray(pktsize)
+
+ Gst.init(None)
+
+ pipeline = Gst.parse_launch(
+ f"""
+ filesrc location="{sys.argv[2]}" ! decodebin !
+ audioconvert ! audioresample !
+ audiobuffersplit output-buffer-duration="20/1000" ! avenc_g722 !
+ appsink name=sink emit-signals=true
+ """
+ )
+
+ def on_new_sample(sink):
+ global seqnum
+
+ sample = sink.emit("pull-sample")
+ buf = sample.get_buffer()
+
+ with buf.map(Gst.MapFlags.READ) as info:
+ pos = 0
+
+ if info.size != pktsize - 1:
+ print("Unexpected buffer size: ", info.size)
+
+ outdata[pos] = seqnum % 256
+ pos += 1
+
+ for byte in info.data:
+ outdata[pos] = byte
+ pos += 1
+
+ try:
+ n = os.write(fd, outdata)
+ if n != pktsize:
+ print("Wrote less than expected: ", n)
+ except:
+ return Gst.FlowReturn.ERROR
+
+ seqnum += 1
+
+ return Gst.FlowReturn.OK
+
+ sink = pipeline.get_by_name("sink")
+ sink.connect("new-sample", on_new_sample)
+
+ def bus_message(_bus, message, _data) -> bool:
+ typ = message.type
+
+ if typ == Gst.MessageType.EOS:
+ print("End of stream")
+ mainloop.quit()
+ elif typ == Gst.MessageType.ERROR:
+ err, debug = message.parse_error()
+ print(f"Pipeline error: {err} ({debug})")
+ mainloop.quit()
+
+ return True
+
+ bus = pipeline.get_bus()
+ bus.add_watch(GLib.PRIORITY_DEFAULT, bus_message, None)
+
+ pipeline.set_state(Gst.State.PLAYING)
+
+
+if __name__ == "__main__":
+ dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
+
+ mainloop = GLib.MainLoop()
+ bus = dbus.SystemBus()
+
+ if (len(sys.argv) == 3) or (len(sys.argv) == 4):
+ device = bluezutils.find_device(sys.argv[1])
+ if device is None:
+ print("Could not find device: ", sys.argv[1])
+ exit(255)
+ else:
+ usage()
+ sys.exit(255)
+
+ asha_object_path = device.object_path + "/asha"
+
+ print("Looking up ASHA object", asha_object_path)
+ asha = bus.get_object("org.bluez", asha_object_path)
+
+ print("Looking up endpoint properties for", asha.object_path)
+ props = asha.GetAll(
+ "org.bluez.MediaEndpoint1",
+ dbus_interface="org.freedesktop.DBus.Properties",
+ )
+ path = props["Transport"]
+
+ print("Trying to acquire", path)
+ transport = dbus.Interface(
+ bus.get_object("org.bluez", path),
+ "org.bluez.MediaTransport1",
+ )
+
+ # Keep default volume at 25%
+ volume = 32
+ if len(sys.argv) == 4:
+ volume = int(sys.argv[3])
+ if volume < 0 or volume > 127:
+ print("Volume must be between 0 (mute) and 127 (max)")
+
+ print("Setting initial volume to", volume)
+ transport.Set(
+ "org.bluez.MediaTransport1",
+ "Volume",
+ dbus.UInt16(volume, variant_level=1),
+ dbus_interface="org.freedesktop.DBus.Properties",
+ )
+
+ print("Acquiring transport")
+ (fd, imtu, omtu) = transport.Acquire()
+
+ print("Starting playback, hit Ctrl-C to stop")
+ start_playback(fd.take(), omtu)
+
+ mainloop.run()
+
+ pipeline.set_state(Gst.State.NULL)
+ transport.Release()
--
2.45.1


2024-06-05 01:40:39

by patchwork-bot+bluetooth

[permalink] [raw]
Subject: Re: [PATCH BlueZ,v8 0/5] ASHA plugin

Hello:

This series was applied to bluetooth/bluez.git (master)
by Luiz Augusto von Dentz <[email protected]>:

On Thu, 23 May 2024 11:52:56 -0400 you wrote:
> Hello,
> This is v8 of the ASHA plugin patch set:
>
> * I've now refactored things so that fd management is all in the
> profile code, rather than shared code
> * In the process, there is bt_asha_device struct, so the transport
> only interacts with that, and access to the shared bt_asha struct is
> more cleanly mediated by shared code
> * Absorbed the connection parameter update into the first two patches
> for easier rebase
>
> [...]

Here is the summary with links:
- [BlueZ,v8,1/5] src/shared: Add initial implementation for an ASHA profile
(no matching commit)
- [BlueZ,v8,2/5] profiles/audio: Add an ASHA plugin
(no matching commit)
- [BlueZ,v8,3/5] test: Add a script to test ASHA
(no matching commit)
- [BlueZ,v8,4/5] gitignore: Add compile_commands.json
https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=5c793eb3c55e
- [BlueZ,v8,5/5] gitignore: Add __pycache__
https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=61776f0de7b2

You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html