From: Luiz Augusto von Dentz <luiz.von.dentz@xxxxxxxxx> BlueZ 4 is no longer supported by BlueZ community for a long long time, also by moving to BlueZ 5 it should make it even more clearer that BlueZ 4 is no longer an option. --- configure.ac | 16 +- po/POTFILES.in | 1 - po/be.po | 28 - po/de.po | 28 - po/el.po | 28 - po/fr.po | 28 - po/hr.po | 28 - po/hu.po | 28 - po/id.po | 28 - po/it.po | 28 - po/lt.po | 28 - po/nn.po | 28 - po/oc.po | 28 - po/pl.po | 28 - po/pt_BR.po | 28 - po/ru.po | 28 - po/sk.po | 28 - po/sv.po | 28 - po/tr.po | 28 - po/uk.po | 28 - po/zh_CN.po | 28 - po/zh_TW.po | 28 - src/Makefile.am | 26 - src/modules/bluetooth/bluez4-util.c | 1851 -------------- src/modules/bluetooth/bluez4-util.h | 160 -- src/modules/bluetooth/module-bluetooth-discover.c | 13 +- src/modules/bluetooth/module-bluez4-device.c | 2664 --------------------- src/modules/bluetooth/module-bluez4-discover.c | 187 -- 28 files changed, 3 insertions(+), 5475 deletions(-) delete mode 100644 src/modules/bluetooth/bluez4-util.c delete mode 100644 src/modules/bluetooth/bluez4-util.h delete mode 100644 src/modules/bluetooth/module-bluez4-device.c delete mode 100644 src/modules/bluetooth/module-bluez4-discover.c diff --git a/configure.ac b/configure.ac index 0eb44b08f..c2e883731 100644 --- a/configure.ac +++ b/configure.ac @@ -1043,24 +1043,14 @@ AX_DEFINE_DIR(PA_MACHINE_ID_FALLBACK, PA_MACHINE_ID_FALLBACK, #### BlueZ support (optional, dependent on D-Bus and SBC) #### -AC_ARG_ENABLE([bluez4], - AS_HELP_STRING([--disable-bluez4],[Disable optional BlueZ 4 support])) AC_ARG_ENABLE([bluez5], AS_HELP_STRING([--disable-bluez5],[Disable optional BlueZ 5 support])) ## SBC ## -AS_IF([test "x$enable_bluez4" != "xno" || test "x$enable_bluez5" != "xno"], +AS_IF([test "x$enable_bluez5" != "xno"], [PKG_CHECK_MODULES(SBC, [ sbc >= 1.0 ], HAVE_SBC=1, HAVE_SBC=0)], HAVE_SBC=0) -## BlueZ 4 ## -AS_IF([test "x$enable_bluez4" != "xno" && test "x$HAVE_DBUS" = "x1" && test "x$HAVE_SBC" = "x1"], HAVE_BLUEZ_4=1, - HAVE_BLUEZ_4=0) -AS_IF([test "x$enable_bluez4" = "xyes" && test "x$HAVE_BLUEZ_4" != "x1"], - [AC_MSG_ERROR([*** BLUEZ 4 support not found (requires sbc and D-Bus)])]) -AC_SUBST(HAVE_BLUEZ_4) -AM_CONDITIONAL([HAVE_BLUEZ_4], [test "x$HAVE_BLUEZ_4" = x1]) - ## BlueZ 5 ## AS_IF([test "x$enable_bluez5" != "xno" && test "x$HAVE_DBUS" = "x1" && test "x$HAVE_SBC" = "x1"], HAVE_BLUEZ_5=1, HAVE_BLUEZ_5=0) @@ -1069,7 +1059,7 @@ AS_IF([test "x$enable_bluez5" = "xyes" && test "x$HAVE_BLUEZ_5" != "x1"], AC_SUBST(HAVE_BLUEZ_5) AM_CONDITIONAL([HAVE_BLUEZ_5], [test "x$HAVE_BLUEZ_5" = x1]) -AS_IF([test "x$HAVE_BLUEZ_4" = "x1" || test "x$HAVE_BLUEZ_5" = "x1"], HAVE_BLUEZ=1, HAVE_BLUEZ=0) +AS_IF([test "x$HAVE_BLUEZ_5" = "x1"], HAVE_BLUEZ=1, HAVE_BLUEZ=0) AC_SUBST(HAVE_BLUEZ) AM_CONDITIONAL([HAVE_BLUEZ], [test "x$HAVE_BLUEZ" = x1]) @@ -1575,7 +1565,6 @@ AS_IF([test "x$HAVE_UDEV" = "x1"], ENABLE_UDEV=yes, ENABLE_UDEV=no) AS_IF([test "x$HAVE_SYSTEMD_DAEMON" = "x1"], ENABLE_SYSTEMD_DAEMON=yes, ENABLE_SYSTEMD_DAEMON=no) AS_IF([test "x$HAVE_SYSTEMD_LOGIN" = "x1"], ENABLE_SYSTEMD_LOGIN=yes, ENABLE_SYSTEMD_LOGIN=no) AS_IF([test "x$HAVE_SYSTEMD_JOURNAL" = "x1"], ENABLE_SYSTEMD_JOURNAL=yes, ENABLE_SYSTEMD_JOURNAL=no) -AS_IF([test "x$HAVE_BLUEZ_4" = "x1"], ENABLE_BLUEZ_4=yes, ENABLE_BLUEZ_4=no) AS_IF([test "x$HAVE_BLUEZ_5" = "x1"], ENABLE_BLUEZ_5=yes, ENABLE_BLUEZ_5=no) AS_IF([test "x$HAVE_BLUEZ_5_OFONO_HEADSET" = "x1"], ENABLE_BLUEZ_5_OFONO_HEADSET=yes, ENABLE_BLUEZ_5_OFONO_HEADSET=no) AS_IF([test "x$HAVE_BLUEZ_5_NATIVE_HEADSET" = "x1"], ENABLE_BLUEZ_5_NATIVE_HEADSET=yes, ENABLE_BLUEZ_5_NATIVE_HEADSET=no) @@ -1633,7 +1622,6 @@ echo " Enable Async DNS: ${ENABLE_LIBASYNCNS} Enable LIRC: ${ENABLE_LIRC} Enable D-Bus: ${ENABLE_DBUS} - Enable BlueZ 4: ${ENABLE_BLUEZ_4} Enable BlueZ 5: ${ENABLE_BLUEZ_5} Enable ofono headsets: ${ENABLE_BLUEZ_5_OFONO_HEADSET} Enable native headsets: ${ENABLE_BLUEZ_5_NATIVE_HEADSET} diff --git a/po/POTFILES.in b/po/POTFILES.in index 75a35c39f..0b519464a 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -14,7 +14,6 @@ src/modules/alsa/alsa-util.c src/modules/alsa/module-alsa-card.c src/modules/alsa/module-alsa-sink.c src/modules/alsa/module-alsa-source.c -src/modules/bluetooth/module-bluez4-device.c src/modules/bluetooth/module-bluez5-device.c src/modules/echo-cancel/module-echo-cancel.c src/modules/gconf/gconf-helper.c diff --git a/po/be.po b/po/be.po index 162c555a3..8c3baba2c 100644 --- a/po/be.po +++ b/po/be.po @@ -591,7 +591,6 @@ msgid "Line In" msgstr "Ð?Ñ?нейнÑ? Ñ?ваÑ?од" #: ../src/modules/alsa/alsa-mixer.c:2383 ../src/modules/alsa/alsa-mixer.c:2461 -#: ../src/modules/bluetooth/module-bluez4-device.c:2099 #: ../src/modules/bluetooth/module-bluez5-device.c:1710 msgid "Microphone" msgstr "Ð?Ñ?кÑ?аÑ?он" @@ -653,7 +652,6 @@ msgid "No Bass Boost" msgstr "Ð?ез Ñ?змаÑ?неннÑ? баÑ?оÑ?" #: ../src/modules/alsa/alsa-mixer.c:2398 -#: ../src/modules/bluetooth/module-bluez4-device.c:2104 #: ../src/modules/bluetooth/module-bluez5-device.c:1717 msgid "Speaker" msgstr "Ð?Ñ?намÑ?к" @@ -826,7 +824,6 @@ msgstr "ШмаÑ?каналÑ?нÑ? дÑ?плекÑ?" #: ../src/modules/alsa/alsa-mixer.c:4155 #: ../src/modules/alsa/module-alsa-card.c:186 -#: ../src/modules/bluetooth/module-bluez4-device.c:2295 #: ../src/modules/bluetooth/module-bluez5-device.c:1941 msgid "Off" msgstr "Ð?дклÑ?Ñ?анÑ?" @@ -961,49 +958,40 @@ msgstr "" "Ð¥Ñ?Ñ?Ñ?Ñ?й за Ñ?Ñ?Ñ?, гÑ?Ñ?а памÑ?лка Ñ? ALSA-дÑ?айвеÑ?Ñ? «%s». Ð?алÑ? лаÑ?ка, паведамÑ?Ñ?е аб" " гÑ?Ñ?Ñ?м Ñ?аÑ?пÑ?аÑ?оÑ?нÑ?кам ALSA." -#: ../src/modules/bluetooth/module-bluez4-device.c:2089 #: ../src/modules/bluetooth/module-bluez5-device.c:1700 msgid "Headset" msgstr "Ð?аÑ?нÑ?Ñ?Ñ?Ñ?а" -#: ../src/modules/bluetooth/module-bluez4-device.c:2094 #: ../src/modules/bluetooth/module-bluez5-device.c:1705 msgid "Handsfree" msgstr "Ð¥Ñ?ндÑ?-Ñ?Ñ?Ñ?" -#: ../src/modules/bluetooth/module-bluez4-device.c:2109 #: ../src/modules/bluetooth/module-bluez5-device.c:1723 msgid "Headphone" msgstr "Ð?авÑ?Ñ?нÑ?к" -#: ../src/modules/bluetooth/module-bluez4-device.c:2114 #: ../src/modules/bluetooth/module-bluez5-device.c:1728 msgid "Portable" msgstr "Ð?аÑ?Ñ?аÑ?Ñ?Ñ?наÑ? Ñ?Ñ?Ñ?Ñ?Ñ?ма" -#: ../src/modules/bluetooth/module-bluez4-device.c:2119 #: ../src/modules/bluetooth/module-bluez5-device.c:1733 msgid "Car" msgstr "Ð?Ñ?Ñ?амабÑ?лÑ?наÑ? Ñ?Ñ?Ñ?Ñ?Ñ?ма" -#: ../src/modules/bluetooth/module-bluez4-device.c:2124 #: ../src/modules/bluetooth/module-bluez5-device.c:1738 msgid "HiFi" msgstr "Hi-Fi" -#: ../src/modules/bluetooth/module-bluez4-device.c:2129 #: ../src/modules/bluetooth/module-bluez5-device.c:1743 msgid "Phone" msgstr "ТÑ?леÑ?он" -#: ../src/modules/bluetooth/module-bluez4-device.c:2137 #: ../src/modules/bluetooth/module-bluez5-device.c:1695 #: ../src/modules/bluetooth/module-bluez5-device.c:1711 #: ../src/modules/bluetooth/module-bluez5-device.c:1749 msgid "Bluetooth Output" msgstr "Bluetooth-вÑ?Ñ?ад" -#: ../src/modules/bluetooth/module-bluez4-device.c:2140 #: ../src/modules/bluetooth/module-bluez5-device.c:1694 #: ../src/modules/bluetooth/module-bluez5-device.c:1716 #: ../src/modules/bluetooth/module-bluez5-device.c:1722 @@ -1011,22 +999,6 @@ msgstr "Bluetooth-вÑ?Ñ?ад" msgid "Bluetooth Input" msgstr "Bluetooth-Ñ?ваÑ?од" -#: ../src/modules/bluetooth/module-bluez4-device.c:2176 -msgid "High Fidelity Playback (A2DP)" -msgstr "Ð?Ñ?айгÑ?аванне вÑ?Ñ?окай Ñ?каÑ?Ñ?Ñ? (A2DP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2187 -msgid "High Fidelity Capture (A2DP)" -msgstr "Ð?аÑ?оп вÑ?Ñ?окай Ñ?каÑ?Ñ?Ñ? (A2DP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2198 -msgid "Telephony Duplex (HSP/HFP)" -msgstr "ТÑ?леÑ?оннÑ? дÑ?плекÑ? (HSP/HFP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2210 -msgid "Handsfree Gateway" -msgstr "ШлÑ?з Ñ?Ñ?ндÑ?-Ñ?Ñ?Ñ?" - #: ../src/modules/bluetooth/module-bluez5-device.c:1786 msgid "High Fidelity Playback (A2DP Sink)" msgstr "Ð?Ñ?айгÑ?аванне вÑ?Ñ?окай Ñ?каÑ?Ñ?Ñ? (A2DP-пÑ?Ñ?Ñ?мнÑ?к)" diff --git a/po/de.po b/po/de.po index e73b652f7..77aa79efc 100644 --- a/po/de.po +++ b/po/de.po @@ -602,7 +602,6 @@ msgid "Line In" msgstr "Line-Eingang" #: ../src/modules/alsa/alsa-mixer.c:2383 ../src/modules/alsa/alsa-mixer.c:2461 -#: ../src/modules/bluetooth/module-bluez4-device.c:2099 #: ../src/modules/bluetooth/module-bluez5-device.c:1710 msgid "Microphone" msgstr "Mikrofon" @@ -664,7 +663,6 @@ msgid "No Bass Boost" msgstr "Keine Bassverstärkung" #: ../src/modules/alsa/alsa-mixer.c:2398 -#: ../src/modules/bluetooth/module-bluez4-device.c:2104 #: ../src/modules/bluetooth/module-bluez5-device.c:1717 msgid "Speaker" msgstr "Lautsprecher" @@ -837,7 +835,6 @@ msgstr "Mehrkanal-Duplex" #: ../src/modules/alsa/alsa-mixer.c:4155 #: ../src/modules/alsa/module-alsa-card.c:186 -#: ../src/modules/bluetooth/module-bluez4-device.c:2319 #: ../src/modules/bluetooth/module-bluez5-device.c:1965 msgid "Off" msgstr "Aus" @@ -976,49 +973,40 @@ msgstr "" "Dies ist wahrscheinlich ein Fehler im ALSA-Treiber »%s«. Bitte melden Sie " "dieses Problem den ALSA-Entwicklern." -#: ../src/modules/bluetooth/module-bluez4-device.c:2089 #: ../src/modules/bluetooth/module-bluez5-device.c:1700 msgid "Headset" msgstr "Headset" -#: ../src/modules/bluetooth/module-bluez4-device.c:2094 #: ../src/modules/bluetooth/module-bluez5-device.c:1705 msgid "Handsfree" msgstr "Freisprecheinrichtung" -#: ../src/modules/bluetooth/module-bluez4-device.c:2109 #: ../src/modules/bluetooth/module-bluez5-device.c:1723 msgid "Headphone" msgstr "Kopfhörer" -#: ../src/modules/bluetooth/module-bluez4-device.c:2114 #: ../src/modules/bluetooth/module-bluez5-device.c:1728 msgid "Portable" msgstr "" -#: ../src/modules/bluetooth/module-bluez4-device.c:2119 #: ../src/modules/bluetooth/module-bluez5-device.c:1733 msgid "Car" msgstr "Auto" -#: ../src/modules/bluetooth/module-bluez4-device.c:2124 #: ../src/modules/bluetooth/module-bluez5-device.c:1738 msgid "HiFi" msgstr "HiFi" -#: ../src/modules/bluetooth/module-bluez4-device.c:2129 #: ../src/modules/bluetooth/module-bluez5-device.c:1743 msgid "Phone" msgstr "Telefon" -#: ../src/modules/bluetooth/module-bluez4-device.c:2137 #: ../src/modules/bluetooth/module-bluez5-device.c:1695 #: ../src/modules/bluetooth/module-bluez5-device.c:1711 #: ../src/modules/bluetooth/module-bluez5-device.c:1749 msgid "Bluetooth Output" msgstr "Bluetooth-Ausgabe" -#: ../src/modules/bluetooth/module-bluez4-device.c:2140 #: ../src/modules/bluetooth/module-bluez5-device.c:1694 #: ../src/modules/bluetooth/module-bluez5-device.c:1716 #: ../src/modules/bluetooth/module-bluez5-device.c:1722 @@ -1026,22 +1014,6 @@ msgstr "Bluetooth-Ausgabe" msgid "Bluetooth Input" msgstr "Bluetooth-Eingabe" -#: ../src/modules/bluetooth/module-bluez4-device.c:2181 -msgid "High Fidelity Playback (A2DP)" -msgstr "High Fidelity Playback (A2DP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2193 -msgid "High Fidelity Capture (A2DP)" -msgstr "High Fidelity Capture (A2DP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2205 -msgid "Telephony Duplex (HSP/HFP)" -msgstr "Telephony Duplex (HSP/HFP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2218 -msgid "Handsfree Gateway" -msgstr "" - #: ../src/modules/bluetooth/module-bluez5-device.c:1790 msgid "High Fidelity Playback (A2DP Sink)" msgstr "High Fidelity Playback (A2DP-Ziel)" diff --git a/po/el.po b/po/el.po index cfa0e46a4..c877b0969 100644 --- a/po/el.po +++ b/po/el.po @@ -840,7 +840,6 @@ msgid "Line In" msgstr "Î?Ï?αμμή ειÏ?Ï?δοÏ?" #: ../src/modules/alsa/alsa-mixer.c:2256 ../src/modules/alsa/alsa-mixer.c:2334 -#: ../src/modules/bluetooth/module-bluez4-device.c:2101 #: ../src/modules/bluetooth/module-bluez5-device.c:1451 msgid "Microphone" msgstr "Î?ικÏ?Ï?Ï?Ï?νο" @@ -902,7 +901,6 @@ msgid "No Bass Boost" msgstr "ΧÏ?Ï?ίÏ? ενίÏ?Ï?Ï?Ï?η μÏ?άÏ?Ï?ν" #: ../src/modules/alsa/alsa-mixer.c:2271 -#: ../src/modules/bluetooth/module-bluez4-device.c:2106 #: ../src/modules/bluetooth/module-bluez5-device.c:1458 msgid "Speaker" msgstr "Î?Ï?είο" @@ -1057,7 +1055,6 @@ msgstr "ΨηÏ?ιακÏ?Ï? Ï?Ï?εÏ?εοÏ?Ï?νικÏ?Ï? αμÏ?ίδÏ?ομοÏ? (IEC958 #: ../src/modules/alsa/alsa-mixer.c:3959 #: ../src/modules/alsa/module-alsa-card.c:193 -#: ../src/modules/bluetooth/module-bluez4-device.c:2297 #: ../src/modules/bluetooth/module-bluez5-device.c:1656 msgid "Off" msgstr "Î?νενεÏ?γÏ?" @@ -1158,49 +1155,40 @@ msgstr "" "Το Ï?ιθανÏ?Ï?εÏ?ο αÏ?Ï?Ï? είναι Îνα Ï?Ï?άλμα Ï?Ï?ον οδηγÏ? ALSA '%s'. ΠαÏ?ακαλοÏ?με, " "αναÏ?ÎÏ?Ï?ε αÏ?Ï?Ï? Ï?ο θÎμα Ï?Ï?οÏ?Ï? Ï?Ï?ογÏ?αμμαÏ?ιÏ?Ï?ÎÏ? ALSA." -#: ../src/modules/bluetooth/module-bluez4-device.c:2091 #: ../src/modules/bluetooth/module-bluez5-device.c:1441 msgid "Headset" msgstr "Î?κοÏ?Ï?Ï?ικά" -#: ../src/modules/bluetooth/module-bluez4-device.c:2096 #: ../src/modules/bluetooth/module-bluez5-device.c:1446 msgid "Handsfree" msgstr "Î?νοιÏ?Ï?ήÏ? ακÏ?Ï?αÏ?ηÏ?" -#: ../src/modules/bluetooth/module-bluez4-device.c:2111 #: ../src/modules/bluetooth/module-bluez5-device.c:1464 msgid "Headphone" msgstr "Î?κοÏ?Ï?Ï?ικÏ?" -#: ../src/modules/bluetooth/module-bluez4-device.c:2116 #: ../src/modules/bluetooth/module-bluez5-device.c:1469 msgid "Portable" msgstr "ΦοÏ?ηÏ?Ï?" -#: ../src/modules/bluetooth/module-bluez4-device.c:2121 #: ../src/modules/bluetooth/module-bluez5-device.c:1474 msgid "Car" msgstr "Î?Ï?Ï?οκίνηÏ?ο" -#: ../src/modules/bluetooth/module-bluez4-device.c:2126 #: ../src/modules/bluetooth/module-bluez5-device.c:1479 msgid "HiFi" msgstr "Î¥Ï?ηλή Ï?ιÏ?Ï?Ï?Ï?ηÏ?α" -#: ../src/modules/bluetooth/module-bluez4-device.c:2131 #: ../src/modules/bluetooth/module-bluez5-device.c:1484 msgid "Phone" msgstr "ΤηλÎÏ?Ï?νο" -#: ../src/modules/bluetooth/module-bluez4-device.c:2139 #: ../src/modules/bluetooth/module-bluez5-device.c:1436 #: ../src/modules/bluetooth/module-bluez5-device.c:1452 #: ../src/modules/bluetooth/module-bluez5-device.c:1490 msgid "Bluetooth Output" msgstr "Î?ξοδοÏ? μÏ?λοÏ?Ï?οÏ?θ" -#: ../src/modules/bluetooth/module-bluez4-device.c:2142 #: ../src/modules/bluetooth/module-bluez5-device.c:1435 #: ../src/modules/bluetooth/module-bluez5-device.c:1457 #: ../src/modules/bluetooth/module-bluez5-device.c:1463 @@ -1208,22 +1196,6 @@ msgstr "Î?ξοδοÏ? μÏ?λοÏ?Ï?οÏ?θ" msgid "Bluetooth Input" msgstr "Î?ίÏ?οδοÏ? μÏ?λοÏ?Ï?οÏ?θ" -#: ../src/modules/bluetooth/module-bluez4-device.c:2178 -msgid "High Fidelity Playback (A2DP)" -msgstr "Î?ναÏ?αÏ?αγÏ?γή Ï?Ï?ηλήÏ? Ï?οιÏ?Ï?ηÏ?α (A2DP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2189 -msgid "High Fidelity Capture (A2DP)" -msgstr "Î?ήÏ?η Ï?Ï?ηλήÏ? Ï?οιÏ?Ï?ηÏ?αÏ? (A2DP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2200 -msgid "Telephony Duplex (HSP/HFP)" -msgstr "Î?μÏ?ίδÏ?ομη Ï?ηλεÏ?Ï?νία (HSP/HFP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2212 -msgid "Handsfree Gateway" -msgstr "Î Ï?λη ανοιÏ?Ï?ήÏ? ακÏ?Ï?αÏ?ηÏ?" - #. TODO: Change this profile's name to a2dp_sink, to reflect the remote #. * device's role and be consistent with the a2dp source profile #: ../src/modules/bluetooth/module-bluez5-device.c:1529 diff --git a/po/fr.po b/po/fr.po index 6a682c528..2abbfb729 100644 --- a/po/fr.po +++ b/po/fr.po @@ -606,7 +606,6 @@ msgid "Line In" msgstr "Entrée ligne" #: ../src/modules/alsa/alsa-mixer.c:2296 ../src/modules/alsa/alsa-mixer.c:2374 -#: ../src/modules/bluetooth/module-bluez4-device.c:2102 #: ../src/modules/bluetooth/module-bluez5-device.c:1710 msgid "Microphone" msgstr "Microphone" @@ -668,7 +667,6 @@ msgid "No Bass Boost" msgstr "Pas de booster de basses" #: ../src/modules/alsa/alsa-mixer.c:2311 -#: ../src/modules/bluetooth/module-bluez4-device.c:2107 #: ../src/modules/bluetooth/module-bluez5-device.c:1717 msgid "Speaker" msgstr "Haut-parleur" @@ -823,7 +821,6 @@ msgstr "Duplex stéréo numérique (IEC958)" #: ../src/modules/alsa/alsa-mixer.c:4052 #: ../src/modules/alsa/module-alsa-card.c:190 -#: ../src/modules/bluetooth/module-bluez4-device.c:2298 #: ../src/modules/bluetooth/module-bluez5-device.c:1941 msgid "Off" msgstr "Ã?teint" @@ -924,49 +921,40 @@ msgstr "" "Il s'agit très probablement d'un bogue dans le pilote ALSA « %s ». Veuillez " "rapporter ce problème aux développeurs d'ALSA." -#: ../src/modules/bluetooth/module-bluez4-device.c:2092 #: ../src/modules/bluetooth/module-bluez5-device.c:1700 msgid "Headset" msgstr "Casque" -#: ../src/modules/bluetooth/module-bluez4-device.c:2097 #: ../src/modules/bluetooth/module-bluez5-device.c:1705 msgid "Handsfree" msgstr "Mains-libres" -#: ../src/modules/bluetooth/module-bluez4-device.c:2112 #: ../src/modules/bluetooth/module-bluez5-device.c:1723 msgid "Headphone" msgstr "Ã?couteurs" -#: ../src/modules/bluetooth/module-bluez4-device.c:2117 #: ../src/modules/bluetooth/module-bluez5-device.c:1728 msgid "Portable" msgstr "Portable" -#: ../src/modules/bluetooth/module-bluez4-device.c:2122 #: ../src/modules/bluetooth/module-bluez5-device.c:1733 msgid "Car" msgstr "Voiture" -#: ../src/modules/bluetooth/module-bluez4-device.c:2127 #: ../src/modules/bluetooth/module-bluez5-device.c:1738 msgid "HiFi" msgstr "HiFi" -#: ../src/modules/bluetooth/module-bluez4-device.c:2132 #: ../src/modules/bluetooth/module-bluez5-device.c:1743 msgid "Phone" msgstr "Téléphone" -#: ../src/modules/bluetooth/module-bluez4-device.c:2140 #: ../src/modules/bluetooth/module-bluez5-device.c:1695 #: ../src/modules/bluetooth/module-bluez5-device.c:1711 #: ../src/modules/bluetooth/module-bluez5-device.c:1749 msgid "Bluetooth Output" msgstr "Sortie Bluetooth" -#: ../src/modules/bluetooth/module-bluez4-device.c:2143 #: ../src/modules/bluetooth/module-bluez5-device.c:1694 #: ../src/modules/bluetooth/module-bluez5-device.c:1716 #: ../src/modules/bluetooth/module-bluez5-device.c:1722 @@ -974,22 +962,6 @@ msgstr "Sortie Bluetooth" msgid "Bluetooth Input" msgstr "Entrée Bluetooth" -#: ../src/modules/bluetooth/module-bluez4-device.c:2179 -msgid "High Fidelity Playback (A2DP)" -msgstr "Lecture haute fidélité (A2DP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2190 -msgid "High Fidelity Capture (A2DP)" -msgstr "Capture haute fidélité (A2DP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2201 -msgid "Telephony Duplex (HSP/HFP)" -msgstr "Telephonie en duplex (HSP/HFP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2213 -msgid "Handsfree Gateway" -msgstr "Passerelle Mains-libres" - #: ../src/modules/bluetooth/module-bluez5-device.c:1786 msgid "High Fidelity Playback (A2DP Sink)" msgstr "Lecture haute fidélité (A2DP Sink)" diff --git a/po/hr.po b/po/hr.po index 3afd72004..fd9322d94 100644 --- a/po/hr.po +++ b/po/hr.po @@ -597,7 +597,6 @@ msgid "Line In" msgstr "Ulaz" #: ../src/modules/alsa/alsa-mixer.c:2383 ../src/modules/alsa/alsa-mixer.c:2461 -#: ../src/modules/bluetooth/module-bluez4-device.c:2104 #: ../src/modules/bluetooth/module-bluez5-device.c:1696 msgid "Microphone" msgstr "Mikrofon" @@ -659,7 +658,6 @@ msgid "No Bass Boost" msgstr "Bez pojaÄ?anja basa" #: ../src/modules/alsa/alsa-mixer.c:2398 -#: ../src/modules/bluetooth/module-bluez4-device.c:2109 #: ../src/modules/bluetooth/module-bluez5-device.c:1703 msgid "Speaker" msgstr "ZvuÄ?nik" @@ -832,7 +830,6 @@ msgstr "ViÅ¡ekanalni obostrani" #: ../src/modules/alsa/alsa-mixer.c:4155 #: ../src/modules/alsa/module-alsa-card.c:186 -#: ../src/modules/bluetooth/module-bluez4-device.c:2324 #: ../src/modules/bluetooth/module-bluez5-device.c:1951 msgid "Off" msgstr "IskljuÄ?eno" @@ -967,49 +964,40 @@ msgstr "" "Najvjerojatnije je ovo greÅ¡ka ALSA upravljaÄ?kog programa '%s'. Prijavite " "problem ALSA razvijateljima." -#: ../src/modules/bluetooth/module-bluez4-device.c:2094 #: ../src/modules/bluetooth/module-bluez5-device.c:1686 msgid "Headset" msgstr "SluÅ¡alice s mikrofonom" -#: ../src/modules/bluetooth/module-bluez4-device.c:2099 #: ../src/modules/bluetooth/module-bluez5-device.c:1691 msgid "Handsfree" msgstr "Bez-ruku" -#: ../src/modules/bluetooth/module-bluez4-device.c:2114 #: ../src/modules/bluetooth/module-bluez5-device.c:1709 msgid "Headphone" msgstr "SluÅ¡alice" -#: ../src/modules/bluetooth/module-bluez4-device.c:2119 #: ../src/modules/bluetooth/module-bluez5-device.c:1714 msgid "Portable" msgstr "Prijenosnik" -#: ../src/modules/bluetooth/module-bluez4-device.c:2124 #: ../src/modules/bluetooth/module-bluez5-device.c:1719 msgid "Car" msgstr "Automobil" -#: ../src/modules/bluetooth/module-bluez4-device.c:2129 #: ../src/modules/bluetooth/module-bluez5-device.c:1724 msgid "HiFi" msgstr "HiFi" -#: ../src/modules/bluetooth/module-bluez4-device.c:2134 #: ../src/modules/bluetooth/module-bluez5-device.c:1729 msgid "Phone" msgstr "Telefon" -#: ../src/modules/bluetooth/module-bluez4-device.c:2142 #: ../src/modules/bluetooth/module-bluez5-device.c:1681 #: ../src/modules/bluetooth/module-bluez5-device.c:1697 #: ../src/modules/bluetooth/module-bluez5-device.c:1735 msgid "Bluetooth Output" msgstr "Bluetooth izlaz" -#: ../src/modules/bluetooth/module-bluez4-device.c:2145 #: ../src/modules/bluetooth/module-bluez5-device.c:1680 #: ../src/modules/bluetooth/module-bluez5-device.c:1702 #: ../src/modules/bluetooth/module-bluez5-device.c:1708 @@ -1017,22 +1005,6 @@ msgstr "Bluetooth izlaz" msgid "Bluetooth Input" msgstr "Bluetooth ulaz" -#: ../src/modules/bluetooth/module-bluez4-device.c:2186 -msgid "High Fidelity Playback (A2DP)" -msgstr "Reprodukcija visoke autentiÄ?nosti (A2DP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2198 -msgid "High Fidelity Capture (A2DP)" -msgstr "Snimanje visoke autentiÄ?nosti (A2DP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2210 -msgid "Telephony Duplex (HSP/HFP)" -msgstr "Obostrana telefonija (HSP/HFP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2223 -msgid "Handsfree Gateway" -msgstr "BezruÄ?ni pristupnik" - #: ../src/modules/bluetooth/module-bluez5-device.c:1776 msgid "High Fidelity Playback (A2DP Sink)" msgstr "Reprodukcija visoke autentiÄ?nosti (A2DP slivnik)" diff --git a/po/hu.po b/po/hu.po index bcb39d8c0..64b57b7cd 100644 --- a/po/hu.po +++ b/po/hu.po @@ -609,7 +609,6 @@ msgid "Line In" msgstr "Vonalbemenet" #: ../src/modules/alsa/alsa-mixer.c:2383 ../src/modules/alsa/alsa-mixer.c:2461 -#: ../src/modules/bluetooth/module-bluez4-device.c:2099 #: ../src/modules/bluetooth/module-bluez5-device.c:1710 msgid "Microphone" msgstr "Mikrofon" @@ -671,7 +670,6 @@ msgid "No Bass Boost" msgstr "Nincs basszuskiemelés" #: ../src/modules/alsa/alsa-mixer.c:2398 -#: ../src/modules/bluetooth/module-bluez4-device.c:2104 #: ../src/modules/bluetooth/module-bluez5-device.c:1717 msgid "Speaker" msgstr "Hangszóró" @@ -844,7 +842,6 @@ msgstr "Többcsatornás duplex" #: ../src/modules/alsa/alsa-mixer.c:4155 #: ../src/modules/alsa/module-alsa-card.c:186 -#: ../src/modules/bluetooth/module-bluez4-device.c:2319 #: ../src/modules/bluetooth/module-bluez5-device.c:1965 msgid "Off" msgstr "Kikapcsolva" @@ -983,50 +980,41 @@ msgstr "" "Ez valószÃnűleg egy hiba eredménye az ALSA â??%sâ?? illesztÅ?programban. Jelentse " "ezt a problémát az ALSA fejlesztÅ?i felé." -#: ../src/modules/bluetooth/module-bluez4-device.c:2089 #: ../src/modules/bluetooth/module-bluez5-device.c:1700 msgid "Headset" msgstr "Fejhallgató" # FIXME: utánanézni -#: ../src/modules/bluetooth/module-bluez4-device.c:2094 #: ../src/modules/bluetooth/module-bluez5-device.c:1705 msgid "Handsfree" msgstr "KihangosÃtó" -#: ../src/modules/bluetooth/module-bluez4-device.c:2109 #: ../src/modules/bluetooth/module-bluez5-device.c:1723 msgid "Headphone" msgstr "Fülhallgató" -#: ../src/modules/bluetooth/module-bluez4-device.c:2114 #: ../src/modules/bluetooth/module-bluez5-device.c:1728 msgid "Portable" msgstr "Hordozható" -#: ../src/modules/bluetooth/module-bluez4-device.c:2119 #: ../src/modules/bluetooth/module-bluez5-device.c:1733 msgid "Car" msgstr "Autó" -#: ../src/modules/bluetooth/module-bluez4-device.c:2124 #: ../src/modules/bluetooth/module-bluez5-device.c:1738 msgid "HiFi" msgstr "Hi-Fi" -#: ../src/modules/bluetooth/module-bluez4-device.c:2129 #: ../src/modules/bluetooth/module-bluez5-device.c:1743 msgid "Phone" msgstr "Telefon" -#: ../src/modules/bluetooth/module-bluez4-device.c:2137 #: ../src/modules/bluetooth/module-bluez5-device.c:1695 #: ../src/modules/bluetooth/module-bluez5-device.c:1711 #: ../src/modules/bluetooth/module-bluez5-device.c:1749 msgid "Bluetooth Output" msgstr "Bluetooth kimenet" -#: ../src/modules/bluetooth/module-bluez4-device.c:2140 #: ../src/modules/bluetooth/module-bluez5-device.c:1694 #: ../src/modules/bluetooth/module-bluez5-device.c:1716 #: ../src/modules/bluetooth/module-bluez5-device.c:1722 @@ -1034,22 +1022,6 @@ msgstr "Bluetooth kimenet" msgid "Bluetooth Input" msgstr "Bluetooth bemenet" -#: ../src/modules/bluetooth/module-bluez4-device.c:2181 -msgid "High Fidelity Playback (A2DP)" -msgstr "Hi-Fi lejátszás (A2DP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2193 -msgid "High Fidelity Capture (A2DP)" -msgstr "Hi-Fi felvétel (A2DP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2205 -msgid "Telephony Duplex (HSP/HFP)" -msgstr "Telefon duplex (HSP/HFP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2218 -msgid "Handsfree Gateway" -msgstr "KihangosÃtó átjáró" - #: ../src/modules/bluetooth/module-bluez5-device.c:1790 msgid "High Fidelity Playback (A2DP Sink)" msgstr "Hi-Fi lejátszás (A2DP bemenet)" diff --git a/po/id.po b/po/id.po index d61df675d..4509d548b 100644 --- a/po/id.po +++ b/po/id.po @@ -590,7 +590,6 @@ msgid "Line In" msgstr "Jalur Masuk" #: ../src/modules/alsa/alsa-mixer.c:2448 ../src/modules/alsa/alsa-mixer.c:2526 -#: ../src/modules/bluetooth/module-bluez4-device.c:2103 #: ../src/modules/bluetooth/module-bluez5-device.c:1781 msgid "Microphone" msgstr "Mikrofon" @@ -652,7 +651,6 @@ msgid "No Bass Boost" msgstr "Tanpa Boost Bass" #: ../src/modules/alsa/alsa-mixer.c:2463 -#: ../src/modules/bluetooth/module-bluez4-device.c:2108 #: ../src/modules/bluetooth/module-bluez5-device.c:1788 msgid "Speaker" msgstr "Speaker" @@ -839,7 +837,6 @@ msgstr "Dupleks Stereo" #: ../src/modules/alsa/alsa-mixer.c:4226 #: ../src/modules/alsa/module-alsa-card.c:185 -#: ../src/modules/bluetooth/module-bluez4-device.c:2323 #: ../src/modules/bluetooth/module-bluez5-device.c:2036 msgid "Off" msgstr "Mati" @@ -974,49 +971,40 @@ msgstr "" "Sangat mungkin ini adalah kutu pada driver ALSA '%s'. Silakan laporkan hal " "ini ke para pengembang ALSA." -#: ../src/modules/bluetooth/module-bluez4-device.c:2093 #: ../src/modules/bluetooth/module-bluez5-device.c:1771 msgid "Headset" msgstr "Headset" -#: ../src/modules/bluetooth/module-bluez4-device.c:2098 #: ../src/modules/bluetooth/module-bluez5-device.c:1776 msgid "Handsfree" msgstr "Handsfree" -#: ../src/modules/bluetooth/module-bluez4-device.c:2113 #: ../src/modules/bluetooth/module-bluez5-device.c:1794 msgid "Headphone" msgstr "Headphone" -#: ../src/modules/bluetooth/module-bluez4-device.c:2118 #: ../src/modules/bluetooth/module-bluez5-device.c:1799 msgid "Portable" msgstr "Portabel" -#: ../src/modules/bluetooth/module-bluez4-device.c:2123 #: ../src/modules/bluetooth/module-bluez5-device.c:1804 msgid "Car" msgstr "Mobil" -#: ../src/modules/bluetooth/module-bluez4-device.c:2128 #: ../src/modules/bluetooth/module-bluez5-device.c:1809 msgid "HiFi" msgstr "HiFi" -#: ../src/modules/bluetooth/module-bluez4-device.c:2133 #: ../src/modules/bluetooth/module-bluez5-device.c:1814 msgid "Phone" msgstr "Telepon" -#: ../src/modules/bluetooth/module-bluez4-device.c:2141 #: ../src/modules/bluetooth/module-bluez5-device.c:1766 #: ../src/modules/bluetooth/module-bluez5-device.c:1782 #: ../src/modules/bluetooth/module-bluez5-device.c:1820 msgid "Bluetooth Output" msgstr "Keluaran Bluetooth" -#: ../src/modules/bluetooth/module-bluez4-device.c:2144 #: ../src/modules/bluetooth/module-bluez5-device.c:1765 #: ../src/modules/bluetooth/module-bluez5-device.c:1787 #: ../src/modules/bluetooth/module-bluez5-device.c:1793 @@ -1024,22 +1012,6 @@ msgstr "Keluaran Bluetooth" msgid "Bluetooth Input" msgstr "Masukan Bluetooth" -#: ../src/modules/bluetooth/module-bluez4-device.c:2185 -msgid "High Fidelity Playback (A2DP)" -msgstr "Main Ulang High Fidelity (A2DP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2197 -msgid "High Fidelity Capture (A2DP)" -msgstr "High Fidelity Capture (A2DP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2209 -msgid "Telephony Duplex (HSP/HFP)" -msgstr "Dupleks Teleponi (HSP/HFP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2222 -msgid "Handsfree Gateway" -msgstr "Gateway Handsfree" - #: ../src/modules/bluetooth/module-bluez5-device.c:1861 #, fuzzy msgid "High Fidelity Playback (A2DP Sink)" diff --git a/po/it.po b/po/it.po index d71d74c9f..151ff3187 100644 --- a/po/it.po +++ b/po/it.po @@ -619,7 +619,6 @@ msgid "Line In" msgstr "Line-In" #: ../src/modules/alsa/alsa-mixer.c:2383 ../src/modules/alsa/alsa-mixer.c:2461 -#: ../src/modules/bluetooth/module-bluez4-device.c:2104 #: ../src/modules/bluetooth/module-bluez5-device.c:1750 msgid "Microphone" msgstr "Microfono" @@ -681,7 +680,6 @@ msgid "No Bass Boost" msgstr "Nessun incremento bassi" #: ../src/modules/alsa/alsa-mixer.c:2398 -#: ../src/modules/bluetooth/module-bluez4-device.c:2109 #: ../src/modules/bluetooth/module-bluez5-device.c:1757 msgid "Speaker" msgstr "Altoparlante" @@ -862,7 +860,6 @@ msgstr "Duplex stereo" #: ../src/modules/alsa/alsa-mixer.c:4157 #: ../src/modules/alsa/module-alsa-card.c:186 -#: ../src/modules/bluetooth/module-bluez4-device.c:2324 #: ../src/modules/bluetooth/module-bluez5-device.c:2005 msgid "Off" msgstr "Spento" @@ -995,49 +992,40 @@ msgstr "" "Molto probabilmente si tratta di un bug nel driver ALSA \"%s\". Segnalare " "questo problema agli sviluppatori ALSA." -#: ../src/modules/bluetooth/module-bluez4-device.c:2094 #: ../src/modules/bluetooth/module-bluez5-device.c:1740 msgid "Headset" msgstr "Cuffie con microfono" -#: ../src/modules/bluetooth/module-bluez4-device.c:2099 #: ../src/modules/bluetooth/module-bluez5-device.c:1745 msgid "Handsfree" msgstr "Sistema mani-libere" -#: ../src/modules/bluetooth/module-bluez4-device.c:2114 #: ../src/modules/bluetooth/module-bluez5-device.c:1763 msgid "Headphone" msgstr "Cuffie" -#: ../src/modules/bluetooth/module-bluez4-device.c:2119 #: ../src/modules/bluetooth/module-bluez5-device.c:1768 msgid "Portable" msgstr "Portabile" -#: ../src/modules/bluetooth/module-bluez4-device.c:2124 #: ../src/modules/bluetooth/module-bluez5-device.c:1773 msgid "Car" msgstr "Automobile" -#: ../src/modules/bluetooth/module-bluez4-device.c:2129 #: ../src/modules/bluetooth/module-bluez5-device.c:1778 msgid "HiFi" msgstr "HiFi" -#: ../src/modules/bluetooth/module-bluez4-device.c:2134 #: ../src/modules/bluetooth/module-bluez5-device.c:1783 msgid "Phone" msgstr "Telefono" -#: ../src/modules/bluetooth/module-bluez4-device.c:2142 #: ../src/modules/bluetooth/module-bluez5-device.c:1735 #: ../src/modules/bluetooth/module-bluez5-device.c:1751 #: ../src/modules/bluetooth/module-bluez5-device.c:1789 msgid "Bluetooth Output" msgstr "Uscita Bluetooth" -#: ../src/modules/bluetooth/module-bluez4-device.c:2145 #: ../src/modules/bluetooth/module-bluez5-device.c:1734 #: ../src/modules/bluetooth/module-bluez5-device.c:1756 #: ../src/modules/bluetooth/module-bluez5-device.c:1762 @@ -1045,22 +1033,6 @@ msgstr "Uscita Bluetooth" msgid "Bluetooth Input" msgstr "Ingresso Bluetooth" -#: ../src/modules/bluetooth/module-bluez4-device.c:2186 -msgid "High Fidelity Playback (A2DP)" -msgstr "Riproduzione ad alta fedeltà (A2DP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2198 -msgid "High Fidelity Capture (A2DP)" -msgstr "Cattura ad alta fedeltà (A2DP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2210 -msgid "Telephony Duplex (HSP/HFP)" -msgstr "Doppino telefonico (HSP/HFP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2223 -msgid "Handsfree Gateway" -msgstr "Gateway handsfree" - #: ../src/modules/bluetooth/module-bluez5-device.c:1830 msgid "High Fidelity Playback (A2DP Sink)" msgstr "Riproduzione ad alta fedeltà (sink A2DP)" diff --git a/po/lt.po b/po/lt.po index d8bee2f7e..a704bec7b 100644 --- a/po/lt.po +++ b/po/lt.po @@ -602,7 +602,6 @@ msgid "Line In" msgstr "Ä®vadinÄ? linija" #: ../src/modules/alsa/alsa-mixer.c:2383 ../src/modules/alsa/alsa-mixer.c:2461 -#: ../src/modules/bluetooth/module-bluez4-device.c:2104 #: ../src/modules/bluetooth/module-bluez5-device.c:1783 msgid "Microphone" msgstr "Mikrofonas" @@ -664,7 +663,6 @@ msgid "No Bass Boost" msgstr "Be žemų tonų pastiprinimo" #: ../src/modules/alsa/alsa-mixer.c:2398 -#: ../src/modules/bluetooth/module-bluez4-device.c:2109 #: ../src/modules/bluetooth/module-bluez5-device.c:1790 msgid "Speaker" msgstr "Garsiakalbis" @@ -849,7 +847,6 @@ msgstr "DvipusÄ? stereo" #: ../src/modules/alsa/alsa-mixer.c:4158 #: ../src/modules/alsa/module-alsa-card.c:186 -#: ../src/modules/bluetooth/module-bluez4-device.c:2324 #: ../src/modules/bluetooth/module-bluez5-device.c:2038 msgid "Off" msgstr "IÅ¡jungta" @@ -984,49 +981,40 @@ msgstr "" "GreiÄ?iausiai, tai yra klaida ALSA \"'%s\" tvarkyklÄ?je. PraÅ¡ome apie Å¡iÄ? " "klaidÄ? praneÅ¡ti ALSA kÅ«rÄ?jams." -#: ../src/modules/bluetooth/module-bluez4-device.c:2094 #: ../src/modules/bluetooth/module-bluez5-device.c:1773 msgid "Headset" msgstr "AusinÄ?s su mikrofonu" -#: ../src/modules/bluetooth/module-bluez4-device.c:2099 #: ../src/modules/bluetooth/module-bluez5-device.c:1778 msgid "Handsfree" msgstr "Laisvų rankų įranga" -#: ../src/modules/bluetooth/module-bluez4-device.c:2114 #: ../src/modules/bluetooth/module-bluez5-device.c:1796 msgid "Headphone" msgstr "AusinÄ?" -#: ../src/modules/bluetooth/module-bluez4-device.c:2119 #: ../src/modules/bluetooth/module-bluez5-device.c:1801 msgid "Portable" msgstr "Portatyvi sistema" -#: ../src/modules/bluetooth/module-bluez4-device.c:2124 #: ../src/modules/bluetooth/module-bluez5-device.c:1806 msgid "Car" msgstr "Automobilis" -#: ../src/modules/bluetooth/module-bluez4-device.c:2129 #: ../src/modules/bluetooth/module-bluez5-device.c:1811 msgid "HiFi" msgstr "HiFi" -#: ../src/modules/bluetooth/module-bluez4-device.c:2134 #: ../src/modules/bluetooth/module-bluez5-device.c:1816 msgid "Phone" msgstr "Telefonas" -#: ../src/modules/bluetooth/module-bluez4-device.c:2142 #: ../src/modules/bluetooth/module-bluez5-device.c:1768 #: ../src/modules/bluetooth/module-bluez5-device.c:1784 #: ../src/modules/bluetooth/module-bluez5-device.c:1822 msgid "Bluetooth Output" msgstr "Bluetooth iÅ¡vestis" -#: ../src/modules/bluetooth/module-bluez4-device.c:2145 #: ../src/modules/bluetooth/module-bluez5-device.c:1767 #: ../src/modules/bluetooth/module-bluez5-device.c:1789 #: ../src/modules/bluetooth/module-bluez5-device.c:1795 @@ -1034,22 +1022,6 @@ msgstr "Bluetooth iÅ¡vestis" msgid "Bluetooth Input" msgstr "Bluetooth įvestis" -#: ../src/modules/bluetooth/module-bluez4-device.c:2186 -msgid "High Fidelity Playback (A2DP)" -msgstr "AukÅ¡tos kokybÄ?s atkÅ«rimas (A2DP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2198 -msgid "High Fidelity Capture (A2DP)" -msgstr "AukÅ¡tos kokybÄ?s paÄ?mimas (A2DP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2210 -msgid "Telephony Duplex (HSP/HFP)" -msgstr "TelefoninÄ? dvipusÄ? (HSP/HFP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2223 -msgid "Handsfree Gateway" -msgstr "Laisvų rankų įrangos tinklų sietuvas" - #: ../src/modules/bluetooth/module-bluez5-device.c:1863 msgid "High Fidelity Playback (A2DP Sink)" msgstr "AukÅ¡tos kokybÄ?s atkÅ«rimas (A2DP rinktuvas)" diff --git a/po/nn.po b/po/nn.po index f6121d1eb..7bce73860 100644 --- a/po/nn.po +++ b/po/nn.po @@ -568,7 +568,6 @@ msgid "Line In" msgstr "Linje inn" #: ../src/modules/alsa/alsa-mixer.c:2383 ../src/modules/alsa/alsa-mixer.c:2461 -#: ../src/modules/bluetooth/module-bluez4-device.c:2104 #: ../src/modules/bluetooth/module-bluez5-device.c:1750 msgid "Microphone" msgstr "Mikrofon" @@ -643,7 +642,6 @@ msgid "No Bass Boost" msgstr "Inga bassforsterking" #: ../src/modules/alsa/alsa-mixer.c:2398 -#: ../src/modules/bluetooth/module-bluez4-device.c:2109 #: ../src/modules/bluetooth/module-bluez5-device.c:1757 msgid "Speaker" msgstr "Høgtalar" @@ -845,7 +843,6 @@ msgstr "Stereo dupleks" #: ../src/modules/alsa/alsa-mixer.c:4157 #: ../src/modules/alsa/module-alsa-card.c:186 -#: ../src/modules/bluetooth/module-bluez4-device.c:2324 #: ../src/modules/bluetooth/module-bluez5-device.c:2005 msgid "Off" msgstr "Av" @@ -943,50 +940,42 @@ msgstr "" "snd_pcm_mmap_begin() gav ein verdi som er uvanleg stor: %lu byte (%lu ms).\n" "Dette kjem truleg av ein feil i ALSA-drivaren «%s». Meld frÃ¥ om problemet til ALSA-utviklarane." -#: ../src/modules/bluetooth/module-bluez4-device.c:2094 #: ../src/modules/bluetooth/module-bluez5-device.c:1740 #| msgctxt "This device is a Headset" #| msgid "Headset" msgid "Headset" msgstr "Hovudsett" -#: ../src/modules/bluetooth/module-bluez4-device.c:2099 #: ../src/modules/bluetooth/module-bluez5-device.c:1745 #| msgctxt "For holding pieces" #| msgid "Hand" msgid "Handsfree" msgstr "Handfri" -#: ../src/modules/bluetooth/module-bluez4-device.c:2114 #: ../src/modules/bluetooth/module-bluez5-device.c:1763 msgid "Headphone" msgstr "Hovudtelefonar" -#: ../src/modules/bluetooth/module-bluez4-device.c:2119 #: ../src/modules/bluetooth/module-bluez5-device.c:1768 #| msgctxt "portugal_districts.kgm" #| msgid "Portalegre" msgid "Portable" msgstr "Portabel" -#: ../src/modules/bluetooth/module-bluez4-device.c:2124 #: ../src/modules/bluetooth/module-bluez5-device.c:1773 msgid "Car" msgstr "Bil" -#: ../src/modules/bluetooth/module-bluez4-device.c:2129 #: ../src/modules/bluetooth/module-bluez5-device.c:1778 msgid "HiFi" msgstr "Hi-fi" -#: ../src/modules/bluetooth/module-bluez4-device.c:2134 #: ../src/modules/bluetooth/module-bluez5-device.c:1783 #| msgctxt "Name" #| msgid "Phone" msgid "Phone" msgstr "Telefon" -#: ../src/modules/bluetooth/module-bluez4-device.c:2142 #: ../src/modules/bluetooth/module-bluez5-device.c:1735 #: ../src/modules/bluetooth/module-bluez5-device.c:1751 #: ../src/modules/bluetooth/module-bluez5-device.c:1789 @@ -995,7 +984,6 @@ msgstr "Telefon" msgid "Bluetooth Output" msgstr "Bluetooth-utlyd" -#: ../src/modules/bluetooth/module-bluez4-device.c:2145 #: ../src/modules/bluetooth/module-bluez5-device.c:1734 #: ../src/modules/bluetooth/module-bluez5-device.c:1756 #: ../src/modules/bluetooth/module-bluez5-device.c:1762 @@ -1005,22 +993,6 @@ msgstr "Bluetooth-utlyd" msgid "Bluetooth Input" msgstr "Bluetooth-innlyd" -#: ../src/modules/bluetooth/module-bluez4-device.c:2186 -msgid "High Fidelity Playback (A2DP)" -msgstr "Hi-fi-avspeling (A2DP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2198 -msgid "High Fidelity Capture (A2DP)" -msgstr "Hi-fi-opptak (A2DP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2210 -msgid "Telephony Duplex (HSP/HFP)" -msgstr "Telefon dupleks (HSP/HFP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2223 -msgid "Handsfree Gateway" -msgstr "Handfri-portnar" - #: ../src/modules/bluetooth/module-bluez5-device.c:1830 msgid "High Fidelity Playback (A2DP Sink)" msgstr "Hi-fi-avspeling (A2DP-sluk)" diff --git a/po/oc.po b/po/oc.po index 4a65fb56d..3fe1f655b 100644 --- a/po/oc.po +++ b/po/oc.po @@ -521,7 +521,6 @@ msgid "Line In" msgstr "Entrada linha" #: ../src/modules/alsa/alsa-mixer.c:2383 ../src/modules/alsa/alsa-mixer.c:2461 -#: ../src/modules/bluetooth/module-bluez4-device.c:2173 #: ../src/modules/bluetooth/module-bluez5-device.c:1937 msgid "Microphone" msgstr "Micrò" @@ -583,7 +582,6 @@ msgid "No Bass Boost" msgstr "Pas d'amplificacion de las bassas" #: ../src/modules/alsa/alsa-mixer.c:2398 -#: ../src/modules/bluetooth/module-bluez4-device.c:2178 #: ../src/modules/bluetooth/module-bluez5-device.c:1944 msgid "Speaker" msgstr "Nautparlaire" @@ -756,7 +754,6 @@ msgstr "" #: ../src/modules/alsa/alsa-mixer.c:4155 #: ../src/modules/alsa/module-alsa-card.c:186 -#: ../src/modules/bluetooth/module-bluez4-device.c:2369 #: ../src/modules/bluetooth/module-bluez5-device.c:2173 #: ../src/modules/droid/module-droid-card.c:221 msgid "Off" @@ -880,49 +877,40 @@ msgstr "" "S'agÃs fòrt probablament d'un bug dins lo pilòt ALSA « %s ». Raportatz " "aqueste problèma als desvolopaires d'ALSA." -#: ../src/modules/bluetooth/module-bluez4-device.c:2163 #: ../src/modules/bluetooth/module-bluez5-device.c:1927 msgid "Headset" msgstr "Casc à udio" -#: ../src/modules/bluetooth/module-bluez4-device.c:2168 #: ../src/modules/bluetooth/module-bluez5-device.c:1932 msgid "Handsfree" msgstr "Mans liuras" -#: ../src/modules/bluetooth/module-bluez4-device.c:2183 #: ../src/modules/bluetooth/module-bluez5-device.c:1950 msgid "Headphone" msgstr "Escotadors" -#: ../src/modules/bluetooth/module-bluez4-device.c:2188 #: ../src/modules/bluetooth/module-bluez5-device.c:1955 msgid "Portable" msgstr "Portable" -#: ../src/modules/bluetooth/module-bluez4-device.c:2193 #: ../src/modules/bluetooth/module-bluez5-device.c:1960 msgid "Car" msgstr "Telefòn de veitura" -#: ../src/modules/bluetooth/module-bluez4-device.c:2198 #: ../src/modules/bluetooth/module-bluez5-device.c:1965 msgid "HiFi" msgstr "HiFi" -#: ../src/modules/bluetooth/module-bluez4-device.c:2203 #: ../src/modules/bluetooth/module-bluez5-device.c:1970 msgid "Phone" msgstr "Telefòn" -#: ../src/modules/bluetooth/module-bluez4-device.c:2211 #: ../src/modules/bluetooth/module-bluez5-device.c:1922 #: ../src/modules/bluetooth/module-bluez5-device.c:1938 #: ../src/modules/bluetooth/module-bluez5-device.c:1976 msgid "Bluetooth Output" msgstr "Sortida Bluetooth" -#: ../src/modules/bluetooth/module-bluez4-device.c:2214 #: ../src/modules/bluetooth/module-bluez5-device.c:1921 #: ../src/modules/bluetooth/module-bluez5-device.c:1943 #: ../src/modules/bluetooth/module-bluez5-device.c:1949 @@ -930,22 +918,6 @@ msgstr "Sortida Bluetooth" msgid "Bluetooth Input" msgstr "Entrada Bluetooth" -#: ../src/modules/bluetooth/module-bluez4-device.c:2250 -msgid "High Fidelity Playback (A2DP)" -msgstr "Lectura nauta fidelitat (A2DP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2261 -msgid "High Fidelity Capture (A2DP)" -msgstr "Captura Hi-Fi (A2DP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2272 -msgid "Telephony Duplex (HSP/HFP)" -msgstr "Telefonia en duplèx (HSP/HFP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2284 -msgid "Handsfree Gateway" -msgstr "Pòrt mans liuras" - #: ../src/modules/bluetooth/module-bluez5-device.c:2013 msgid "High Fidelity Playback (A2DP Sink)" msgstr "" diff --git a/po/pl.po b/po/pl.po index cdc10ce7f..9bd2020bf 100644 --- a/po/pl.po +++ b/po/pl.po @@ -594,7 +594,6 @@ msgid "Line In" msgstr "WejÅ?cie liniowe" #: ../src/modules/alsa/alsa-mixer.c:2383 ../src/modules/alsa/alsa-mixer.c:2461 -#: ../src/modules/bluetooth/module-bluez4-device.c:2104 #: ../src/modules/bluetooth/module-bluez5-device.c:1750 msgid "Microphone" msgstr "Mikrofon" @@ -656,7 +655,6 @@ msgid "No Bass Boost" msgstr "Brak podbicia basów" #: ../src/modules/alsa/alsa-mixer.c:2398 -#: ../src/modules/bluetooth/module-bluez4-device.c:2109 #: ../src/modules/bluetooth/module-bluez5-device.c:1757 msgid "Speaker" msgstr "GÅ?oÅ?nik" @@ -837,7 +835,6 @@ msgstr "Dupleks stereo" #: ../src/modules/alsa/alsa-mixer.c:4157 #: ../src/modules/alsa/module-alsa-card.c:186 -#: ../src/modules/bluetooth/module-bluez4-device.c:2324 #: ../src/modules/bluetooth/module-bluez5-device.c:2005 msgid "Off" msgstr "WyÅ?Ä?czone" @@ -969,49 +966,40 @@ msgstr "" "Prawdopodobnie jest to bÅ?Ä?d sterownika ALSA â??%sâ??. ProszÄ? zgÅ?osiÄ? ten problem " "programistom usÅ?ugi ALSA." -#: ../src/modules/bluetooth/module-bluez4-device.c:2094 #: ../src/modules/bluetooth/module-bluez5-device.c:1740 msgid "Headset" msgstr "SÅ?uchawki z mikrofonem" -#: ../src/modules/bluetooth/module-bluez4-device.c:2099 #: ../src/modules/bluetooth/module-bluez5-device.c:1745 msgid "Handsfree" msgstr "Zestaw gÅ?oÅ?nomówiÄ?cy" -#: ../src/modules/bluetooth/module-bluez4-device.c:2114 #: ../src/modules/bluetooth/module-bluez5-device.c:1763 msgid "Headphone" msgstr "SÅ?uchawki" -#: ../src/modules/bluetooth/module-bluez4-device.c:2119 #: ../src/modules/bluetooth/module-bluez5-device.c:1768 msgid "Portable" msgstr "PrzenoÅ?ne" -#: ../src/modules/bluetooth/module-bluez4-device.c:2124 #: ../src/modules/bluetooth/module-bluez5-device.c:1773 msgid "Car" msgstr "Samochód" -#: ../src/modules/bluetooth/module-bluez4-device.c:2129 #: ../src/modules/bluetooth/module-bluez5-device.c:1778 msgid "HiFi" msgstr "HiFi" -#: ../src/modules/bluetooth/module-bluez4-device.c:2134 #: ../src/modules/bluetooth/module-bluez5-device.c:1783 msgid "Phone" msgstr "Telefon" -#: ../src/modules/bluetooth/module-bluez4-device.c:2142 #: ../src/modules/bluetooth/module-bluez5-device.c:1735 #: ../src/modules/bluetooth/module-bluez5-device.c:1751 #: ../src/modules/bluetooth/module-bluez5-device.c:1789 msgid "Bluetooth Output" msgstr "WyjÅ?cie Bluetooth" -#: ../src/modules/bluetooth/module-bluez4-device.c:2145 #: ../src/modules/bluetooth/module-bluez5-device.c:1734 #: ../src/modules/bluetooth/module-bluez5-device.c:1756 #: ../src/modules/bluetooth/module-bluez5-device.c:1762 @@ -1019,22 +1007,6 @@ msgstr "WyjÅ?cie Bluetooth" msgid "Bluetooth Input" msgstr "WejÅ?cie Bluetooth" -#: ../src/modules/bluetooth/module-bluez4-device.c:2186 -msgid "High Fidelity Playback (A2DP)" -msgstr "Odtwarzanie o wysokiej dokÅ?adnoÅ?ci (A2DP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2198 -msgid "High Fidelity Capture (A2DP)" -msgstr "Przechwytywanie o wysokiej dokÅ?adnoÅ?ci (A2DP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2210 -msgid "Telephony Duplex (HSP/HFP)" -msgstr "Dupleks telefoniczny (HSP/HFP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2223 -msgid "Handsfree Gateway" -msgstr "Zestaw gÅ?oÅ?nomówiÄ?cy" - #: ../src/modules/bluetooth/module-bluez5-device.c:1830 msgid "High Fidelity Playback (A2DP Sink)" msgstr "Odtwarzanie o wysokiej dokÅ?adnoÅ?ci (odpÅ?yw A2DP)" diff --git a/po/pt_BR.po b/po/pt_BR.po index a9fd40b7f..e918c0425 100644 --- a/po/pt_BR.po +++ b/po/pt_BR.po @@ -605,7 +605,6 @@ msgid "Line In" msgstr "Entrada de linha" #: ../src/modules/alsa/alsa-mixer.c:2383 ../src/modules/alsa/alsa-mixer.c:2461 -#: ../src/modules/bluetooth/module-bluez4-device.c:2103 #: ../src/modules/bluetooth/module-bluez5-device.c:1716 msgid "Microphone" msgstr "Microfone" @@ -673,7 +672,6 @@ msgid "No Bass Boost" msgstr "Sem reforço de graves" #: ../src/modules/alsa/alsa-mixer.c:2398 -#: ../src/modules/bluetooth/module-bluez4-device.c:2108 #: ../src/modules/bluetooth/module-bluez5-device.c:1723 msgid "Speaker" msgstr "Auto-falante" @@ -846,7 +844,6 @@ msgstr "Duplex multicanal" #: ../src/modules/alsa/alsa-mixer.c:4155 #: ../src/modules/alsa/module-alsa-card.c:186 -#: ../src/modules/bluetooth/module-bluez4-device.c:2323 #: ../src/modules/bluetooth/module-bluez5-device.c:1971 msgid "Off" msgstr "Desligado" @@ -982,50 +979,41 @@ msgstr "" "relate esse problema aos desenvolvedores do ALSA." # Fone de ouvido não se encaixa como tradução aqui, pois há ou pode haver microfone junto. -#: ../src/modules/bluetooth/module-bluez4-device.c:2093 #: ../src/modules/bluetooth/module-bluez5-device.c:1706 msgid "Headset" msgstr "Headset" # Desconheço tradução comum para esta palavra. -#: ../src/modules/bluetooth/module-bluez4-device.c:2098 #: ../src/modules/bluetooth/module-bluez5-device.c:1711 msgid "Handsfree" msgstr "Handsfree" -#: ../src/modules/bluetooth/module-bluez4-device.c:2113 #: ../src/modules/bluetooth/module-bluez5-device.c:1729 msgid "Headphone" msgstr "Fones de ouvido" -#: ../src/modules/bluetooth/module-bluez4-device.c:2118 #: ../src/modules/bluetooth/module-bluez5-device.c:1734 msgid "Portable" msgstr "Portátil" -#: ../src/modules/bluetooth/module-bluez4-device.c:2123 #: ../src/modules/bluetooth/module-bluez5-device.c:1739 msgid "Car" msgstr "Carro" -#: ../src/modules/bluetooth/module-bluez4-device.c:2128 #: ../src/modules/bluetooth/module-bluez5-device.c:1744 msgid "HiFi" msgstr "HiFi" -#: ../src/modules/bluetooth/module-bluez4-device.c:2133 #: ../src/modules/bluetooth/module-bluez5-device.c:1749 msgid "Phone" msgstr "Telefone" -#: ../src/modules/bluetooth/module-bluez4-device.c:2141 #: ../src/modules/bluetooth/module-bluez5-device.c:1701 #: ../src/modules/bluetooth/module-bluez5-device.c:1717 #: ../src/modules/bluetooth/module-bluez5-device.c:1755 msgid "Bluetooth Output" msgstr "SaÃda Bluetooth" -#: ../src/modules/bluetooth/module-bluez4-device.c:2144 #: ../src/modules/bluetooth/module-bluez5-device.c:1700 #: ../src/modules/bluetooth/module-bluez5-device.c:1722 #: ../src/modules/bluetooth/module-bluez5-device.c:1728 @@ -1033,22 +1021,6 @@ msgstr "SaÃda Bluetooth" msgid "Bluetooth Input" msgstr "Entrada Bluetooth" -#: ../src/modules/bluetooth/module-bluez4-device.c:2185 -msgid "High Fidelity Playback (A2DP)" -msgstr "Reprodução de alta fidelidade (A2DP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2197 -msgid "High Fidelity Capture (A2DP)" -msgstr "Captura de alta fidelidade (A2DP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2209 -msgid "Telephony Duplex (HSP/HFP)" -msgstr "Duplex telefônico (HSP/HFP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2222 -msgid "Handsfree Gateway" -msgstr "Gateway de handsfree" - #: ../src/modules/bluetooth/module-bluez5-device.c:1796 msgid "High Fidelity Playback (A2DP Sink)" msgstr "Reprodução de alta fidelidade (Destino A2DP)" diff --git a/po/ru.po b/po/ru.po index 2e81b0718..1888c4cf3 100644 --- a/po/ru.po +++ b/po/ru.po @@ -779,7 +779,6 @@ msgid "Line In" msgstr "Ð?инейнÑ?й вÑ?од" #: ../src/modules/alsa/alsa-mixer.c:2256 ../src/modules/alsa/alsa-mixer.c:2334 -#: ../src/modules/bluetooth/module-bluez4-device.c:2101 #: ../src/modules/bluetooth/module-bluez5-device.c:1451 msgid "Microphone" msgstr "Ð?икÑ?оÑ?он" @@ -843,7 +842,6 @@ msgid "No Bass Boost" msgstr "Ð?еÑ? Ñ?Ñ?илениÑ? баÑ?ов" #: ../src/modules/alsa/alsa-mixer.c:2271 -#: ../src/modules/bluetooth/module-bluez4-device.c:2106 #: ../src/modules/bluetooth/module-bluez5-device.c:1458 msgid "Speaker" msgstr "Ð?инамик" @@ -998,7 +996,6 @@ msgstr "ЦиÑ?Ñ?овой Ñ?Ñ?еÑ?ео дÑ?плекÑ? (IEC958)" #: ../src/modules/alsa/alsa-mixer.c:3959 #: ../src/modules/alsa/module-alsa-card.c:193 -#: ../src/modules/bluetooth/module-bluez4-device.c:2297 #: ../src/modules/bluetooth/module-bluez5-device.c:1656 msgid "Off" msgstr "Ð?Ñ?клÑ?Ñ?ено" @@ -1101,50 +1098,41 @@ msgstr "" "Ð?еÑ?оÑ?Ñ?но, Ñ?Ñ?о оÑ?ибка в дÑ?айвеÑ?е ALSA «%s». Ð?ожалÑ?йÑ?Ñ?а, Ñ?ообÑ?иÑ?е об Ñ?Ñ?ой " "пÑ?облеме Ñ?азÑ?абоÑ?Ñ?икам ALSA." -#: ../src/modules/bluetooth/module-bluez4-device.c:2091 #: ../src/modules/bluetooth/module-bluez5-device.c:1441 msgid "Headset" msgstr "Ð?аÑ?ниÑ?Ñ?Ñ?а" -#: ../src/modules/bluetooth/module-bluez4-device.c:2096 #: ../src/modules/bluetooth/module-bluez5-device.c:1446 msgid "Handsfree" msgstr "ХендÑ?-Ñ?Ñ?и" -#: ../src/modules/bluetooth/module-bluez4-device.c:2111 #: ../src/modules/bluetooth/module-bluez5-device.c:1464 msgid "Headphone" msgstr "Ð?аÑ?Ñ?ник" -#: ../src/modules/bluetooth/module-bluez4-device.c:2116 #: ../src/modules/bluetooth/module-bluez5-device.c:1469 msgid "Portable" msgstr "Ð?оÑ?Ñ?аÑ?ивнÑ?й динамик" -#: ../src/modules/bluetooth/module-bluez4-device.c:2121 #: ../src/modules/bluetooth/module-bluez5-device.c:1474 msgid "Car" msgstr "Ð?вÑ?омобилÑ?нÑ?й динамик" -#: ../src/modules/bluetooth/module-bluez4-device.c:2126 #: ../src/modules/bluetooth/module-bluez5-device.c:1479 msgid "HiFi" msgstr "Hi-Fi" # BUGME: please clarify, does this mean a cell phone? --aspotashev -#: ../src/modules/bluetooth/module-bluez4-device.c:2131 #: ../src/modules/bluetooth/module-bluez5-device.c:1484 msgid "Phone" msgstr "ТелеÑ?он" -#: ../src/modules/bluetooth/module-bluez4-device.c:2139 #: ../src/modules/bluetooth/module-bluez5-device.c:1436 #: ../src/modules/bluetooth/module-bluez5-device.c:1452 #: ../src/modules/bluetooth/module-bluez5-device.c:1490 msgid "Bluetooth Output" msgstr "Ð?Ñ?Ñ?од Bluetooth" -#: ../src/modules/bluetooth/module-bluez4-device.c:2142 #: ../src/modules/bluetooth/module-bluez5-device.c:1435 #: ../src/modules/bluetooth/module-bluez5-device.c:1457 #: ../src/modules/bluetooth/module-bluez5-device.c:1463 @@ -1152,22 +1140,6 @@ msgstr "Ð?Ñ?Ñ?од Bluetooth" msgid "Bluetooth Input" msgstr "Ð?Ñ?од Bluetooth" -#: ../src/modules/bluetooth/module-bluez4-device.c:2178 -msgid "High Fidelity Playback (A2DP)" -msgstr "Ð?оÑ?пÑ?оизведение вÑ?Ñ?окого каÑ?еÑ?Ñ?ва (A2DP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2189 -msgid "High Fidelity Capture (A2DP)" -msgstr "Ð?апиÑ?Ñ? вÑ?Ñ?окого каÑ?еÑ?Ñ?ва (A2DP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2200 -msgid "Telephony Duplex (HSP/HFP)" -msgstr "Ð?Ñ?плекÑ?наÑ? Ñ?елеÑ?ониÑ? (HSP/HFP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2212 -msgid "Handsfree Gateway" -msgstr "ШлÑ?з пеÑ?едаÑ?и даннÑ?Ñ? длÑ? Ñ?ендÑ?-Ñ?Ñ?и" - #. TODO: Change this profile's name to a2dp_sink, to reflect the remote #. * device's role and be consistent with the a2dp source profile #: ../src/modules/bluetooth/module-bluez5-device.c:1529 diff --git a/po/sk.po b/po/sk.po index 730c2344b..322de4f5e 100644 --- a/po/sk.po +++ b/po/sk.po @@ -495,7 +495,6 @@ msgid "Line In" msgstr "Vstupná linka" #: ../src/modules/alsa/alsa-mixer.c:2383 ../src/modules/alsa/alsa-mixer.c:2461 -#: ../src/modules/bluetooth/module-bluez4-device.c:2099 #: ../src/modules/bluetooth/module-bluez5-device.c:1710 msgid "Microphone" msgstr "Mikrofón" @@ -557,7 +556,6 @@ msgid "No Bass Boost" msgstr "Bez zosilnenia basov" #: ../src/modules/alsa/alsa-mixer.c:2398 -#: ../src/modules/bluetooth/module-bluez4-device.c:2104 #: ../src/modules/bluetooth/module-bluez5-device.c:1717 msgid "Speaker" msgstr "Reproduktor" @@ -730,7 +728,6 @@ msgstr "Obojsmerný viackanálový" #: ../src/modules/alsa/alsa-mixer.c:4155 #: ../src/modules/alsa/module-alsa-card.c:186 -#: ../src/modules/bluetooth/module-bluez4-device.c:2295 #: ../src/modules/bluetooth/module-bluez5-device.c:1941 msgid "Off" msgstr "Vypnuté" @@ -825,49 +822,40 @@ msgid "" "to the ALSA developers." msgstr "" -#: ../src/modules/bluetooth/module-bluez4-device.c:2089 #: ../src/modules/bluetooth/module-bluez5-device.c:1700 msgid "Headset" msgstr "Headset" -#: ../src/modules/bluetooth/module-bluez4-device.c:2094 #: ../src/modules/bluetooth/module-bluez5-device.c:1705 msgid "Handsfree" msgstr "Handsfree" -#: ../src/modules/bluetooth/module-bluez4-device.c:2109 #: ../src/modules/bluetooth/module-bluez5-device.c:1723 msgid "Headphone" msgstr "Slúchadlo" -#: ../src/modules/bluetooth/module-bluez4-device.c:2114 #: ../src/modules/bluetooth/module-bluez5-device.c:1728 msgid "Portable" msgstr "Prenosné" -#: ../src/modules/bluetooth/module-bluez4-device.c:2119 #: ../src/modules/bluetooth/module-bluez5-device.c:1733 msgid "Car" msgstr "Automobil" -#: ../src/modules/bluetooth/module-bluez4-device.c:2124 #: ../src/modules/bluetooth/module-bluez5-device.c:1738 msgid "HiFi" msgstr "HiFi" -#: ../src/modules/bluetooth/module-bluez4-device.c:2129 #: ../src/modules/bluetooth/module-bluez5-device.c:1743 msgid "Phone" msgstr "Telefón" -#: ../src/modules/bluetooth/module-bluez4-device.c:2137 #: ../src/modules/bluetooth/module-bluez5-device.c:1695 #: ../src/modules/bluetooth/module-bluez5-device.c:1711 #: ../src/modules/bluetooth/module-bluez5-device.c:1749 msgid "Bluetooth Output" msgstr "Výstup cez Bluetooth" -#: ../src/modules/bluetooth/module-bluez4-device.c:2140 #: ../src/modules/bluetooth/module-bluez5-device.c:1694 #: ../src/modules/bluetooth/module-bluez5-device.c:1716 #: ../src/modules/bluetooth/module-bluez5-device.c:1722 @@ -875,22 +863,6 @@ msgstr "Výstup cez Bluetooth" msgid "Bluetooth Input" msgstr "Vstup cez Bluetooth" -#: ../src/modules/bluetooth/module-bluez4-device.c:2176 -msgid "High Fidelity Playback (A2DP)" -msgstr "Hi-Fi prehrávanie (A2DP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2187 -msgid "High Fidelity Capture (A2DP)" -msgstr "Hi-Fi zaznamenávanie (A2DP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2198 -msgid "Telephony Duplex (HSP/HFP)" -msgstr "" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2210 -msgid "Handsfree Gateway" -msgstr "Brána pre handsfree" - #: ../src/modules/bluetooth/module-bluez5-device.c:1786 msgid "High Fidelity Playback (A2DP Sink)" msgstr "" diff --git a/po/sv.po b/po/sv.po index a5b6d6fbf..a86895950 100644 --- a/po/sv.po +++ b/po/sv.po @@ -594,7 +594,6 @@ msgid "Line In" msgstr "Linje in" #: ../src/modules/alsa/alsa-mixer.c:2383 ../src/modules/alsa/alsa-mixer.c:2461 -#: ../src/modules/bluetooth/module-bluez4-device.c:2104 #: ../src/modules/bluetooth/module-bluez5-device.c:1783 msgid "Microphone" msgstr "Mikrofon" @@ -656,7 +655,6 @@ msgid "No Bass Boost" msgstr "Ingen basökning" #: ../src/modules/alsa/alsa-mixer.c:2398 -#: ../src/modules/bluetooth/module-bluez4-device.c:2109 #: ../src/modules/bluetooth/module-bluez5-device.c:1790 msgid "Speaker" msgstr "Högtalare" @@ -841,7 +839,6 @@ msgstr "Stereo duplex" #: ../src/modules/alsa/alsa-mixer.c:4158 #: ../src/modules/alsa/module-alsa-card.c:186 -#: ../src/modules/bluetooth/module-bluez4-device.c:2324 #: ../src/modules/bluetooth/module-bluez5-device.c:2038 msgid "Off" msgstr "Av" @@ -976,49 +973,40 @@ msgstr "" "Förmodligen är detta ett fel i ALSA-drivrutinen â??%sâ??. Vänligen rapportera " "problemet till ALSA-utvecklarna." -#: ../src/modules/bluetooth/module-bluez4-device.c:2094 #: ../src/modules/bluetooth/module-bluez5-device.c:1773 msgid "Headset" msgstr "Headset" -#: ../src/modules/bluetooth/module-bluez4-device.c:2099 #: ../src/modules/bluetooth/module-bluez5-device.c:1778 msgid "Handsfree" msgstr "Handsfree" -#: ../src/modules/bluetooth/module-bluez4-device.c:2114 #: ../src/modules/bluetooth/module-bluez5-device.c:1796 msgid "Headphone" msgstr "Hörlurar" -#: ../src/modules/bluetooth/module-bluez4-device.c:2119 #: ../src/modules/bluetooth/module-bluez5-device.c:1801 msgid "Portable" msgstr "Bärbar" -#: ../src/modules/bluetooth/module-bluez4-device.c:2124 #: ../src/modules/bluetooth/module-bluez5-device.c:1806 msgid "Car" msgstr "Bil" -#: ../src/modules/bluetooth/module-bluez4-device.c:2129 #: ../src/modules/bluetooth/module-bluez5-device.c:1811 msgid "HiFi" msgstr "HiFi" -#: ../src/modules/bluetooth/module-bluez4-device.c:2134 #: ../src/modules/bluetooth/module-bluez5-device.c:1816 msgid "Phone" msgstr "Telefon" -#: ../src/modules/bluetooth/module-bluez4-device.c:2142 #: ../src/modules/bluetooth/module-bluez5-device.c:1768 #: ../src/modules/bluetooth/module-bluez5-device.c:1784 #: ../src/modules/bluetooth/module-bluez5-device.c:1822 msgid "Bluetooth Output" msgstr "Bluetooth-utgÃ¥ng" -#: ../src/modules/bluetooth/module-bluez4-device.c:2145 #: ../src/modules/bluetooth/module-bluez5-device.c:1767 #: ../src/modules/bluetooth/module-bluez5-device.c:1789 #: ../src/modules/bluetooth/module-bluez5-device.c:1795 @@ -1026,22 +1014,6 @@ msgstr "Bluetooth-utgÃ¥ng" msgid "Bluetooth Input" msgstr "Bluetooth-ingÃ¥ng" -#: ../src/modules/bluetooth/module-bluez4-device.c:2186 -msgid "High Fidelity Playback (A2DP)" -msgstr "High fidelity playback (A2DP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2198 -msgid "High Fidelity Capture (A2DP)" -msgstr "High fidelity capture (A2DP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2210 -msgid "Telephony Duplex (HSP/HFP)" -msgstr "Telephony duplex (HSP/HFP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2223 -msgid "Handsfree Gateway" -msgstr "Handsfree gateway" - #: ../src/modules/bluetooth/module-bluez5-device.c:1863 msgid "High Fidelity Playback (A2DP Sink)" msgstr "High fidelity playback (A2DP Sink)" diff --git a/po/tr.po b/po/tr.po index 9a72759a2..2600f8aa8 100644 --- a/po/tr.po +++ b/po/tr.po @@ -678,7 +678,6 @@ msgid "Line In" msgstr "Hat giriÅ?i" #: ../src/modules/alsa/alsa-mixer.c:2383 ../src/modules/alsa/alsa-mixer.c:2461 -#: ../src/modules/bluetooth/module-bluez4-device.c:2104 #: ../src/modules/bluetooth/module-bluez5-device.c:1696 msgid "Microphone" msgstr "Mikrofon" @@ -740,7 +739,6 @@ msgid "No Bass Boost" msgstr "Bas Artırma" #: ../src/modules/alsa/alsa-mixer.c:2398 -#: ../src/modules/bluetooth/module-bluez4-device.c:2109 #: ../src/modules/bluetooth/module-bluez5-device.c:1703 msgid "Speaker" msgstr "Hoparlör" @@ -922,7 +920,6 @@ msgstr "Ä°kili Stereo" #: ../src/modules/alsa/alsa-mixer.c:4157 #: ../src/modules/alsa/module-alsa-card.c:186 -#: ../src/modules/bluetooth/module-bluez4-device.c:2324 #: ../src/modules/bluetooth/module-bluez5-device.c:1951 msgid "Off" msgstr "Kapalı" @@ -1054,49 +1051,40 @@ msgstr "" "Büyük ihtimalle bu bir ALSA sürücüsü '%s' hatasıdır. Lütfen bu sorunu ALSA " "geliÅ?tiricilerine bildirin." -#: ../src/modules/bluetooth/module-bluez4-device.c:2094 #: ../src/modules/bluetooth/module-bluez5-device.c:1686 msgid "Headset" msgstr "Kulaklık" -#: ../src/modules/bluetooth/module-bluez4-device.c:2099 #: ../src/modules/bluetooth/module-bluez5-device.c:1691 msgid "Handsfree" msgstr "Ahizesiz" -#: ../src/modules/bluetooth/module-bluez4-device.c:2114 #: ../src/modules/bluetooth/module-bluez5-device.c:1709 msgid "Headphone" msgstr "Kulaklık" -#: ../src/modules/bluetooth/module-bluez4-device.c:2119 #: ../src/modules/bluetooth/module-bluez5-device.c:1714 msgid "Portable" msgstr "TaÅ?ınabilir" -#: ../src/modules/bluetooth/module-bluez4-device.c:2124 #: ../src/modules/bluetooth/module-bluez5-device.c:1719 msgid "Car" msgstr "Araba" -#: ../src/modules/bluetooth/module-bluez4-device.c:2129 #: ../src/modules/bluetooth/module-bluez5-device.c:1724 msgid "HiFi" msgstr "Yüksek duyarlılık" -#: ../src/modules/bluetooth/module-bluez4-device.c:2134 #: ../src/modules/bluetooth/module-bluez5-device.c:1729 msgid "Phone" msgstr "Telefon" -#: ../src/modules/bluetooth/module-bluez4-device.c:2142 #: ../src/modules/bluetooth/module-bluez5-device.c:1681 #: ../src/modules/bluetooth/module-bluez5-device.c:1697 #: ../src/modules/bluetooth/module-bluez5-device.c:1735 msgid "Bluetooth Output" msgstr "Bluetooth Ã?ıkıÅ?ı" -#: ../src/modules/bluetooth/module-bluez4-device.c:2145 #: ../src/modules/bluetooth/module-bluez5-device.c:1680 #: ../src/modules/bluetooth/module-bluez5-device.c:1702 #: ../src/modules/bluetooth/module-bluez5-device.c:1708 @@ -1104,22 +1092,6 @@ msgstr "Bluetooth Ã?ıkıÅ?ı" msgid "Bluetooth Input" msgstr "Bluetooth GiriÅ?i" -#: ../src/modules/bluetooth/module-bluez4-device.c:2186 -msgid "High Fidelity Playback (A2DP)" -msgstr "Yüksek Kaliteli Ã?alma (A2DP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2198 -msgid "High Fidelity Capture (A2DP)" -msgstr "Yüksek Kaliteli Yakalama (A2DP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2210 -msgid "Telephony Duplex (HSP/HFP)" -msgstr "Ã?ift yönlü Telefon (HSP/HFP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2223 -msgid "Handsfree Gateway" -msgstr "Eller Serbest Geçidi" - #: ../src/modules/bluetooth/module-bluez5-device.c:1776 msgid "High Fidelity Playback (A2DP Sink)" msgstr "Yüksek Kaliteli Ã?alma (A2DP Alıcı)" diff --git a/po/uk.po b/po/uk.po index 48160aef8..1dcd6c10c 100644 --- a/po/uk.po +++ b/po/uk.po @@ -609,7 +609,6 @@ msgid "Line In" msgstr "Ð?Ñ?нÑ?йний вÑ?Ñ?д" #: ../src/modules/alsa/alsa-mixer.c:2383 ../src/modules/alsa/alsa-mixer.c:2461 -#: ../src/modules/bluetooth/module-bluez4-device.c:2104 #: ../src/modules/bluetooth/module-bluez5-device.c:1783 msgid "Microphone" msgstr "Ð?Ñ?кÑ?оÑ?он" @@ -671,7 +670,6 @@ msgid "No Bass Boost" msgstr "Ð?ез пÑ?дÑ?иленнÑ?" #: ../src/modules/alsa/alsa-mixer.c:2398 -#: ../src/modules/bluetooth/module-bluez4-device.c:2109 #: ../src/modules/bluetooth/module-bluez5-device.c:1790 msgid "Speaker" msgstr "Ð?Ñ?Ñ?номовеÑ?Ñ?" @@ -857,7 +855,6 @@ msgstr "Ð?вобÑ?Ñ?не Ñ?Ñ?еÑ?ео" #: ../src/modules/alsa/alsa-mixer.c:4158 #: ../src/modules/alsa/module-alsa-card.c:186 -#: ../src/modules/bluetooth/module-bluez4-device.c:2324 #: ../src/modules/bluetooth/module-bluez5-device.c:2038 msgid "Off" msgstr "Ð?имкнено" @@ -992,49 +989,40 @@ msgstr "" "Ð?мовÑ?Ñ?но, ви наÑ?Ñ?апили на вадÑ? Ñ? дÑ?айвеÑ?Ñ? ALSA «%s». Ð?Ñ?дÑ? лаÑ?ка, повÑ?домÑ?е " "пÑ?о Ñ?Ñ? вадÑ? Ñ?озÑ?обникам ALSA." -#: ../src/modules/bluetooth/module-bluez4-device.c:2094 #: ../src/modules/bluetooth/module-bluez5-device.c:1773 msgid "Headset" msgstr "Ð?аÑ?нÑ?Ñ?Ñ?Ñ?а" -#: ../src/modules/bluetooth/module-bluez4-device.c:2099 #: ../src/modules/bluetooth/module-bluez5-device.c:1778 msgid "Handsfree" msgstr "Ð?Ñ?иÑ?Ñ?Ñ?Ñ?й гÑ?Ñ?ного звâ??Ñ?зкÑ?" -#: ../src/modules/bluetooth/module-bluez4-device.c:2114 #: ../src/modules/bluetooth/module-bluez5-device.c:1796 msgid "Headphone" msgstr "Ð?авÑ?Ñ?ники" -#: ../src/modules/bluetooth/module-bluez4-device.c:2119 #: ../src/modules/bluetooth/module-bluez5-device.c:1801 msgid "Portable" msgstr "Ð?оÑ?Ñ?аÑ?ивна Ñ?иÑ?Ñ?ема" -#: ../src/modules/bluetooth/module-bluez4-device.c:2124 #: ../src/modules/bluetooth/module-bluez5-device.c:1806 msgid "Car" msgstr "Ð?вÑ?омобÑ?лÑ?на Ñ?иÑ?Ñ?ема" -#: ../src/modules/bluetooth/module-bluez4-device.c:2129 #: ../src/modules/bluetooth/module-bluez5-device.c:1811 msgid "HiFi" msgstr "HiFi" -#: ../src/modules/bluetooth/module-bluez4-device.c:2134 #: ../src/modules/bluetooth/module-bluez5-device.c:1816 msgid "Phone" msgstr "ТелеÑ?он" -#: ../src/modules/bluetooth/module-bluez4-device.c:2142 #: ../src/modules/bluetooth/module-bluez5-device.c:1768 #: ../src/modules/bluetooth/module-bluez5-device.c:1784 #: ../src/modules/bluetooth/module-bluez5-device.c:1822 msgid "Bluetooth Output" msgstr "Bluetooth (вÑ?дÑ?воÑ?еннÑ?)" -#: ../src/modules/bluetooth/module-bluez4-device.c:2145 #: ../src/modules/bluetooth/module-bluez5-device.c:1767 #: ../src/modules/bluetooth/module-bluez5-device.c:1789 #: ../src/modules/bluetooth/module-bluez5-device.c:1795 @@ -1042,22 +1030,6 @@ msgstr "Bluetooth (вÑ?дÑ?воÑ?еннÑ?)" msgid "Bluetooth Input" msgstr "Bluetooth (вÑ?Ñ?д)" -#: ../src/modules/bluetooth/module-bluez4-device.c:2186 -msgid "High Fidelity Playback (A2DP)" -msgstr "Ð?иÑ?окоÑ?оÑ?не вÑ?дÑ?воÑ?еннÑ? (A2DP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2198 -msgid "High Fidelity Capture (A2DP)" -msgstr "Ð?иÑ?окоÑ?оÑ?не заÑ?опленнÑ? (A2DP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2210 -msgid "Telephony Duplex (HSP/HFP)" -msgstr "ТелеÑ?онний дÑ?плекÑ? (HSP/HFP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2223 -msgid "Handsfree Gateway" -msgstr "Ð?Ñ?иÑ?Ñ?Ñ?Ñ?й гÑ?Ñ?ного звâ??Ñ?зкÑ?" - #: ../src/modules/bluetooth/module-bluez5-device.c:1863 msgid "High Fidelity Playback (A2DP Sink)" msgstr "Ð?иÑ?окоÑ?оÑ?не вÑ?дÑ?воÑ?еннÑ? (пÑ?иймаÑ? A2DP)" diff --git a/po/zh_CN.po b/po/zh_CN.po index 19a7ae5c7..daa8b5d8d 100644 --- a/po/zh_CN.po +++ b/po/zh_CN.po @@ -555,7 +555,6 @@ msgid "Line In" msgstr "è¾?å?¥æ??å?" #: ../src/modules/alsa/alsa-mixer.c:2383 ../src/modules/alsa/alsa-mixer.c:2461 -#: ../src/modules/bluetooth/module-bluez4-device.c:2099 #: ../src/modules/bluetooth/module-bluez5-device.c:1710 msgid "Microphone" msgstr "è¯?ç?" @@ -617,7 +616,6 @@ msgid "No Bass Boost" msgstr "æ? é??ä½?é?³å¢?强" #: ../src/modules/alsa/alsa-mixer.c:2398 -#: ../src/modules/bluetooth/module-bluez4-device.c:2104 #: ../src/modules/bluetooth/module-bluez5-device.c:1717 msgid "Speaker" msgstr "æ?¬å£°å?¨" @@ -790,7 +788,6 @@ msgstr "å¤?声é??å??å·¥" #: ../src/modules/alsa/alsa-mixer.c:4155 #: ../src/modules/alsa/module-alsa-card.c:186 -#: ../src/modules/bluetooth/module-bluez4-device.c:2295 #: ../src/modules/bluetooth/module-bluez5-device.c:1941 msgid "Off" msgstr "å?³" @@ -911,49 +908,40 @@ msgstr "" "snd_pcm_mmap_begin() è¿?å??ç??å?¼é??常大ï¼?%lu å?è??(%lu ms)ã??\n" "è¿?å¾?å?¯è?½æ?¯ç?± ALSA 驱å?¨ç¨?åº? %s ä¸ç?? bugã??请å?? ALSA å¼?å??è??举æ?¥è¿?个é?®é¢?ã??" -#: ../src/modules/bluetooth/module-bluez4-device.c:2089 #: ../src/modules/bluetooth/module-bluez5-device.c:1700 msgid "Headset" msgstr "è?³æ?º" -#: ../src/modules/bluetooth/module-bluez4-device.c:2094 #: ../src/modules/bluetooth/module-bluez5-device.c:1705 msgid "Handsfree" msgstr "å??æ??æ??ä½?" -#: ../src/modules/bluetooth/module-bluez4-device.c:2109 #: ../src/modules/bluetooth/module-bluez5-device.c:1723 msgid "Headphone" msgstr "头æ?´è?³æ?º" -#: ../src/modules/bluetooth/module-bluez4-device.c:2114 #: ../src/modules/bluetooth/module-bluez5-device.c:1728 msgid "Portable" msgstr "便æ?ºå¼?" -#: ../src/modules/bluetooth/module-bluez4-device.c:2119 #: ../src/modules/bluetooth/module-bluez5-device.c:1733 msgid "Car" msgstr "车å??" -#: ../src/modules/bluetooth/module-bluez4-device.c:2124 #: ../src/modules/bluetooth/module-bluez5-device.c:1738 msgid "HiFi" msgstr "é«?ä¿?ç??" -#: ../src/modules/bluetooth/module-bluez4-device.c:2129 #: ../src/modules/bluetooth/module-bluez5-device.c:1743 msgid "Phone" msgstr "ç?µè¯?" -#: ../src/modules/bluetooth/module-bluez4-device.c:2137 #: ../src/modules/bluetooth/module-bluez5-device.c:1695 #: ../src/modules/bluetooth/module-bluez5-device.c:1711 #: ../src/modules/bluetooth/module-bluez5-device.c:1749 msgid "Bluetooth Output" msgstr "è??ç??è¾?å?º" -#: ../src/modules/bluetooth/module-bluez4-device.c:2140 #: ../src/modules/bluetooth/module-bluez5-device.c:1694 #: ../src/modules/bluetooth/module-bluez5-device.c:1716 #: ../src/modules/bluetooth/module-bluez5-device.c:1722 @@ -961,22 +949,6 @@ msgstr "è??ç??è¾?å?º" msgid "Bluetooth Input" msgstr "è??ç??è¾?å?¥" -#: ../src/modules/bluetooth/module-bluez4-device.c:2176 -msgid "High Fidelity Playback (A2DP)" -msgstr "é«?ä¿?ç??å??æ?¾(A2DP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2187 -msgid "High Fidelity Capture (A2DP)" -msgstr "é«?ä¿?ç??é??é??(A2DP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2198 -msgid "Telephony Duplex (HSP/HFP)" -msgstr "å??å·¥ç?µè¯?(HSP/HFP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2210 -msgid "Handsfree Gateway" -msgstr "è??ç??é?³é¢?ç½?å?³" - #: ../src/modules/bluetooth/module-bluez5-device.c:1786 msgid "High Fidelity Playback (A2DP Sink)" msgstr "é«?ä¿?ç??å??æ?¾ (A2DP 信宿)" diff --git a/po/zh_TW.po b/po/zh_TW.po index 6f6dc9ac7..5233a9ecc 100644 --- a/po/zh_TW.po +++ b/po/zh_TW.po @@ -558,7 +558,6 @@ msgid "Line In" msgstr "ç·?路輸å?¥" #: ../src/modules/alsa/alsa-mixer.c:2383 ../src/modules/alsa/alsa-mixer.c:2461 -#: ../src/modules/bluetooth/module-bluez4-device.c:2104 #: ../src/modules/bluetooth/module-bluez5-device.c:1773 msgid "Microphone" msgstr "麥å??風" @@ -620,7 +619,6 @@ msgid "No Bass Boost" msgstr "ç?¡ä½?é?³å¢?å¼·" #: ../src/modules/alsa/alsa-mixer.c:2398 -#: ../src/modules/bluetooth/module-bluez4-device.c:2109 #: ../src/modules/bluetooth/module-bluez5-device.c:1780 msgid "Speaker" msgstr "å??å?" @@ -805,7 +803,6 @@ msgstr "ç«?é«?è?²é??å·¥" #: ../src/modules/alsa/alsa-mixer.c:4158 #: ../src/modules/alsa/module-alsa-card.c:186 -#: ../src/modules/bluetooth/module-bluez4-device.c:2324 #: ../src/modules/bluetooth/module-bluez5-device.c:2028 msgid "Off" msgstr "é??é??" @@ -924,49 +921,40 @@ msgstr "" "snd_pcm_mmap_begin() å?³å??è¶?å?ºé ?æ??ç??大å?¼ï¼?%lu bytes (%lu ms)ã??\n" "é??å¾?è?½æ?¯ ALSA é©?å??ç¨?å¼?ã??%sã??ç??è?è?²ã??è«?å??å ±é??å??å??é¡?給 ALSA é??ç?¼è??ã??" -#: ../src/modules/bluetooth/module-bluez4-device.c:2094 #: ../src/modules/bluetooth/module-bluez5-device.c:1763 msgid "Headset" msgstr "è?³éº¥" -#: ../src/modules/bluetooth/module-bluez4-device.c:2099 #: ../src/modules/bluetooth/module-bluez5-device.c:1768 msgid "Handsfree" msgstr "å??æ??è£?ç½®" -#: ../src/modules/bluetooth/module-bluez4-device.c:2114 #: ../src/modules/bluetooth/module-bluez5-device.c:1786 msgid "Headphone" msgstr "é æ?´å¼?è?³æ©?" -#: ../src/modules/bluetooth/module-bluez4-device.c:2119 #: ../src/modules/bluetooth/module-bluez5-device.c:1791 msgid "Portable" msgstr "å?¯æ??è£?ç½®" -#: ../src/modules/bluetooth/module-bluez4-device.c:2124 #: ../src/modules/bluetooth/module-bluez5-device.c:1796 msgid "Car" msgstr "æ±½è»?" -#: ../src/modules/bluetooth/module-bluez4-device.c:2129 #: ../src/modules/bluetooth/module-bluez5-device.c:1801 msgid "HiFi" msgstr "HiFi" -#: ../src/modules/bluetooth/module-bluez4-device.c:2134 #: ../src/modules/bluetooth/module-bluez5-device.c:1806 msgid "Phone" msgstr "æ??æ©?" -#: ../src/modules/bluetooth/module-bluez4-device.c:2142 #: ../src/modules/bluetooth/module-bluez5-device.c:1758 #: ../src/modules/bluetooth/module-bluez5-device.c:1774 #: ../src/modules/bluetooth/module-bluez5-device.c:1812 msgid "Bluetooth Output" msgstr "è??ç??輸å?º" -#: ../src/modules/bluetooth/module-bluez4-device.c:2145 #: ../src/modules/bluetooth/module-bluez5-device.c:1757 #: ../src/modules/bluetooth/module-bluez5-device.c:1779 #: ../src/modules/bluetooth/module-bluez5-device.c:1785 @@ -974,22 +962,6 @@ msgstr "è??ç??輸å?º" msgid "Bluetooth Input" msgstr "è??ç??輸å?¥" -#: ../src/modules/bluetooth/module-bluez4-device.c:2186 -msgid "High Fidelity Playback (A2DP)" -msgstr "é«?å?³ç??æ?æ?¾è£?ç½® (A2DP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2198 -msgid "High Fidelity Capture (A2DP)" -msgstr "é«?å?³ç??æ?·å??è£?ç½® (A2DP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2210 -msgid "Telephony Duplex (HSP/HFP)" -msgstr "é?»è©±é??å·¥ (HSP/HFP)" - -#: ../src/modules/bluetooth/module-bluez4-device.c:2223 -msgid "Handsfree Gateway" -msgstr "å??æ??é??é??" - #: ../src/modules/bluetooth/module-bluez5-device.c:1853 msgid "High Fidelity Playback (A2DP Sink)" msgstr "é«?å?³ç??æ?æ?¾è£?ç½® (A2DP Sink)" diff --git a/src/Makefile.am b/src/Makefile.am index 45616c01c..8d8b701fe 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1444,13 +1444,6 @@ modlibexec_LTLIBRARIES += \ module-bluetooth-policy.la endif -if HAVE_BLUEZ_4 -modlibexec_LTLIBRARIES += \ - libbluez4-util.la \ - module-bluez4-discover.la \ - module-bluez4-device.la -endif - if HAVE_BLUEZ_5 modlibexec_LTLIBRARIES += \ libbluez5-util.la \ @@ -2079,25 +2072,6 @@ module_bluetooth_discover_la_LDFLAGS = $(MODULE_LDFLAGS) module_bluetooth_discover_la_LIBADD = $(MODULE_LIBADD) module_bluetooth_discover_la_CFLAGS = $(AM_CFLAGS) -DPA_MODULE_NAME=module_bluetooth_discover -# Bluetooth BlueZ 4 sink / source -module_bluez4_discover_la_SOURCES = modules/bluetooth/module-bluez4-discover.c -module_bluez4_discover_la_LDFLAGS = $(MODULE_LDFLAGS) -module_bluez4_discover_la_LIBADD = $(MODULE_LIBADD) $(DBUS_LIBS) libbluez4-util.la -module_bluez4_discover_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS) -DPA_MODULE_NAME=module_bluez4_discover - -libbluez4_util_la_SOURCES = \ - modules/bluetooth/a2dp-codecs.h \ - modules/bluetooth/bluez4-util.c \ - modules/bluetooth/bluez4-util.h -libbluez4_util_la_LDFLAGS = -avoid-version -libbluez4_util_la_LIBADD = $(MODULE_LIBADD) $(DBUS_LIBS) -libbluez4_util_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS) - -module_bluez4_device_la_SOURCES = modules/bluetooth/module-bluez4-device.c modules/bluetooth/rtp.h -module_bluez4_device_la_LDFLAGS = $(MODULE_LDFLAGS) -module_bluez4_device_la_LIBADD = $(MODULE_LIBADD) $(DBUS_LIBS) $(SBC_LIBS) libbluez4-util.la -module_bluez4_device_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS) $(SBC_CFLAGS) -DPA_MODULE_NAME=module_bluez4_device - # Bluetooth BlueZ 5 sink / source libbluez5_util_la_SOURCES = \ modules/bluetooth/bluez5-util.c \ diff --git a/src/modules/bluetooth/bluez4-util.c b/src/modules/bluetooth/bluez4-util.c deleted file mode 100644 index ca606193d..000000000 --- a/src/modules/bluetooth/bluez4-util.c +++ /dev/null @@ -1,1851 +0,0 @@ -/*** - This file is part of PulseAudio. - - Copyright 2008-2013 João Paulo Rechi Vita - - PulseAudio is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - PulseAudio is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. -***/ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <pulse/xmalloc.h> - -#include <pulsecore/core-util.h> -#include <pulsecore/shared.h> -#include <pulsecore/dbus-shared.h> - -#include "bluez4-util.h" -#include "a2dp-codecs.h" - -#define ENDPOINT_PATH_HFP_AG "/MediaEndpoint/BlueZ4/HFPAG" -#define ENDPOINT_PATH_HFP_HS "/MediaEndpoint/BlueZ4/HFPHS" -#define ENDPOINT_PATH_A2DP_SOURCE "/MediaEndpoint/BlueZ4/A2DPSource" -#define ENDPOINT_PATH_A2DP_SINK "/MediaEndpoint/BlueZ4/A2DPSink" - -#define ENDPOINT_INTROSPECT_XML \ - DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \ - "<node>" \ - " <interface name=\"org.bluez.MediaEndpoint\">" \ - " <method name=\"SetConfiguration\">" \ - " <arg name=\"transport\" direction=\"in\" type=\"o\"/>" \ - " <arg name=\"configuration\" direction=\"in\" type=\"ay\"/>" \ - " </method>" \ - " <method name=\"SelectConfiguration\">" \ - " <arg name=\"capabilities\" direction=\"in\" type=\"ay\"/>" \ - " <arg name=\"configuration\" direction=\"out\" type=\"ay\"/>" \ - " </method>" \ - " <method name=\"ClearConfiguration\">" \ - " </method>" \ - " <method name=\"Release\">" \ - " </method>" \ - " </interface>" \ - " <interface name=\"org.freedesktop.DBus.Introspectable\">" \ - " <method name=\"Introspect\">" \ - " <arg name=\"data\" type=\"s\" direction=\"out\"/>" \ - " </method>" \ - " </interface>" \ - "</node>" - -struct pa_bluez4_discovery { - PA_REFCNT_DECLARE; - - pa_core *core; - pa_dbus_connection *connection; - PA_LLIST_HEAD(pa_dbus_pending, pending); - bool adapters_listed; - pa_hashmap *devices; - pa_hashmap *transports; - pa_hook hooks[PA_BLUEZ4_HOOK_MAX]; - bool filter_added; -}; - -static void get_properties_reply(DBusPendingCall *pending, void *userdata); -static pa_dbus_pending* send_and_add_to_pending(pa_bluez4_discovery *y, DBusMessage *m, DBusPendingCallNotifyFunction func, - void *call_data); -static void found_adapter(pa_bluez4_discovery *y, const char *path); -static pa_bluez4_device *found_device(pa_bluez4_discovery *y, const char* path); -static void transport_set_state(pa_bluez4_transport *transport, pa_bluez4_transport_state_t state); - -static pa_bluez4_audio_state_t audio_state_from_string(const char* value) { - pa_assert(value); - - if (pa_streq(value, "disconnected")) - return PA_BLUEZ4_AUDIO_STATE_DISCONNECTED; - else if (pa_streq(value, "connecting")) - return PA_BLUEZ4_AUDIO_STATE_CONNECTING; - else if (pa_streq(value, "connected")) - return PA_BLUEZ4_AUDIO_STATE_CONNECTED; - else if (pa_streq(value, "playing")) - return PA_BLUEZ4_AUDIO_STATE_PLAYING; - - return PA_BLUEZ4_AUDIO_STATE_INVALID; -} - -const char *pa_bluez4_profile_to_string(pa_bluez4_profile_t profile) { - switch(profile) { - case PA_BLUEZ4_PROFILE_A2DP_SINK: - return "a2dp"; - case PA_BLUEZ4_PROFILE_A2DP_SOURCE: - return "a2dp_source"; - case PA_BLUEZ4_PROFILE_HEADSET_HEAD_UNIT: - return "hsp"; - case PA_BLUEZ4_PROFILE_HEADSET_AUDIO_GATEWAY: - return "hfgw"; - case PA_BLUEZ4_PROFILE_OFF: - pa_assert_not_reached(); - } - - pa_assert_not_reached(); -} - -static int profile_from_interface(const char *interface, pa_bluez4_profile_t *p) { - pa_assert(interface); - pa_assert(p); - - if (pa_streq(interface, "org.bluez.AudioSink")) { - *p = PA_BLUEZ4_PROFILE_A2DP_SINK; - return 0; - } else if (pa_streq(interface, "org.bluez.AudioSource")) { - *p = PA_BLUEZ4_PROFILE_A2DP_SOURCE; - return 0; - } else if (pa_streq(interface, "org.bluez.Headset")) { - *p = PA_BLUEZ4_PROFILE_HEADSET_HEAD_UNIT; - return 0; - } else if (pa_streq(interface, "org.bluez.HandsfreeGateway")) { - *p = PA_BLUEZ4_PROFILE_HEADSET_AUDIO_GATEWAY; - return 0; - } - - return -1; -} - -static pa_bluez4_transport_state_t audio_state_to_transport_state(pa_bluez4_audio_state_t state) { - switch (state) { - case PA_BLUEZ4_AUDIO_STATE_INVALID: /* Typically if state hasn't been received yet */ - case PA_BLUEZ4_AUDIO_STATE_DISCONNECTED: - case PA_BLUEZ4_AUDIO_STATE_CONNECTING: - return PA_BLUEZ4_TRANSPORT_STATE_DISCONNECTED; - case PA_BLUEZ4_AUDIO_STATE_CONNECTED: - return PA_BLUEZ4_TRANSPORT_STATE_IDLE; - case PA_BLUEZ4_AUDIO_STATE_PLAYING: - return PA_BLUEZ4_TRANSPORT_STATE_PLAYING; - } - - pa_assert_not_reached(); -} - -static pa_bluez4_device* device_new(pa_bluez4_discovery *discovery, const char *path) { - pa_bluez4_device *d; - unsigned i; - - pa_assert(discovery); - pa_assert(path); - - d = pa_xnew0(pa_bluez4_device, 1); - - d->discovery = discovery; - d->dead = false; - - d->device_info_valid = 0; - - d->name = NULL; - d->path = pa_xstrdup(path); - d->paired = -1; - d->alias = NULL; - d->uuids = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, NULL, pa_xfree); - d->address = NULL; - d->class = -1; - d->trusted = -1; - - d->audio_state = PA_BLUEZ4_AUDIO_STATE_INVALID; - - for (i = 0; i < PA_BLUEZ4_PROFILE_COUNT; i++) - d->profile_state[i] = PA_BLUEZ4_AUDIO_STATE_INVALID; - - return d; -} - -static void transport_free(pa_bluez4_transport *t) { - pa_assert(t); - - pa_xfree(t->owner); - pa_xfree(t->path); - pa_xfree(t->config); - pa_xfree(t); -} - -static void device_free(pa_bluez4_device *d) { - pa_bluez4_transport *t; - unsigned i; - - pa_assert(d); - - for (i = 0; i < PA_BLUEZ4_PROFILE_COUNT; i++) { - if (!(t = d->transports[i])) - continue; - - d->transports[i] = NULL; - pa_hashmap_remove(d->discovery->transports, t->path); - transport_set_state(t, PA_BLUEZ4_TRANSPORT_STATE_DISCONNECTED); - transport_free(t); - } - - if (d->uuids) - pa_hashmap_free(d->uuids); - - pa_xfree(d->name); - pa_xfree(d->path); - pa_xfree(d->alias); - pa_xfree(d->address); - pa_xfree(d); -} - -static const char *check_variant_property(DBusMessageIter *i) { - const char *key; - - pa_assert(i); - - if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_STRING) { - pa_log("Property name not a string."); - return NULL; - } - - dbus_message_iter_get_basic(i, &key); - - if (!dbus_message_iter_next(i)) { - pa_log("Property value missing"); - return NULL; - } - - if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_VARIANT) { - pa_log("Property value not a variant."); - return NULL; - } - - return key; -} - -static int parse_manager_property(pa_bluez4_discovery *y, DBusMessageIter *i, bool is_property_change) { - const char *key; - DBusMessageIter variant_i; - - pa_assert(y); - - key = check_variant_property(i); - if (key == NULL) - return -1; - - dbus_message_iter_recurse(i, &variant_i); - - switch (dbus_message_iter_get_arg_type(&variant_i)) { - - case DBUS_TYPE_ARRAY: { - - DBusMessageIter ai; - dbus_message_iter_recurse(&variant_i, &ai); - - if (pa_streq(key, "Adapters")) { - y->adapters_listed = true; - - if (dbus_message_iter_get_arg_type(&ai) != DBUS_TYPE_OBJECT_PATH) - break; - - while (dbus_message_iter_get_arg_type(&ai) != DBUS_TYPE_INVALID) { - const char *value; - - dbus_message_iter_get_basic(&ai, &value); - - found_adapter(y, value); - - dbus_message_iter_next(&ai); - } - } - - break; - } - } - - return 0; -} - -static int parse_adapter_property(pa_bluez4_discovery *y, DBusMessageIter *i, bool is_property_change) { - const char *key; - DBusMessageIter variant_i; - - pa_assert(y); - - key = check_variant_property(i); - if (key == NULL) - return -1; - - dbus_message_iter_recurse(i, &variant_i); - - switch (dbus_message_iter_get_arg_type(&variant_i)) { - - case DBUS_TYPE_ARRAY: { - - DBusMessageIter ai; - dbus_message_iter_recurse(&variant_i, &ai); - - if (dbus_message_iter_get_arg_type(&ai) == DBUS_TYPE_OBJECT_PATH && - pa_streq(key, "Devices")) { - - while (dbus_message_iter_get_arg_type(&ai) != DBUS_TYPE_INVALID) { - const char *value; - - dbus_message_iter_get_basic(&ai, &value); - - found_device(y, value); - - dbus_message_iter_next(&ai); - } - } - - break; - } - } - - return 0; -} - -static int parse_device_property(pa_bluez4_device *d, DBusMessageIter *i, bool is_property_change) { - const char *key; - DBusMessageIter variant_i; - - pa_assert(d); - - key = check_variant_property(i); - if (key == NULL) - return -1; - - dbus_message_iter_recurse(i, &variant_i); - -/* pa_log_debug("Parsing property org.bluez.Device.%s", key); */ - - switch (dbus_message_iter_get_arg_type(&variant_i)) { - - case DBUS_TYPE_STRING: { - - const char *value; - dbus_message_iter_get_basic(&variant_i, &value); - - if (pa_streq(key, "Name")) { - pa_xfree(d->name); - d->name = pa_xstrdup(value); - } else if (pa_streq(key, "Alias")) { - pa_xfree(d->alias); - d->alias = pa_xstrdup(value); - } else if (pa_streq(key, "Address")) { - if (is_property_change) { - pa_log("Device property 'Address' expected to be constant but changed for %s", d->path); - return -1; - } - - if (d->address) { - pa_log("Device %s: Received a duplicate Address property.", d->path); - return -1; - } - - d->address = pa_xstrdup(value); - } - -/* pa_log_debug("Value %s", value); */ - - break; - } - - case DBUS_TYPE_BOOLEAN: { - - dbus_bool_t value; - dbus_message_iter_get_basic(&variant_i, &value); - - if (pa_streq(key, "Paired")) - d->paired = !!value; - else if (pa_streq(key, "Trusted")) - d->trusted = !!value; - -/* pa_log_debug("Value %s", pa_yes_no(value)); */ - - break; - } - - case DBUS_TYPE_UINT32: { - - uint32_t value; - dbus_message_iter_get_basic(&variant_i, &value); - - if (pa_streq(key, "Class")) - d->class = (int) value; - -/* pa_log_debug("Value %u", (unsigned) value); */ - - break; - } - - case DBUS_TYPE_ARRAY: { - DBusMessageIter ai; - dbus_message_iter_recurse(&variant_i, &ai); - - if (dbus_message_iter_get_arg_type(&ai) == DBUS_TYPE_STRING && pa_streq(key, "UUIDs")) { - DBusMessage *m; - bool has_audio = false; - - /* bluetoothd never removes UUIDs from a device object so we - * don't need to check for disappeared UUIDs here. */ - while (dbus_message_iter_get_arg_type(&ai) != DBUS_TYPE_INVALID) { - const char *value; - char *uuid; - struct pa_bluez4_hook_uuid_data uuiddata; - - dbus_message_iter_get_basic(&ai, &value); - - if (pa_hashmap_get(d->uuids, value)) { - dbus_message_iter_next(&ai); - continue; - } - - uuid = pa_xstrdup(value); - pa_hashmap_put(d->uuids, uuid, uuid); - - pa_log_debug("%s: %s", key, value); - - uuiddata.device = d; - uuiddata.uuid = value; - pa_hook_fire(&d->discovery->hooks[PA_BLUEZ4_HOOK_DEVICE_UUID_ADDED], &uuiddata); - - /* Vudentz said the interfaces are here when the UUIDs are announced */ - if (pa_streq(PA_BLUEZ4_UUID_HSP_AG, value) || pa_streq(PA_BLUEZ4_UUID_HFP_AG, value)) { - pa_assert_se(m = dbus_message_new_method_call("org.bluez", d->path, "org.bluez.HandsfreeGateway", - "GetProperties")); - send_and_add_to_pending(d->discovery, m, get_properties_reply, d); - has_audio = true; - } else if (pa_streq(PA_BLUEZ4_UUID_HSP_HS, value) || pa_streq(PA_BLUEZ4_UUID_HFP_HF, value)) { - pa_assert_se(m = dbus_message_new_method_call("org.bluez", d->path, "org.bluez.Headset", - "GetProperties")); - send_and_add_to_pending(d->discovery, m, get_properties_reply, d); - has_audio = true; - } else if (pa_streq(PA_BLUEZ4_UUID_A2DP_SINK, value)) { - pa_assert_se(m = dbus_message_new_method_call("org.bluez", d->path, "org.bluez.AudioSink", - "GetProperties")); - send_and_add_to_pending(d->discovery, m, get_properties_reply, d); - has_audio = true; - } else if (pa_streq(PA_BLUEZ4_UUID_A2DP_SOURCE, value)) { - pa_assert_se(m = dbus_message_new_method_call("org.bluez", d->path, "org.bluez.AudioSource", - "GetProperties")); - send_and_add_to_pending(d->discovery, m, get_properties_reply, d); - has_audio = true; - } - - dbus_message_iter_next(&ai); - } - - /* this might eventually be racy if .Audio is not there yet, but - the State change will come anyway later, so this call is for - cold-detection mostly */ - if (has_audio) { - pa_assert_se(m = dbus_message_new_method_call("org.bluez", d->path, "org.bluez.Audio", "GetProperties")); - send_and_add_to_pending(d->discovery, m, get_properties_reply, d); - } - } - - break; - } - } - - return 0; -} - -static const char *transport_state_to_string(pa_bluez4_transport_state_t state) { - switch (state) { - case PA_BLUEZ4_TRANSPORT_STATE_DISCONNECTED: - return "disconnected"; - case PA_BLUEZ4_TRANSPORT_STATE_IDLE: - return "idle"; - case PA_BLUEZ4_TRANSPORT_STATE_PLAYING: - return "playing"; - } - - pa_assert_not_reached(); -} - -static int parse_audio_property(pa_bluez4_device *d, const char *interface, DBusMessageIter *i, bool is_property_change) { - pa_bluez4_transport *transport; - const char *key; - DBusMessageIter variant_i; - bool is_audio_interface; - pa_bluez4_profile_t p = PA_BLUEZ4_PROFILE_OFF; - - pa_assert(d); - pa_assert(interface); - pa_assert(i); - - if (!(is_audio_interface = pa_streq(interface, "org.bluez.Audio"))) - if (profile_from_interface(interface, &p) < 0) - return 0; /* Interface not known so silently ignore property */ - - key = check_variant_property(i); - if (key == NULL) - return -1; - - transport = p == PA_BLUEZ4_PROFILE_OFF ? NULL : d->transports[p]; - - dbus_message_iter_recurse(i, &variant_i); - -/* pa_log_debug("Parsing property org.bluez.{Audio|AudioSink|AudioSource|Headset}.%s", key); */ - - switch (dbus_message_iter_get_arg_type(&variant_i)) { - - case DBUS_TYPE_STRING: { - - const char *value; - dbus_message_iter_get_basic(&variant_i, &value); - - if (pa_streq(key, "State")) { - pa_bluez4_audio_state_t state = audio_state_from_string(value); - - pa_log_debug("Device %s interface %s property 'State' changed to value '%s'", d->path, interface, value); - - if (state == PA_BLUEZ4_AUDIO_STATE_INVALID) - return -1; - - if (is_audio_interface) { - d->audio_state = state; - break; - } - - pa_assert(p != PA_BLUEZ4_PROFILE_OFF); - - d->profile_state[p] = state; - - if (!transport) - break; - - transport_set_state(transport, audio_state_to_transport_state(state)); - } - - break; - } - - case DBUS_TYPE_UINT16: { - uint16_t value; - - dbus_message_iter_get_basic(&variant_i, &value); - - if (pa_streq(key, "MicrophoneGain")) { - uint16_t gain; - - pa_log_debug("dbus: property '%s' changed to value '%u'", key, value); - - if (!transport) { - pa_log("Volume change does not have an associated transport"); - return -1; - } - - if ((gain = PA_MIN(value, HSP_MAX_GAIN)) == transport->microphone_gain) - break; - - transport->microphone_gain = gain; - pa_hook_fire(&d->discovery->hooks[PA_BLUEZ4_HOOK_TRANSPORT_MICROPHONE_GAIN_CHANGED], transport); - } else if (pa_streq(key, "SpeakerGain")) { - uint16_t gain; - - pa_log_debug("dbus: property '%s' changed to value '%u'", key, value); - - if (!transport) { - pa_log("Volume change does not have an associated transport"); - return -1; - } - - if ((gain = PA_MIN(value, HSP_MAX_GAIN)) == transport->speaker_gain) - break; - - transport->speaker_gain = gain; - pa_hook_fire(&d->discovery->hooks[PA_BLUEZ4_HOOK_TRANSPORT_SPEAKER_GAIN_CHANGED], transport); - } - - break; - } - } - - return 0; -} - -static void run_callback(pa_bluez4_device *d, bool dead) { - pa_assert(d); - - if (d->device_info_valid != 1) - return; - - d->dead = dead; - pa_hook_fire(&d->discovery->hooks[PA_BLUEZ4_HOOK_DEVICE_CONNECTION_CHANGED], d); -} - -static void remove_all_devices(pa_bluez4_discovery *y) { - pa_bluez4_device *d; - - pa_assert(y); - - while ((d = pa_hashmap_steal_first(y->devices))) { - run_callback(d, true); - device_free(d); - } -} - -static pa_bluez4_device *found_device(pa_bluez4_discovery *y, const char* path) { - DBusMessage *m; - pa_bluez4_device *d; - - pa_assert(y); - pa_assert(path); - - d = pa_hashmap_get(y->devices, path); - if (d) - return d; - - d = device_new(y, path); - - pa_hashmap_put(y->devices, d->path, d); - - pa_assert_se(m = dbus_message_new_method_call("org.bluez", path, "org.bluez.Device", "GetProperties")); - send_and_add_to_pending(y, m, get_properties_reply, d); - - /* Before we read the other properties (Audio, AudioSink, AudioSource, - * Headset) we wait that the UUID is read */ - return d; -} - -static void get_properties_reply(DBusPendingCall *pending, void *userdata) { - DBusMessage *r; - DBusMessageIter arg_i, element_i; - pa_dbus_pending *p; - pa_bluez4_device *d; - pa_bluez4_discovery *y; - int valid; - bool old_any_connected; - - pa_assert_se(p = userdata); - pa_assert_se(y = p->context_data); - pa_assert_se(r = dbus_pending_call_steal_reply(pending)); - -/* pa_log_debug("Got %s.GetProperties response for %s", */ -/* dbus_message_get_interface(p->message), */ -/* dbus_message_get_path(p->message)); */ - - /* We don't use p->call_data here right-away since the device - * might already be invalidated at this point */ - - if (dbus_message_has_interface(p->message, "org.bluez.Manager") || - dbus_message_has_interface(p->message, "org.bluez.Adapter")) - d = NULL; - else if (!(d = pa_hashmap_get(y->devices, dbus_message_get_path(p->message)))) { - pa_log_warn("Received GetProperties() reply from unknown device: %s (device removed?)", dbus_message_get_path(p->message)); - goto finish2; - } - - pa_assert(p->call_data == d); - - if (d != NULL) { - old_any_connected = pa_bluez4_device_any_audio_connected(d); - valid = dbus_message_get_type(r) == DBUS_MESSAGE_TYPE_ERROR ? -1 : 1; - - if (dbus_message_is_method_call(p->message, "org.bluez.Device", "GetProperties")) - d->device_info_valid = valid; - } - - if (dbus_message_is_error(r, DBUS_ERROR_SERVICE_UNKNOWN)) { - pa_log_debug("Bluetooth daemon is apparently not available."); - remove_all_devices(y); - goto finish2; - } - - if (dbus_message_get_type(r) == DBUS_MESSAGE_TYPE_ERROR) { - pa_log("%s.GetProperties() failed: %s: %s", dbus_message_get_interface(p->message), dbus_message_get_error_name(r), - pa_dbus_get_error_message(r)); - goto finish; - } - - if (!dbus_message_iter_init(r, &arg_i)) { - pa_log("GetProperties reply has no arguments."); - goto finish; - } - - if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_ARRAY) { - pa_log("GetProperties argument is not an array."); - goto finish; - } - - dbus_message_iter_recurse(&arg_i, &element_i); - while (dbus_message_iter_get_arg_type(&element_i) != DBUS_TYPE_INVALID) { - - if (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_DICT_ENTRY) { - DBusMessageIter dict_i; - - dbus_message_iter_recurse(&element_i, &dict_i); - - if (dbus_message_has_interface(p->message, "org.bluez.Manager")) { - if (parse_manager_property(y, &dict_i, false) < 0) - goto finish; - - } else if (dbus_message_has_interface(p->message, "org.bluez.Adapter")) { - if (parse_adapter_property(y, &dict_i, false) < 0) - goto finish; - - } else if (dbus_message_has_interface(p->message, "org.bluez.Device")) { - if (parse_device_property(d, &dict_i, false) < 0) - goto finish; - - } else if (parse_audio_property(d, dbus_message_get_interface(p->message), &dict_i, false) < 0) - goto finish; - - } - - dbus_message_iter_next(&element_i); - } - -finish: - if (d != NULL && old_any_connected != pa_bluez4_device_any_audio_connected(d)) - run_callback(d, false); - -finish2: - dbus_message_unref(r); - - PA_LLIST_REMOVE(pa_dbus_pending, y->pending, p); - pa_dbus_pending_free(p); -} - -static pa_dbus_pending* send_and_add_to_pending(pa_bluez4_discovery *y, DBusMessage *m, DBusPendingCallNotifyFunction func, - void *call_data) { - pa_dbus_pending *p; - DBusPendingCall *call; - - pa_assert(y); - pa_assert(m); - - pa_assert_se(dbus_connection_send_with_reply(pa_dbus_connection_get(y->connection), m, &call, -1)); - - p = pa_dbus_pending_new(pa_dbus_connection_get(y->connection), m, call, y, call_data); - PA_LLIST_PREPEND(pa_dbus_pending, y->pending, p); - dbus_pending_call_set_notify(call, func, p, NULL); - - return p; -} - -static void register_endpoint_reply(DBusPendingCall *pending, void *userdata) { - DBusMessage *r; - pa_dbus_pending *p; - pa_bluez4_discovery *y; - char *endpoint; - - pa_assert(pending); - pa_assert_se(p = userdata); - pa_assert_se(y = p->context_data); - pa_assert_se(endpoint = p->call_data); - pa_assert_se(r = dbus_pending_call_steal_reply(pending)); - - if (dbus_message_is_error(r, DBUS_ERROR_SERVICE_UNKNOWN)) { - pa_log_debug("Bluetooth daemon is apparently not available."); - remove_all_devices(y); - goto finish; - } - - if (dbus_message_is_error(r, PA_BLUEZ4_ERROR_NOT_SUPPORTED)) { - pa_log_info("Couldn't register endpoint %s, because BlueZ is configured to disable the endpoint type.", endpoint); - goto finish; - } - - if (dbus_message_get_type(r) == DBUS_MESSAGE_TYPE_ERROR) { - pa_log("org.bluez.Media.RegisterEndpoint() failed: %s: %s", dbus_message_get_error_name(r), - pa_dbus_get_error_message(r)); - goto finish; - } - -finish: - dbus_message_unref(r); - - PA_LLIST_REMOVE(pa_dbus_pending, y->pending, p); - pa_dbus_pending_free(p); - - pa_xfree(endpoint); -} - -static void register_endpoint(pa_bluez4_discovery *y, const char *path, const char *endpoint, const char *uuid) { - DBusMessage *m; - DBusMessageIter i, d; - uint8_t codec = 0; - - pa_log_debug("Registering %s on adapter %s.", endpoint, path); - - pa_assert_se(m = dbus_message_new_method_call("org.bluez", path, "org.bluez.Media", "RegisterEndpoint")); - - dbus_message_iter_init_append(m, &i); - - pa_assert_se(dbus_message_iter_append_basic(&i, DBUS_TYPE_OBJECT_PATH, &endpoint)); - - dbus_message_iter_open_container(&i, DBUS_TYPE_ARRAY, DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING - DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING, - &d); - - pa_dbus_append_basic_variant_dict_entry(&d, "UUID", DBUS_TYPE_STRING, &uuid); - - pa_dbus_append_basic_variant_dict_entry(&d, "Codec", DBUS_TYPE_BYTE, &codec); - - if (pa_streq(uuid, PA_BLUEZ4_UUID_HFP_AG) || pa_streq(uuid, PA_BLUEZ4_UUID_HFP_HF)) { - uint8_t capability = 0; - pa_dbus_append_basic_array_variant_dict_entry(&d, "Capabilities", DBUS_TYPE_BYTE, &capability, 1); - } else { - a2dp_sbc_t capabilities; - - capabilities.channel_mode = SBC_CHANNEL_MODE_MONO | SBC_CHANNEL_MODE_DUAL_CHANNEL | - SBC_CHANNEL_MODE_STEREO | SBC_CHANNEL_MODE_JOINT_STEREO; - capabilities.frequency = SBC_SAMPLING_FREQ_16000 | SBC_SAMPLING_FREQ_32000 | - SBC_SAMPLING_FREQ_44100 | SBC_SAMPLING_FREQ_48000; - capabilities.allocation_method = SBC_ALLOCATION_SNR | SBC_ALLOCATION_LOUDNESS; - capabilities.subbands = SBC_SUBBANDS_4 | SBC_SUBBANDS_8; - capabilities.block_length = SBC_BLOCK_LENGTH_4 | SBC_BLOCK_LENGTH_8 | - SBC_BLOCK_LENGTH_12 | SBC_BLOCK_LENGTH_16; - capabilities.min_bitpool = MIN_BITPOOL; - capabilities.max_bitpool = MAX_BITPOOL; - - pa_dbus_append_basic_array_variant_dict_entry(&d, "Capabilities", DBUS_TYPE_BYTE, &capabilities, sizeof(capabilities)); - } - - dbus_message_iter_close_container(&i, &d); - - send_and_add_to_pending(y, m, register_endpoint_reply, pa_xstrdup(endpoint)); -} - -static void found_adapter(pa_bluez4_discovery *y, const char *path) { - DBusMessage *m; - - pa_assert_se(m = dbus_message_new_method_call("org.bluez", path, "org.bluez.Adapter", "GetProperties")); - send_and_add_to_pending(y, m, get_properties_reply, NULL); - - register_endpoint(y, path, ENDPOINT_PATH_HFP_AG, PA_BLUEZ4_UUID_HFP_AG); - register_endpoint(y, path, ENDPOINT_PATH_HFP_HS, PA_BLUEZ4_UUID_HFP_HF); - register_endpoint(y, path, ENDPOINT_PATH_A2DP_SOURCE, PA_BLUEZ4_UUID_A2DP_SOURCE); - register_endpoint(y, path, ENDPOINT_PATH_A2DP_SINK, PA_BLUEZ4_UUID_A2DP_SINK); -} - -static void list_adapters(pa_bluez4_discovery *y) { - DBusMessage *m; - pa_assert(y); - - pa_assert_se(m = dbus_message_new_method_call("org.bluez", "/", "org.bluez.Manager", "GetProperties")); - send_and_add_to_pending(y, m, get_properties_reply, NULL); -} - -static int transport_parse_property(pa_bluez4_transport *t, DBusMessageIter *i) { - const char *key; - DBusMessageIter variant_i; - - key = check_variant_property(i); - if (key == NULL) - return -1; - - dbus_message_iter_recurse(i, &variant_i); - - switch (dbus_message_iter_get_arg_type(&variant_i)) { - - case DBUS_TYPE_BOOLEAN: { - - dbus_bool_t value; - dbus_message_iter_get_basic(&variant_i, &value); - - if (pa_streq(key, "NREC") && t->nrec != value) { - t->nrec = value; - pa_log_debug("Transport %s: Property 'NREC' changed to %s.", t->path, t->nrec ? "True" : "False"); - pa_hook_fire(&t->device->discovery->hooks[PA_BLUEZ4_HOOK_TRANSPORT_NREC_CHANGED], t); - } - - break; - } - } - - return 0; -} - -static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *userdata) { - DBusError err; - pa_bluez4_discovery *y; - - pa_assert(bus); - pa_assert(m); - - pa_assert_se(y = userdata); - - dbus_error_init(&err); - - pa_log_debug("dbus: interface=%s, path=%s, member=%s", - dbus_message_get_interface(m), - dbus_message_get_path(m), - dbus_message_get_member(m)); - - if (dbus_message_is_signal(m, "org.bluez.Adapter", "DeviceRemoved")) { - const char *path; - pa_bluez4_device *d; - - if (!dbus_message_get_args(m, &err, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID)) { - pa_log("Failed to parse org.bluez.Adapter.DeviceRemoved: %s", err.message); - goto fail; - } - - pa_log_debug("Device %s removed", path); - - if ((d = pa_hashmap_remove(y->devices, path))) { - run_callback(d, true); - device_free(d); - } - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - } else if (dbus_message_is_signal(m, "org.bluez.Adapter", "DeviceCreated")) { - const char *path; - - if (!dbus_message_get_args(m, &err, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID)) { - pa_log("Failed to parse org.bluez.Adapter.DeviceCreated: %s", err.message); - goto fail; - } - - pa_log_debug("Device %s created", path); - - found_device(y, path); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - } else if (dbus_message_is_signal(m, "org.bluez.Manager", "AdapterAdded")) { - const char *path; - - if (!dbus_message_get_args(m, &err, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID)) { - pa_log("Failed to parse org.bluez.Manager.AdapterAdded: %s", err.message); - goto fail; - } - - if (!y->adapters_listed) { - pa_log_debug("Ignoring 'AdapterAdded' because initial adapter list has not been received yet."); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } - - pa_log_debug("Adapter %s created", path); - - found_adapter(y, path); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - } else if (dbus_message_is_signal(m, "org.bluez.Audio", "PropertyChanged") || - dbus_message_is_signal(m, "org.bluez.Headset", "PropertyChanged") || - dbus_message_is_signal(m, "org.bluez.AudioSink", "PropertyChanged") || - dbus_message_is_signal(m, "org.bluez.AudioSource", "PropertyChanged") || - dbus_message_is_signal(m, "org.bluez.HandsfreeGateway", "PropertyChanged") || - dbus_message_is_signal(m, "org.bluez.Device", "PropertyChanged")) { - - pa_bluez4_device *d; - - if ((d = pa_hashmap_get(y->devices, dbus_message_get_path(m)))) { - DBusMessageIter arg_i; - bool old_any_connected = pa_bluez4_device_any_audio_connected(d); - - if (!dbus_message_iter_init(m, &arg_i)) { - pa_log("Failed to parse PropertyChanged for device %s", d->path); - goto fail; - } - - if (dbus_message_has_interface(m, "org.bluez.Device")) { - if (parse_device_property(d, &arg_i, true) < 0) - goto fail; - - } else if (parse_audio_property(d, dbus_message_get_interface(m), &arg_i, true) < 0) - goto fail; - - if (old_any_connected != pa_bluez4_device_any_audio_connected(d)) - run_callback(d, false); - } - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - } else if (dbus_message_is_signal(m, "org.freedesktop.DBus", "NameOwnerChanged")) { - const char *name, *old_owner, *new_owner; - - if (!dbus_message_get_args(m, &err, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_STRING, &old_owner, - DBUS_TYPE_STRING, &new_owner, - DBUS_TYPE_INVALID)) { - pa_log("Failed to parse org.freedesktop.DBus.NameOwnerChanged: %s", err.message); - goto fail; - } - - if (pa_streq(name, "org.bluez")) { - if (old_owner && *old_owner) { - pa_log_debug("Bluetooth daemon disappeared."); - remove_all_devices(y); - y->adapters_listed = false; - } - - if (new_owner && *new_owner) { - pa_log_debug("Bluetooth daemon appeared."); - list_adapters(y); - } - } - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } else if (dbus_message_is_signal(m, "org.bluez.MediaTransport", "PropertyChanged")) { - pa_bluez4_transport *t; - DBusMessageIter arg_i; - - if (!(t = pa_hashmap_get(y->transports, dbus_message_get_path(m)))) - goto fail; - - if (!dbus_message_iter_init(m, &arg_i)) { - pa_log("Failed to parse PropertyChanged for transport %s", t->path); - goto fail; - } - - if (transport_parse_property(t, &arg_i) < 0) - goto fail; - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } - -fail: - dbus_error_free(&err); - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - -pa_bluez4_device* pa_bluez4_discovery_get_by_address(pa_bluez4_discovery *y, const char* address) { - pa_bluez4_device *d; - void *state = NULL; - - pa_assert(y); - pa_assert(PA_REFCNT_VALUE(y) > 0); - pa_assert(address); - - while ((d = pa_hashmap_iterate(y->devices, &state, NULL))) - if (pa_streq(d->address, address)) - return d->device_info_valid == 1 ? d : NULL; - - return NULL; -} - -pa_bluez4_device* pa_bluez4_discovery_get_by_path(pa_bluez4_discovery *y, const char* path) { - pa_bluez4_device *d; - - pa_assert(y); - pa_assert(PA_REFCNT_VALUE(y) > 0); - pa_assert(path); - - if ((d = pa_hashmap_get(y->devices, path))) - if (d->device_info_valid == 1) - return d; - - return NULL; -} - -bool pa_bluez4_device_any_audio_connected(const pa_bluez4_device *d) { - unsigned i; - - pa_assert(d); - - if (d->dead || d->device_info_valid != 1) - return false; - - if (d->audio_state == PA_BLUEZ4_AUDIO_STATE_INVALID) - return false; - - /* Make sure audio_state is *not* in CONNECTING state before we fire the - * hook to report the new device state. This is actually very important in - * order to make module-card-restore work well with headsets: if the headset - * supports both HSP and A2DP, one of those profiles is connected first and - * then the other, and lastly the Audio interface becomes connected. - * Checking only audio_state means that this function will return false at - * the time when only the first connection has been made. This is good, - * because otherwise, if the first connection is for HSP and we would - * already load a new device module instance, and module-card-restore tries - * to restore the A2DP profile, that would fail because A2DP is not yet - * connected. Waiting until the Audio interface gets connected means that - * both headset profiles will be connected when the device module is - * loaded. */ - if (d->audio_state == PA_BLUEZ4_AUDIO_STATE_CONNECTING) - return false; - - for (i = 0; i < PA_BLUEZ4_PROFILE_COUNT; i++) - if (d->transports[i] && d->transports[i]->state != PA_BLUEZ4_TRANSPORT_STATE_DISCONNECTED) - return true; - - return false; -} - -int pa_bluez4_transport_acquire(pa_bluez4_transport *t, bool optional, size_t *imtu, size_t *omtu) { - const char *accesstype = "rw"; - DBusMessage *m, *r; - DBusError err; - int ret; - uint16_t i, o; - - pa_assert(t); - pa_assert(t->device); - pa_assert(t->device->discovery); - - if (optional) { - /* FIXME: we are trying to acquire the transport only if the stream is - playing, without actually initiating the stream request from our side - (which is typically undesireable specially for hfgw use-cases. - However this approach is racy, since the stream could have been - suspended in the meantime, so we can't really guarantee that the - stream will not be requested until BlueZ's API supports this - atomically. */ - if (t->state < PA_BLUEZ4_TRANSPORT_STATE_PLAYING) { - pa_log_info("Failed optional acquire of transport %s", t->path); - return -1; - } - } - - dbus_error_init(&err); - - pa_assert_se(m = dbus_message_new_method_call(t->owner, t->path, "org.bluez.MediaTransport", "Acquire")); - pa_assert_se(dbus_message_append_args(m, DBUS_TYPE_STRING, &accesstype, DBUS_TYPE_INVALID)); - r = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(t->device->discovery->connection), m, -1, &err); - dbus_message_unref(m); - m = NULL; - - if (!r) { - dbus_error_free(&err); - return -1; - } - - if (!dbus_message_get_args(r, &err, DBUS_TYPE_UNIX_FD, &ret, DBUS_TYPE_UINT16, &i, DBUS_TYPE_UINT16, &o, - DBUS_TYPE_INVALID)) { - pa_log("Failed to parse org.bluez.MediaTransport.Acquire(): %s", err.message); - ret = -1; - dbus_error_free(&err); - goto fail; - } - - if (imtu) - *imtu = i; - - if (omtu) - *omtu = o; - -fail: - dbus_message_unref(r); - return ret; -} - -void pa_bluez4_transport_release(pa_bluez4_transport *t) { - const char *accesstype = "rw"; - DBusMessage *m, *r; - DBusError err; - - pa_assert(t); - pa_assert(t->device); - pa_assert(t->device->discovery); - - dbus_error_init(&err); - - pa_assert_se(m = dbus_message_new_method_call(t->owner, t->path, "org.bluez.MediaTransport", "Release")); - pa_assert_se(dbus_message_append_args(m, DBUS_TYPE_STRING, &accesstype, DBUS_TYPE_INVALID)); - r = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(t->device->discovery->connection), m, -1, &err); - dbus_message_unref(m); - m = NULL; - if (r) { - dbus_message_unref(r); - r = NULL; - } - - if (dbus_error_is_set(&err)) { - pa_log("Failed to release transport %s: %s", t->path, err.message); - dbus_error_free(&err); - } else - pa_log_info("Transport %s released", t->path); -} - -static void set_property(pa_bluez4_discovery *y, const char *bus, const char *path, const char *interface, - const char *prop_name, int prop_type, void *prop_value) { - DBusMessage *m; - DBusMessageIter i; - - pa_assert(y); - pa_assert(path); - pa_assert(interface); - pa_assert(prop_name); - - pa_assert_se(m = dbus_message_new_method_call(bus, path, interface, "SetProperty")); - dbus_message_iter_init_append(m, &i); - pa_assert_se(dbus_message_iter_append_basic(&i, DBUS_TYPE_STRING, &prop_name)); - pa_dbus_append_basic_variant(&i, prop_type, prop_value); - - dbus_message_set_no_reply(m, true); - pa_assert_se(dbus_connection_send(pa_dbus_connection_get(y->connection), m, NULL)); - dbus_message_unref(m); -} - -void pa_bluez4_transport_set_microphone_gain(pa_bluez4_transport *t, uint16_t value) { - dbus_uint16_t gain = PA_MIN(value, HSP_MAX_GAIN); - - pa_assert(t); - pa_assert(t->profile == PA_BLUEZ4_PROFILE_HEADSET_HEAD_UNIT); - - set_property(t->device->discovery, "org.bluez", t->device->path, "org.bluez.Headset", - "MicrophoneGain", DBUS_TYPE_UINT16, &gain); -} - -void pa_bluez4_transport_set_speaker_gain(pa_bluez4_transport *t, uint16_t value) { - dbus_uint16_t gain = PA_MIN(value, HSP_MAX_GAIN); - - pa_assert(t); - pa_assert(t->profile == PA_BLUEZ4_PROFILE_HEADSET_HEAD_UNIT); - - set_property(t->device->discovery, "org.bluez", t->device->path, "org.bluez.Headset", - "SpeakerGain", DBUS_TYPE_UINT16, &gain); -} - -static int setup_dbus(pa_bluez4_discovery *y) { - DBusError err; - - dbus_error_init(&err); - - if (!(y->connection = pa_dbus_bus_get(y->core, DBUS_BUS_SYSTEM, &err))) { - pa_log("Failed to get D-Bus connection: %s", err.message); - dbus_error_free(&err); - return -1; - } - - return 0; -} - -static pa_bluez4_transport *transport_new(pa_bluez4_device *d, const char *owner, const char *path, pa_bluez4_profile_t p, - const uint8_t *config, int size) { - pa_bluez4_transport *t; - - t = pa_xnew0(pa_bluez4_transport, 1); - t->device = d; - t->owner = pa_xstrdup(owner); - t->path = pa_xstrdup(path); - t->profile = p; - t->config_size = size; - - if (size > 0) { - t->config = pa_xnew(uint8_t, size); - memcpy(t->config, config, size); - } - - t->state = audio_state_to_transport_state(d->profile_state[p]); - - return t; -} - -static void transport_set_state(pa_bluez4_transport *transport, pa_bluez4_transport_state_t state) { - if (transport->state == state) - return; - - pa_log_debug("Transport %s state: %s -> %s", - transport->path, transport_state_to_string(transport->state), transport_state_to_string(state)); - - transport->state = state; - - pa_hook_fire(&transport->device->discovery->hooks[PA_BLUEZ4_HOOK_TRANSPORT_STATE_CHANGED], transport); -} - -static DBusMessage *endpoint_set_configuration(DBusConnection *conn, DBusMessage *m, void *userdata) { - pa_bluez4_discovery *y = userdata; - pa_bluez4_device *d; - pa_bluez4_transport *t; - const char *sender, *path, *dev_path = NULL, *uuid = NULL; - uint8_t *config = NULL; - int size = 0; - bool nrec = false; - pa_bluez4_profile_t p; - DBusMessageIter args, props; - DBusMessage *r; - bool old_any_connected; - - if (!dbus_message_iter_init(m, &args) || !pa_streq(dbus_message_get_signature(m), "oa{sv}")) { - pa_log("Invalid signature for method SetConfiguration"); - goto fail2; - } - - dbus_message_iter_get_basic(&args, &path); - - if (pa_hashmap_get(y->transports, path)) { - pa_log("org.bluez.MediaEndpoint.SetConfiguration: Transport %s is already configured.", path); - goto fail2; - } - - pa_assert_se(dbus_message_iter_next(&args)); - - dbus_message_iter_recurse(&args, &props); - if (dbus_message_iter_get_arg_type(&props) != DBUS_TYPE_DICT_ENTRY) - goto fail; - - /* Read transport properties */ - while (dbus_message_iter_get_arg_type(&props) == DBUS_TYPE_DICT_ENTRY) { - const char *key; - DBusMessageIter value, entry; - int var; - - dbus_message_iter_recurse(&props, &entry); - dbus_message_iter_get_basic(&entry, &key); - - dbus_message_iter_next(&entry); - dbus_message_iter_recurse(&entry, &value); - - var = dbus_message_iter_get_arg_type(&value); - - if (strcasecmp(key, "UUID") == 0) { - if (var != DBUS_TYPE_STRING) - goto fail; - - dbus_message_iter_get_basic(&value, &uuid); - } else if (strcasecmp(key, "Device") == 0) { - if (var != DBUS_TYPE_OBJECT_PATH) - goto fail; - - dbus_message_iter_get_basic(&value, &dev_path); - } else if (strcasecmp(key, "NREC") == 0) { - dbus_bool_t tmp_boolean; - if (var != DBUS_TYPE_BOOLEAN) - goto fail; - - dbus_message_iter_get_basic(&value, &tmp_boolean); - nrec = tmp_boolean; - } else if (strcasecmp(key, "Configuration") == 0) { - DBusMessageIter array; - if (var != DBUS_TYPE_ARRAY) - goto fail; - - dbus_message_iter_recurse(&value, &array); - dbus_message_iter_get_fixed_array(&array, &config, &size); - } - - dbus_message_iter_next(&props); - } - - d = found_device(y, dev_path); - if (!d) - goto fail; - - if (dbus_message_has_path(m, ENDPOINT_PATH_HFP_AG)) - p = PA_BLUEZ4_PROFILE_HEADSET_HEAD_UNIT; - else if (dbus_message_has_path(m, ENDPOINT_PATH_HFP_HS)) - p = PA_BLUEZ4_PROFILE_HEADSET_AUDIO_GATEWAY; - else if (dbus_message_has_path(m, ENDPOINT_PATH_A2DP_SOURCE)) - p = PA_BLUEZ4_PROFILE_A2DP_SINK; - else - p = PA_BLUEZ4_PROFILE_A2DP_SOURCE; - - if (d->transports[p] != NULL) { - pa_log("Cannot configure transport %s because profile %d is already used", path, p); - goto fail2; - } - - old_any_connected = pa_bluez4_device_any_audio_connected(d); - - sender = dbus_message_get_sender(m); - - t = transport_new(d, sender, path, p, config, size); - if (nrec) - t->nrec = nrec; - - d->transports[p] = t; - pa_assert_se(pa_hashmap_put(y->transports, t->path, t) >= 0); - - pa_log_debug("Transport %s profile %d available", t->path, t->profile); - - pa_assert_se(r = dbus_message_new_method_return(m)); - pa_assert_se(dbus_connection_send(pa_dbus_connection_get(y->connection), r, NULL)); - dbus_message_unref(r); - - if (old_any_connected != pa_bluez4_device_any_audio_connected(d)) - run_callback(d, false); - - return NULL; - -fail: - pa_log("org.bluez.MediaEndpoint.SetConfiguration: invalid arguments"); - -fail2: - pa_assert_se(r = dbus_message_new_error(m, "org.bluez.MediaEndpoint.Error.InvalidArguments", - "Unable to set configuration")); - return r; -} - -static DBusMessage *endpoint_clear_configuration(DBusConnection *c, DBusMessage *m, void *userdata) { - pa_bluez4_discovery *y = userdata; - pa_bluez4_transport *t; - DBusMessage *r; - DBusError e; - const char *path; - - dbus_error_init(&e); - - if (!dbus_message_get_args(m, &e, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID)) { - pa_log("org.bluez.MediaEndpoint.ClearConfiguration: %s", e.message); - dbus_error_free(&e); - goto fail; - } - - if ((t = pa_hashmap_get(y->transports, path))) { - bool old_any_connected = pa_bluez4_device_any_audio_connected(t->device); - - pa_log_debug("Clearing transport %s profile %d", t->path, t->profile); - t->device->transports[t->profile] = NULL; - pa_hashmap_remove(y->transports, t->path); - transport_set_state(t, PA_BLUEZ4_TRANSPORT_STATE_DISCONNECTED); - - if (old_any_connected != pa_bluez4_device_any_audio_connected(t->device)) - run_callback(t->device, false); - - transport_free(t); - } - - pa_assert_se(r = dbus_message_new_method_return(m)); - - return r; - -fail: - pa_assert_se(r = dbus_message_new_error(m, "org.bluez.MediaEndpoint.Error.InvalidArguments", - "Unable to clear configuration")); - return r; -} - -static uint8_t a2dp_default_bitpool(uint8_t freq, uint8_t mode) { - - switch (freq) { - case SBC_SAMPLING_FREQ_16000: - case SBC_SAMPLING_FREQ_32000: - return 53; - - case SBC_SAMPLING_FREQ_44100: - - switch (mode) { - case SBC_CHANNEL_MODE_MONO: - case SBC_CHANNEL_MODE_DUAL_CHANNEL: - return 31; - - case SBC_CHANNEL_MODE_STEREO: - case SBC_CHANNEL_MODE_JOINT_STEREO: - return 53; - - default: - pa_log_warn("Invalid channel mode %u", mode); - return 53; - } - - case SBC_SAMPLING_FREQ_48000: - - switch (mode) { - case SBC_CHANNEL_MODE_MONO: - case SBC_CHANNEL_MODE_DUAL_CHANNEL: - return 29; - - case SBC_CHANNEL_MODE_STEREO: - case SBC_CHANNEL_MODE_JOINT_STEREO: - return 51; - - default: - pa_log_warn("Invalid channel mode %u", mode); - return 51; - } - - default: - pa_log_warn("Invalid sampling freq %u", freq); - return 53; - } -} - -static DBusMessage *endpoint_select_configuration(DBusConnection *c, DBusMessage *m, void *userdata) { - pa_bluez4_discovery *y = userdata; - a2dp_sbc_t *cap, config; - uint8_t *pconf = (uint8_t *) &config; - int i, size; - DBusMessage *r; - DBusError e; - - static const struct { - uint32_t rate; - uint8_t cap; - } freq_table[] = { - { 16000U, SBC_SAMPLING_FREQ_16000 }, - { 32000U, SBC_SAMPLING_FREQ_32000 }, - { 44100U, SBC_SAMPLING_FREQ_44100 }, - { 48000U, SBC_SAMPLING_FREQ_48000 } - }; - - dbus_error_init(&e); - - if (!dbus_message_get_args(m, &e, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &cap, &size, DBUS_TYPE_INVALID)) { - pa_log("org.bluez.MediaEndpoint.SelectConfiguration: %s", e.message); - dbus_error_free(&e); - goto fail; - } - - if (dbus_message_has_path(m, ENDPOINT_PATH_HFP_AG) || dbus_message_has_path(m, ENDPOINT_PATH_HFP_HS)) - goto done; - - pa_assert(size == sizeof(config)); - - memset(&config, 0, sizeof(config)); - - /* Find the lowest freq that is at least as high as the requested - * sampling rate */ - for (i = 0; (unsigned) i < PA_ELEMENTSOF(freq_table); i++) - if (freq_table[i].rate >= y->core->default_sample_spec.rate && (cap->frequency & freq_table[i].cap)) { - config.frequency = freq_table[i].cap; - break; - } - - if ((unsigned) i == PA_ELEMENTSOF(freq_table)) { - for (--i; i >= 0; i--) { - if (cap->frequency & freq_table[i].cap) { - config.frequency = freq_table[i].cap; - break; - } - } - - if (i < 0) { - pa_log("Not suitable sample rate"); - goto fail; - } - } - - pa_assert((unsigned) i < PA_ELEMENTSOF(freq_table)); - - if (y->core->default_sample_spec.channels <= 1) { - if (cap->channel_mode & SBC_CHANNEL_MODE_MONO) - config.channel_mode = SBC_CHANNEL_MODE_MONO; - } - - if (y->core->default_sample_spec.channels >= 2) { - if (cap->channel_mode & SBC_CHANNEL_MODE_JOINT_STEREO) - config.channel_mode = SBC_CHANNEL_MODE_JOINT_STEREO; - else if (cap->channel_mode & SBC_CHANNEL_MODE_STEREO) - config.channel_mode = SBC_CHANNEL_MODE_STEREO; - else if (cap->channel_mode & SBC_CHANNEL_MODE_DUAL_CHANNEL) - config.channel_mode = SBC_CHANNEL_MODE_DUAL_CHANNEL; - else if (cap->channel_mode & SBC_CHANNEL_MODE_MONO) { - config.channel_mode = SBC_CHANNEL_MODE_MONO; - } else { - pa_log("No supported channel modes"); - goto fail; - } - } - - if (cap->block_length & SBC_BLOCK_LENGTH_16) - config.block_length = SBC_BLOCK_LENGTH_16; - else if (cap->block_length & SBC_BLOCK_LENGTH_12) - config.block_length = SBC_BLOCK_LENGTH_12; - else if (cap->block_length & SBC_BLOCK_LENGTH_8) - config.block_length = SBC_BLOCK_LENGTH_8; - else if (cap->block_length & SBC_BLOCK_LENGTH_4) - config.block_length = SBC_BLOCK_LENGTH_4; - else { - pa_log_error("No supported block lengths"); - goto fail; - } - - if (cap->subbands & SBC_SUBBANDS_8) - config.subbands = SBC_SUBBANDS_8; - else if (cap->subbands & SBC_SUBBANDS_4) - config.subbands = SBC_SUBBANDS_4; - else { - pa_log_error("No supported subbands"); - goto fail; - } - - if (cap->allocation_method & SBC_ALLOCATION_LOUDNESS) - config.allocation_method = SBC_ALLOCATION_LOUDNESS; - else if (cap->allocation_method & SBC_ALLOCATION_SNR) - config.allocation_method = SBC_ALLOCATION_SNR; - - config.min_bitpool = (uint8_t) PA_MAX(MIN_BITPOOL, cap->min_bitpool); - config.max_bitpool = (uint8_t) PA_MIN(a2dp_default_bitpool(config.frequency, config.channel_mode), cap->max_bitpool); - -done: - pa_assert_se(r = dbus_message_new_method_return(m)); - - pa_assert_se(dbus_message_append_args( - r, - DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &pconf, size, - DBUS_TYPE_INVALID)); - - return r; - -fail: - pa_assert_se(r = dbus_message_new_error(m, "org.bluez.MediaEndpoint.Error.InvalidArguments", - "Unable to select configuration")); - return r; -} - -static DBusHandlerResult endpoint_handler(DBusConnection *c, DBusMessage *m, void *userdata) { - struct pa_bluez4_discovery *y = userdata; - DBusMessage *r = NULL; - DBusError e; - const char *path, *interface, *member; - - pa_assert(y); - - path = dbus_message_get_path(m); - interface = dbus_message_get_interface(m); - member = dbus_message_get_member(m); - - pa_log_debug("dbus: path=%s, interface=%s, member=%s", path, interface, member); - - dbus_error_init(&e); - - if (!pa_streq(path, ENDPOINT_PATH_A2DP_SOURCE) && !pa_streq(path, ENDPOINT_PATH_A2DP_SINK) - && !pa_streq(path, ENDPOINT_PATH_HFP_AG) && !pa_streq(path, ENDPOINT_PATH_HFP_HS)) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - if (dbus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect")) { - const char *xml = ENDPOINT_INTROSPECT_XML; - - pa_assert_se(r = dbus_message_new_method_return(m)); - pa_assert_se(dbus_message_append_args(r, DBUS_TYPE_STRING, &xml, DBUS_TYPE_INVALID)); - - } else if (dbus_message_is_method_call(m, "org.bluez.MediaEndpoint", "SetConfiguration")) - r = endpoint_set_configuration(c, m, userdata); - else if (dbus_message_is_method_call(m, "org.bluez.MediaEndpoint", "SelectConfiguration")) - r = endpoint_select_configuration(c, m, userdata); - else if (dbus_message_is_method_call(m, "org.bluez.MediaEndpoint", "ClearConfiguration")) - r = endpoint_clear_configuration(c, m, userdata); - else - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - if (r) { - pa_assert_se(dbus_connection_send(pa_dbus_connection_get(y->connection), r, NULL)); - dbus_message_unref(r); - } - - return DBUS_HANDLER_RESULT_HANDLED; -} - -pa_bluez4_discovery* pa_bluez4_discovery_get(pa_core *c) { - DBusError err; - pa_bluez4_discovery *y; - DBusConnection *conn; - unsigned i; - static const DBusObjectPathVTable vtable_endpoint = { - .message_function = endpoint_handler, - }; - - pa_assert(c); - - dbus_error_init(&err); - - if ((y = pa_shared_get(c, "bluez4-discovery"))) - return pa_bluez4_discovery_ref(y); - - y = pa_xnew0(pa_bluez4_discovery, 1); - PA_REFCNT_INIT(y); - y->core = c; - y->devices = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); - y->transports = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); - PA_LLIST_HEAD_INIT(pa_dbus_pending, y->pending); - - for (i = 0; i < PA_BLUEZ4_HOOK_MAX; i++) - pa_hook_init(&y->hooks[i], y); - - pa_shared_set(c, "bluez4-discovery", y); - - if (setup_dbus(y) < 0) - goto fail; - - conn = pa_dbus_connection_get(y->connection); - - /* dynamic detection of bluetooth audio devices */ - if (!dbus_connection_add_filter(conn, filter_cb, y, NULL)) { - pa_log_error("Failed to add filter function"); - goto fail; - } - - y->filter_added = true; - - if (pa_dbus_add_matches( - conn, &err, - "type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='NameOwnerChanged'" - ",arg0='org.bluez'", - "type='signal',sender='org.bluez',interface='org.bluez.Manager',member='AdapterAdded'", - "type='signal',sender='org.bluez',interface='org.bluez.Adapter',member='DeviceRemoved'", - "type='signal',sender='org.bluez',interface='org.bluez.Adapter',member='DeviceCreated'", - "type='signal',sender='org.bluez',interface='org.bluez.Device',member='PropertyChanged'", - "type='signal',sender='org.bluez',interface='org.bluez.Audio',member='PropertyChanged'", - "type='signal',sender='org.bluez',interface='org.bluez.Headset',member='PropertyChanged'", - "type='signal',sender='org.bluez',interface='org.bluez.AudioSink',member='PropertyChanged'", - "type='signal',sender='org.bluez',interface='org.bluez.AudioSource',member='PropertyChanged'", - "type='signal',sender='org.bluez',interface='org.bluez.HandsfreeGateway',member='PropertyChanged'", - "type='signal',sender='org.bluez',interface='org.bluez.MediaTransport',member='PropertyChanged'", - NULL) < 0) { - pa_log("Failed to add D-Bus matches: %s", err.message); - goto fail; - } - - pa_assert_se(dbus_connection_register_object_path(conn, ENDPOINT_PATH_HFP_AG, &vtable_endpoint, y)); - pa_assert_se(dbus_connection_register_object_path(conn, ENDPOINT_PATH_HFP_HS, &vtable_endpoint, y)); - pa_assert_se(dbus_connection_register_object_path(conn, ENDPOINT_PATH_A2DP_SOURCE, &vtable_endpoint, y)); - pa_assert_se(dbus_connection_register_object_path(conn, ENDPOINT_PATH_A2DP_SINK, &vtable_endpoint, y)); - - list_adapters(y); - - return y; - -fail: - if (y) - pa_bluez4_discovery_unref(y); - - dbus_error_free(&err); - - return NULL; -} - -pa_bluez4_discovery* pa_bluez4_discovery_ref(pa_bluez4_discovery *y) { - pa_assert(y); - pa_assert(PA_REFCNT_VALUE(y) > 0); - - PA_REFCNT_INC(y); - - return y; -} - -void pa_bluez4_discovery_unref(pa_bluez4_discovery *y) { - unsigned i; - - pa_assert(y); - pa_assert(PA_REFCNT_VALUE(y) > 0); - - if (PA_REFCNT_DEC(y) > 0) - return; - - pa_dbus_free_pending_list(&y->pending); - - if (y->devices) { - remove_all_devices(y); - pa_hashmap_free(y->devices); - } - - if (y->transports) { - pa_assert(pa_hashmap_isempty(y->transports)); - pa_hashmap_free(y->transports); - } - - if (y->connection) { - dbus_connection_unregister_object_path(pa_dbus_connection_get(y->connection), ENDPOINT_PATH_HFP_AG); - dbus_connection_unregister_object_path(pa_dbus_connection_get(y->connection), ENDPOINT_PATH_HFP_HS); - dbus_connection_unregister_object_path(pa_dbus_connection_get(y->connection), ENDPOINT_PATH_A2DP_SOURCE); - dbus_connection_unregister_object_path(pa_dbus_connection_get(y->connection), ENDPOINT_PATH_A2DP_SINK); - pa_dbus_remove_matches( - pa_dbus_connection_get(y->connection), - "type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='NameOwnerChanged'" - ",arg0='org.bluez'", - "type='signal',sender='org.bluez',interface='org.bluez.Manager',member='AdapterAdded'", - "type='signal',sender='org.bluez',interface='org.bluez.Manager',member='AdapterRemoved'", - "type='signal',sender='org.bluez',interface='org.bluez.Adapter',member='DeviceRemoved'", - "type='signal',sender='org.bluez',interface='org.bluez.Adapter',member='DeviceCreated'", - "type='signal',sender='org.bluez',interface='org.bluez.Device',member='PropertyChanged'", - "type='signal',sender='org.bluez',interface='org.bluez.Audio',member='PropertyChanged'", - "type='signal',sender='org.bluez',interface='org.bluez.Headset',member='PropertyChanged'", - "type='signal',sender='org.bluez',interface='org.bluez.AudioSink',member='PropertyChanged'", - "type='signal',sender='org.bluez',interface='org.bluez.AudioSource',member='PropertyChanged'", - "type='signal',sender='org.bluez',interface='org.bluez.HandsfreeGateway',member='PropertyChanged'", - "type='signal',sender='org.bluez',interface='org.bluez.MediaTransport',member='PropertyChanged'", - NULL); - - if (y->filter_added) - dbus_connection_remove_filter(pa_dbus_connection_get(y->connection), filter_cb, y); - - pa_dbus_connection_unref(y->connection); - } - - for (i = 0; i < PA_BLUEZ4_HOOK_MAX; i++) - pa_hook_done(&y->hooks[i]); - - if (y->core) - pa_shared_remove(y->core, "bluez4-discovery"); - - pa_xfree(y); -} - -pa_hook* pa_bluez4_discovery_hook(pa_bluez4_discovery *y, pa_bluez4_hook_t hook) { - pa_assert(y); - pa_assert(PA_REFCNT_VALUE(y) > 0); - - return &y->hooks[hook]; -} - -pa_bluez4_form_factor_t pa_bluez4_get_form_factor(uint32_t class) { - unsigned major, minor; - pa_bluez4_form_factor_t r; - - static const pa_bluez4_form_factor_t table[] = { - [1] = PA_BLUEZ4_FORM_FACTOR_HEADSET, - [2] = PA_BLUEZ4_FORM_FACTOR_HANDSFREE, - [4] = PA_BLUEZ4_FORM_FACTOR_MICROPHONE, - [5] = PA_BLUEZ4_FORM_FACTOR_SPEAKER, - [6] = PA_BLUEZ4_FORM_FACTOR_HEADPHONE, - [7] = PA_BLUEZ4_FORM_FACTOR_PORTABLE, - [8] = PA_BLUEZ4_FORM_FACTOR_CAR, - [10] = PA_BLUEZ4_FORM_FACTOR_HIFI - }; - - /* - * See Bluetooth Assigned Numbers: - * https://www.bluetooth.org/Technical/AssignedNumbers/baseband.htm - */ - major = (class >> 8) & 0x1F; - minor = (class >> 2) & 0x3F; - - switch (major) { - case 2: - return PA_BLUEZ4_FORM_FACTOR_PHONE; - case 4: - break; - default: - pa_log_debug("Unknown Bluetooth major device class %u", major); - return PA_BLUEZ4_FORM_FACTOR_UNKNOWN; - } - - r = minor < PA_ELEMENTSOF(table) ? table[minor] : PA_BLUEZ4_FORM_FACTOR_UNKNOWN; - - if (!r) - pa_log_debug("Unknown Bluetooth minor device class %u", minor); - - return r; -} - -const char *pa_bluez4_form_factor_to_string(pa_bluez4_form_factor_t ff) { - switch (ff) { - case PA_BLUEZ4_FORM_FACTOR_UNKNOWN: - return "unknown"; - case PA_BLUEZ4_FORM_FACTOR_HEADSET: - return "headset"; - case PA_BLUEZ4_FORM_FACTOR_HANDSFREE: - return "hands-free"; - case PA_BLUEZ4_FORM_FACTOR_MICROPHONE: - return "microphone"; - case PA_BLUEZ4_FORM_FACTOR_SPEAKER: - return "speaker"; - case PA_BLUEZ4_FORM_FACTOR_HEADPHONE: - return "headphone"; - case PA_BLUEZ4_FORM_FACTOR_PORTABLE: - return "portable"; - case PA_BLUEZ4_FORM_FACTOR_CAR: - return "car"; - case PA_BLUEZ4_FORM_FACTOR_HIFI: - return "hifi"; - case PA_BLUEZ4_FORM_FACTOR_PHONE: - return "phone"; - } - - pa_assert_not_reached(); -} diff --git a/src/modules/bluetooth/bluez4-util.h b/src/modules/bluetooth/bluez4-util.h deleted file mode 100644 index f4b5ca349..000000000 --- a/src/modules/bluetooth/bluez4-util.h +++ /dev/null @@ -1,160 +0,0 @@ -#ifndef foobluez4utilhfoo -#define foobluez4utilhfoo - -/*** - This file is part of PulseAudio. - - Copyright 2008-2013 João Paulo Rechi Vita - - PulseAudio is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - PulseAudio is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. -***/ - -#include <dbus/dbus.h> - -#include <pulsecore/llist.h> -#include <pulsecore/macro.h> - -#define PA_BLUEZ4_ERROR_NOT_SUPPORTED "org.bluez.Error.NotSupported" - -#define PA_BLUEZ4_UUID_A2DP_SOURCE "0000110a-0000-1000-8000-00805f9b34fb" -#define PA_BLUEZ4_UUID_A2DP_SINK "0000110b-0000-1000-8000-00805f9b34fb" -#define PA_BLUEZ4_UUID_HSP_HS "00001108-0000-1000-8000-00805f9b34fb" -#define PA_BLUEZ4_UUID_HSP_AG "00001112-0000-1000-8000-00805f9b34fb" -#define PA_BLUEZ4_UUID_HFP_HF "0000111e-0000-1000-8000-00805f9b34fb" -#define PA_BLUEZ4_UUID_HFP_AG "0000111f-0000-1000-8000-00805f9b34fb" - -#define HSP_MAX_GAIN 15 - -typedef struct pa_bluez4_device pa_bluez4_device; -typedef struct pa_bluez4_discovery pa_bluez4_discovery; -typedef struct pa_bluez4_transport pa_bluez4_transport; - -struct userdata; - -typedef enum pa_bluez4_profile { - PA_BLUEZ4_PROFILE_A2DP_SINK, - PA_BLUEZ4_PROFILE_A2DP_SOURCE, - PA_BLUEZ4_PROFILE_HEADSET_HEAD_UNIT, - PA_BLUEZ4_PROFILE_HEADSET_AUDIO_GATEWAY, - PA_BLUEZ4_PROFILE_OFF -} pa_bluez4_profile_t; - -#define PA_BLUEZ4_PROFILE_COUNT PA_BLUEZ4_PROFILE_OFF - -struct pa_bluez4_hook_uuid_data { - pa_bluez4_device *device; - const char *uuid; -}; - -/* Hook data: pa_bluez4_discovery pointer. */ -typedef enum pa_bluez4_hook { - PA_BLUEZ4_HOOK_DEVICE_CONNECTION_CHANGED, /* Call data: pa_bluez4_device */ - PA_BLUEZ4_HOOK_DEVICE_UUID_ADDED, /* Call data: pa_bluez4_hook_uuid_data */ - PA_BLUEZ4_HOOK_TRANSPORT_STATE_CHANGED, /* Call data: pa_bluez4_transport */ - PA_BLUEZ4_HOOK_TRANSPORT_NREC_CHANGED, /* Call data: pa_bluez4_transport */ - PA_BLUEZ4_HOOK_TRANSPORT_MICROPHONE_GAIN_CHANGED, /* Call data: pa_bluez4_transport */ - PA_BLUEZ4_HOOK_TRANSPORT_SPEAKER_GAIN_CHANGED, /* Call data: pa_bluez4_transport */ - PA_BLUEZ4_HOOK_MAX -} pa_bluez4_hook_t; - -typedef enum pa_bluez4_transport_state { - PA_BLUEZ4_TRANSPORT_STATE_DISCONNECTED, - PA_BLUEZ4_TRANSPORT_STATE_IDLE, /* Connected but not playing */ - PA_BLUEZ4_TRANSPORT_STATE_PLAYING -} pa_bluez4_transport_state_t; - -struct pa_bluez4_transport { - pa_bluez4_device *device; - char *owner; - char *path; - pa_bluez4_profile_t profile; - uint8_t codec; - uint8_t *config; - int config_size; - - pa_bluez4_transport_state_t state; - bool nrec; - uint16_t microphone_gain; /* Used for HSP/HFP */ - uint16_t speaker_gain; /* Used for HSP/HFP */ -}; - -/* This enum is shared among Audio, Headset, AudioSink, and AudioSource, although not all values are acceptable in all profiles */ -typedef enum pa_bluez4_audio_state { - PA_BLUEZ4_AUDIO_STATE_INVALID = -1, - PA_BLUEZ4_AUDIO_STATE_DISCONNECTED, - PA_BLUEZ4_AUDIO_STATE_CONNECTING, - PA_BLUEZ4_AUDIO_STATE_CONNECTED, - PA_BLUEZ4_AUDIO_STATE_PLAYING -} pa_bluez4_audio_state_t; - -struct pa_bluez4_device { - pa_bluez4_discovery *discovery; - bool dead; - - int device_info_valid; /* 0: no results yet; 1: good results; -1: bad results ... */ - - /* Device information */ - char *name; - char *path; - pa_bluez4_transport *transports[PA_BLUEZ4_PROFILE_COUNT]; - int paired; - char *alias; - char *address; - int class; - pa_hashmap *uuids; /* char* -> char* (hashmap-as-a-set) */ - int trusted; - - /* Audio state */ - pa_bluez4_audio_state_t audio_state; - - /* AudioSink, AudioSource, Headset and HandsfreeGateway states */ - pa_bluez4_audio_state_t profile_state[PA_BLUEZ4_PROFILE_COUNT]; -}; - -pa_bluez4_discovery* pa_bluez4_discovery_get(pa_core *core); -pa_bluez4_discovery* pa_bluez4_discovery_ref(pa_bluez4_discovery *y); -void pa_bluez4_discovery_unref(pa_bluez4_discovery *d); - -pa_bluez4_device* pa_bluez4_discovery_get_by_path(pa_bluez4_discovery *d, const char* path); -pa_bluez4_device* pa_bluez4_discovery_get_by_address(pa_bluez4_discovery *d, const char* address); - -bool pa_bluez4_device_any_audio_connected(const pa_bluez4_device *d); - -int pa_bluez4_transport_acquire(pa_bluez4_transport *t, bool optional, size_t *imtu, size_t *omtu); -void pa_bluez4_transport_release(pa_bluez4_transport *t); - -void pa_bluez4_transport_set_microphone_gain(pa_bluez4_transport *t, uint16_t value); -void pa_bluez4_transport_set_speaker_gain(pa_bluez4_transport *t, uint16_t value); - -pa_hook* pa_bluez4_discovery_hook(pa_bluez4_discovery *y, pa_bluez4_hook_t hook); - -typedef enum pa_bluez4_form_factor { - PA_BLUEZ4_FORM_FACTOR_UNKNOWN, - PA_BLUEZ4_FORM_FACTOR_HEADSET, - PA_BLUEZ4_FORM_FACTOR_HANDSFREE, - PA_BLUEZ4_FORM_FACTOR_MICROPHONE, - PA_BLUEZ4_FORM_FACTOR_SPEAKER, - PA_BLUEZ4_FORM_FACTOR_HEADPHONE, - PA_BLUEZ4_FORM_FACTOR_PORTABLE, - PA_BLUEZ4_FORM_FACTOR_CAR, - PA_BLUEZ4_FORM_FACTOR_HIFI, - PA_BLUEZ4_FORM_FACTOR_PHONE, -} pa_bluez4_form_factor_t; - -pa_bluez4_form_factor_t pa_bluez4_get_form_factor(uint32_t class); -const char *pa_bluez4_form_factor_to_string(pa_bluez4_form_factor_t ff); - -const char *pa_bluez4_profile_to_string(pa_bluez4_profile_t profile); - -#endif diff --git a/src/modules/bluetooth/module-bluetooth-discover.c b/src/modules/bluetooth/module-bluetooth-discover.c index 49718c0c9..63195d3e1 100644 --- a/src/modules/bluetooth/module-bluetooth-discover.c +++ b/src/modules/bluetooth/module-bluetooth-discover.c @@ -36,7 +36,6 @@ PA_MODULE_USAGE( struct userdata { uint32_t bluez5_module_idx; - uint32_t bluez4_module_idx; }; int pa__init(pa_module* m) { @@ -47,7 +46,6 @@ int pa__init(pa_module* m) { m->userdata = u = pa_xnew0(struct userdata, 1); u->bluez5_module_idx = PA_INVALID_INDEX; - u->bluez4_module_idx = PA_INVALID_INDEX; if (pa_module_exists("module-bluez5-discover")) { pa_module_load(&mm, m->core, "module-bluez5-discover", m->argument); @@ -55,13 +53,7 @@ int pa__init(pa_module* m) { u->bluez5_module_idx = mm->index; } - if (pa_module_exists("module-bluez4-discover")) { - pa_module_load(&mm, m->core, "module-bluez4-discover", NULL); - if (mm) - u->bluez4_module_idx = mm->index; - } - - if (u->bluez5_module_idx == PA_INVALID_INDEX && u->bluez4_module_idx == PA_INVALID_INDEX) { + if (u->bluez5_module_idx == PA_INVALID_INDEX) { pa_xfree(u); return -1; } @@ -80,8 +72,5 @@ void pa__done(pa_module* m) { if (u->bluez5_module_idx != PA_INVALID_INDEX) pa_module_unload_by_index(m->core, u->bluez5_module_idx, true); - if (u->bluez4_module_idx != PA_INVALID_INDEX) - pa_module_unload_by_index(m->core, u->bluez4_module_idx, true); - pa_xfree(u); } diff --git a/src/modules/bluetooth/module-bluez4-device.c b/src/modules/bluetooth/module-bluez4-device.c deleted file mode 100644 index 79d75c11b..000000000 --- a/src/modules/bluetooth/module-bluez4-device.c +++ /dev/null @@ -1,2664 +0,0 @@ -/*** - This file is part of PulseAudio. - - Copyright 2008-2013 João Paulo Rechi Vita - Copyright 2011-2013 BMW Car IT GmbH. - - PulseAudio is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - PulseAudio is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. -***/ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <string.h> -#include <errno.h> -#include <math.h> -#include <linux/sockios.h> -#include <arpa/inet.h> - -#include <pulse/rtclock.h> -#include <pulse/sample.h> -#include <pulse/timeval.h> -#include <pulse/utf8.h> -#include <pulse/xmalloc.h> - -#include <pulsecore/i18n.h> -#include <pulsecore/module.h> -#include <pulsecore/modargs.h> -#include <pulsecore/core-rtclock.h> -#include <pulsecore/core-util.h> -#include <pulsecore/core-error.h> -#include <pulsecore/shared.h> -#include <pulsecore/socket-util.h> -#include <pulsecore/thread.h> -#include <pulsecore/thread-mq.h> -#include <pulsecore/poll.h> -#include <pulsecore/rtpoll.h> -#include <pulsecore/time-smoother.h> -#include <pulsecore/namereg.h> - -#include <sbc/sbc.h> - -#include "a2dp-codecs.h" -#include "rtp.h" -#include "bluez4-util.h" - -#define BITPOOL_DEC_LIMIT 32 -#define BITPOOL_DEC_STEP 5 - -PA_MODULE_AUTHOR("João Paulo Rechi Vita"); -PA_MODULE_DESCRIPTION("BlueZ 4 Bluetooth audio sink and source"); -PA_MODULE_VERSION(PACKAGE_VERSION); -PA_MODULE_LOAD_ONCE(false); -PA_MODULE_USAGE( - "name=<name for the card/sink/source, to be prefixed> " - "card_name=<name for the card> " - "card_properties=<properties for the card> " - "sink_name=<name for the sink> " - "sink_properties=<properties for the sink> " - "source_name=<name for the source> " - "source_properties=<properties for the source> " - "address=<address of the device> " - "profile=<a2dp|hsp|hfgw> " - "rate=<sample rate> " - "channels=<number of channels> " - "path=<device object path> " - "sco_sink=<SCO over PCM sink name> " - "sco_source=<SCO over PCM source name>"); - -/* TODO: not close fd when entering suspend mode in a2dp */ - -static const char* const valid_modargs[] = { - "name", - "card_name", - "card_properties", - "sink_name", - "sink_properties", - "source_name", - "source_properties", - "address", - "profile", - "rate", - "channels", - "path", - "sco_sink", - "sco_source", - NULL -}; - -struct a2dp_info { - sbc_t sbc; /* Codec data */ - bool sbc_initialized; /* Keep track if the encoder is initialized */ - size_t codesize, frame_length; /* SBC Codesize, frame_length. We simply cache those values here */ - - void* buffer; /* Codec transfer buffer */ - size_t buffer_size; /* Size of the buffer */ - - uint16_t seq_num; /* Cumulative packet sequence */ - uint8_t min_bitpool; - uint8_t max_bitpool; -}; - -struct hsp_info { - pa_sink *sco_sink; - void (*sco_sink_set_volume)(pa_sink *s); - pa_source *sco_source; - void (*sco_source_set_volume)(pa_source *s); -}; - -struct bluetooth_msg { - pa_msgobject parent; - pa_card *card; -}; - -typedef struct bluetooth_msg bluetooth_msg; -PA_DEFINE_PRIVATE_CLASS(bluetooth_msg, pa_msgobject); -#define BLUETOOTH_MSG(o) (bluetooth_msg_cast(o)) - -struct userdata { - pa_core *core; - pa_module *module; - - pa_bluez4_device *device; - pa_hook_slot *uuid_added_slot; - char *address; - char *path; - pa_bluez4_transport *transport; - bool transport_acquired; - pa_hook_slot *discovery_slot; - pa_hook_slot *sink_state_changed_slot; - pa_hook_slot *source_state_changed_slot; - pa_hook_slot *transport_state_changed_slot; - pa_hook_slot *transport_nrec_changed_slot; - pa_hook_slot *transport_microphone_changed_slot; - pa_hook_slot *transport_speaker_changed_slot; - - pa_bluez4_discovery *discovery; - - char *output_port_name; - char *input_port_name; - - pa_card *card; - pa_sink *sink; - pa_source *source; - - pa_thread_mq thread_mq; - pa_rtpoll *rtpoll; - pa_rtpoll_item *rtpoll_item; - pa_thread *thread; - bluetooth_msg *msg; - - uint64_t read_index, write_index; - pa_usec_t started_at; - pa_smoother *read_smoother; - - pa_memchunk write_memchunk; - - pa_sample_spec sample_spec, requested_sample_spec; - - int stream_fd; - - size_t read_link_mtu; - size_t read_block_size; - - size_t write_link_mtu; - size_t write_block_size; - - struct a2dp_info a2dp; - struct hsp_info hsp; - - pa_bluez4_profile_t profile; - - pa_modargs *modargs; - - int stream_write_type; -}; - -enum { - BLUETOOTH_MESSAGE_IO_THREAD_FAILED, - BLUETOOTH_MESSAGE_MAX -}; - -#define FIXED_LATENCY_PLAYBACK_A2DP (25*PA_USEC_PER_MSEC) -#define FIXED_LATENCY_RECORD_A2DP (25*PA_USEC_PER_MSEC) -#define FIXED_LATENCY_PLAYBACK_HSP (125*PA_USEC_PER_MSEC) -#define FIXED_LATENCY_RECORD_HSP (25*PA_USEC_PER_MSEC) - -#define MAX_PLAYBACK_CATCH_UP_USEC (100*PA_USEC_PER_MSEC) - -#define USE_SCO_OVER_PCM(u) (u->profile == PA_BLUEZ4_PROFILE_HEADSET_HEAD_UNIT && (u->hsp.sco_sink && u->hsp.sco_source)) - -static int init_profile(struct userdata *u); - -/* from IO thread */ -static void a2dp_set_bitpool(struct userdata *u, uint8_t bitpool) { - struct a2dp_info *a2dp; - - pa_assert(u); - - a2dp = &u->a2dp; - - if (a2dp->sbc.bitpool == bitpool) - return; - - if (bitpool > a2dp->max_bitpool) - bitpool = a2dp->max_bitpool; - else if (bitpool < a2dp->min_bitpool) - bitpool = a2dp->min_bitpool; - - a2dp->sbc.bitpool = bitpool; - - a2dp->codesize = sbc_get_codesize(&a2dp->sbc); - a2dp->frame_length = sbc_get_frame_length(&a2dp->sbc); - - pa_log_debug("Bitpool has changed to %u", a2dp->sbc.bitpool); - - u->read_block_size = - (u->read_link_mtu - sizeof(struct rtp_header) - sizeof(struct rtp_payload)) - / a2dp->frame_length * a2dp->codesize; - - u->write_block_size = - (u->write_link_mtu - sizeof(struct rtp_header) - sizeof(struct rtp_payload)) - / a2dp->frame_length * a2dp->codesize; - - pa_sink_set_max_request_within_thread(u->sink, u->write_block_size); - pa_sink_set_fixed_latency_within_thread(u->sink, - FIXED_LATENCY_PLAYBACK_A2DP + pa_bytes_to_usec(u->write_block_size, &u->sample_spec)); -} - -/* from IO thread, except in SCO over PCM */ -static void bt_transport_config_mtu(struct userdata *u) { - /* Calculate block sizes */ - if (u->profile == PA_BLUEZ4_PROFILE_HEADSET_HEAD_UNIT || u->profile == PA_BLUEZ4_PROFILE_HEADSET_AUDIO_GATEWAY) { - u->read_block_size = u->read_link_mtu; - u->write_block_size = u->write_link_mtu; - } else { - u->read_block_size = - (u->read_link_mtu - sizeof(struct rtp_header) - sizeof(struct rtp_payload)) - / u->a2dp.frame_length * u->a2dp.codesize; - - u->write_block_size = - (u->write_link_mtu - sizeof(struct rtp_header) - sizeof(struct rtp_payload)) - / u->a2dp.frame_length * u->a2dp.codesize; - } - - if (USE_SCO_OVER_PCM(u)) - return; - - if (u->sink) { - pa_sink_set_max_request_within_thread(u->sink, u->write_block_size); - pa_sink_set_fixed_latency_within_thread(u->sink, - (u->profile == PA_BLUEZ4_PROFILE_A2DP_SINK ? - FIXED_LATENCY_PLAYBACK_A2DP : FIXED_LATENCY_PLAYBACK_HSP) + - pa_bytes_to_usec(u->write_block_size, &u->sample_spec)); - } - - if (u->source) - pa_source_set_fixed_latency_within_thread(u->source, - (u->profile == PA_BLUEZ4_PROFILE_A2DP_SOURCE ? - FIXED_LATENCY_RECORD_A2DP : FIXED_LATENCY_RECORD_HSP) + - pa_bytes_to_usec(u->read_block_size, &u->sample_spec)); -} - -/* from IO thread, except in SCO over PCM */ - -static void setup_stream(struct userdata *u) { - struct pollfd *pollfd; - int one; - - pa_log_info("Transport %s resuming", u->transport->path); - - bt_transport_config_mtu(u); - - pa_make_fd_nonblock(u->stream_fd); - pa_make_socket_low_delay(u->stream_fd); - - one = 1; - if (setsockopt(u->stream_fd, SOL_SOCKET, SO_TIMESTAMP, &one, sizeof(one)) < 0) - pa_log_warn("Failed to enable SO_TIMESTAMP: %s", pa_cstrerror(errno)); - - pa_log_debug("Stream properly set up, we're ready to roll!"); - - if (u->profile == PA_BLUEZ4_PROFILE_A2DP_SINK) - a2dp_set_bitpool(u, u->a2dp.max_bitpool); - - u->rtpoll_item = pa_rtpoll_item_new(u->rtpoll, PA_RTPOLL_NEVER, 1); - pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL); - pollfd->fd = u->stream_fd; - pollfd->events = pollfd->revents = 0; - - u->read_index = u->write_index = 0; - u->started_at = 0; - - if (u->source) - u->read_smoother = pa_smoother_new( - PA_USEC_PER_SEC, - PA_USEC_PER_SEC*2, - true, - true, - 10, - pa_rtclock_now(), - true); -} - -static void teardown_stream(struct userdata *u) { - if (u->rtpoll_item) { - pa_rtpoll_item_free(u->rtpoll_item); - u->rtpoll_item = NULL; - } - - if (u->stream_fd >= 0) { - pa_close(u->stream_fd); - u->stream_fd = -1; - } - - if (u->read_smoother) { - pa_smoother_free(u->read_smoother); - u->read_smoother = NULL; - } - - if (u->write_memchunk.memblock) { - pa_memblock_unref(u->write_memchunk.memblock); - pa_memchunk_reset(&u->write_memchunk); - } - - pa_log_debug("Audio stream torn down"); -} - -static void bt_transport_release(struct userdata *u) { - pa_assert(u->transport); - - /* Ignore if already released */ - if (!u->transport_acquired) - return; - - pa_log_debug("Releasing transport %s", u->transport->path); - - pa_bluez4_transport_release(u->transport); - - u->transport_acquired = false; - - teardown_stream(u); -} - -static int bt_transport_acquire(struct userdata *u, bool optional) { - pa_assert(u->transport); - - if (u->transport_acquired) - return 0; - - pa_log_debug("Acquiring transport %s", u->transport->path); - - u->stream_fd = pa_bluez4_transport_acquire(u->transport, optional, &u->read_link_mtu, &u->write_link_mtu); - if (u->stream_fd < 0) { - if (!optional) - pa_log("Failed to acquire transport %s", u->transport->path); - else - pa_log_info("Failed optional acquire of transport %s", u->transport->path); - - return -1; - } - - u->transport_acquired = true; - pa_log_info("Transport %s acquired: fd %d", u->transport->path, u->stream_fd); - - return 0; -} - -/* Run from IO thread */ -static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) { - struct userdata *u = PA_SINK(o)->userdata; - - pa_assert(u->sink == PA_SINK(o)); - pa_assert(u->transport); - - switch (code) { - - case PA_SINK_MESSAGE_GET_LATENCY: { - - if (u->read_smoother) { - int64_t wi, ri; - - ri = pa_smoother_get(u->read_smoother, pa_rtclock_now()); - wi = pa_bytes_to_usec(u->write_index + u->write_block_size, &u->sample_spec); - - *((int64_t*) data) = wi - ri; - } else { - int64_t ri, wi; - - ri = pa_rtclock_now() - u->started_at; - wi = pa_bytes_to_usec(u->write_index, &u->sample_spec); - - *((int64_t*) data) = wi - ri; - } - - *((int64_t*) data) += u->sink->thread_info.fixed_latency; - return 0; - } - } - - return pa_sink_process_msg(o, code, data, offset, chunk); -} - -/* Called from the IO thread. */ -static int sink_set_state_in_io_thread_cb(pa_sink *s, pa_sink_state_t new_state, pa_suspend_cause_t new_suspend_cause) { - struct userdata *u; - - pa_assert(s); - pa_assert_se(u = s->userdata); - - switch (new_state) { - - case PA_SINK_SUSPENDED: - /* Ignore if transition is PA_SINK_INIT->PA_SINK_SUSPENDED */ - if (!PA_SINK_IS_OPENED(u->sink->thread_info.state)) - break; - - /* Stop the device if the source is suspended as well */ - if (!u->source || u->source->state == PA_SOURCE_SUSPENDED) - /* We deliberately ignore whether stopping - * actually worked. Since the stream_fd is - * closed it doesn't really matter */ - bt_transport_release(u); - - break; - - case PA_SINK_IDLE: - case PA_SINK_RUNNING: - if (u->sink->thread_info.state != PA_SINK_SUSPENDED) - break; - - /* Resume the device if the source was suspended as well */ - if (!u->source || !PA_SOURCE_IS_OPENED(u->source->thread_info.state)) { - if (bt_transport_acquire(u, false) < 0) - return -1; - else - setup_stream(u); - } - break; - - case PA_SINK_UNLINKED: - case PA_SINK_INIT: - case PA_SINK_INVALID_STATE: - break; - } - - return 0; -} - -/* Run from IO thread */ -static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) { - struct userdata *u = PA_SOURCE(o)->userdata; - - pa_assert(u->source == PA_SOURCE(o)); - pa_assert(u->transport); - - switch (code) { - - case PA_SOURCE_MESSAGE_GET_LATENCY: { - int64_t wi, ri; - - if (u->read_smoother) { - wi = pa_smoother_get(u->read_smoother, pa_rtclock_now()); - ri = pa_bytes_to_usec(u->read_index, &u->sample_spec); - - *((int64_t*) data) = wi - ri + u->source->thread_info.fixed_latency; - } else - *((int64_t*) data) = 0; - - return 0; - } - - } - - return pa_source_process_msg(o, code, data, offset, chunk); -} - -/* Called from the IO thread. */ -static int source_set_state_in_io_thread_cb(pa_source *s, pa_source_state_t new_state, pa_suspend_cause_t new_suspend_cause) { - struct userdata *u; - - pa_assert(s); - pa_assert_se(u = s->userdata); - - switch (new_state) { - - case PA_SOURCE_SUSPENDED: - /* Ignore if transition is PA_SOURCE_INIT->PA_SOURCE_SUSPENDED */ - if (!PA_SOURCE_IS_OPENED(u->source->thread_info.state)) - break; - - /* Stop the device if the sink is suspended as well */ - if (!u->sink || u->sink->state == PA_SINK_SUSPENDED) - bt_transport_release(u); - - if (u->read_smoother) - pa_smoother_pause(u->read_smoother, pa_rtclock_now()); - break; - - case PA_SOURCE_IDLE: - case PA_SOURCE_RUNNING: - if (u->source->thread_info.state != PA_SOURCE_SUSPENDED) - break; - - /* Resume the device if the sink was suspended as well */ - if (!u->sink || !PA_SINK_IS_OPENED(u->sink->thread_info.state)) { - if (bt_transport_acquire(u, false) < 0) - return -1; - else - setup_stream(u); - } - /* We don't resume the smoother here. Instead we - * wait until the first packet arrives */ - break; - - case PA_SOURCE_UNLINKED: - case PA_SOURCE_INIT: - case PA_SOURCE_INVALID_STATE: - break; - } - - return 0; -} - -/* Called from main thread context */ -static int device_process_msg(pa_msgobject *obj, int code, void *data, int64_t offset, pa_memchunk *chunk) { - struct bluetooth_msg *u = BLUETOOTH_MSG(obj); - - switch (code) { - case BLUETOOTH_MESSAGE_IO_THREAD_FAILED: { - if (u->card->module->unload_requested) - break; - - pa_log_debug("Switching the profile to off due to IO thread failure."); - - pa_assert_se(pa_card_set_profile(u->card, pa_hashmap_get(u->card->profiles, "off"), false) >= 0); - break; - } - } - return 0; -} - -/* Run from IO thread */ -static int hsp_process_render(struct userdata *u) { - int ret = 0; - - pa_assert(u); - pa_assert(u->profile == PA_BLUEZ4_PROFILE_HEADSET_HEAD_UNIT || u->profile == PA_BLUEZ4_PROFILE_HEADSET_AUDIO_GATEWAY); - pa_assert(u->sink); - - /* First, render some data */ - if (!u->write_memchunk.memblock) - pa_sink_render_full(u->sink, u->write_block_size, &u->write_memchunk); - - pa_assert(u->write_memchunk.length == u->write_block_size); - - for (;;) { - ssize_t l; - const void *p; - - /* Now write that data to the socket. The socket is of type - * SEQPACKET, and we generated the data of the MTU size, so this - * should just work. */ - - p = (const uint8_t *) pa_memblock_acquire_chunk(&u->write_memchunk); - l = pa_write(u->stream_fd, p, u->write_memchunk.length, &u->stream_write_type); - pa_memblock_release(u->write_memchunk.memblock); - - pa_assert(l != 0); - - if (l < 0) { - - if (errno == EINTR) - /* Retry right away if we got interrupted */ - continue; - - else if (errno == EAGAIN) - /* Hmm, apparently the socket was not writable, give up for now */ - break; - - pa_log_error("Failed to write data to SCO socket: %s", pa_cstrerror(errno)); - ret = -1; - break; - } - - pa_assert((size_t) l <= u->write_memchunk.length); - - if ((size_t) l != u->write_memchunk.length) { - pa_log_error("Wrote memory block to socket only partially! %llu written, wanted to write %llu.", - (unsigned long long) l, - (unsigned long long) u->write_memchunk.length); - ret = -1; - break; - } - - u->write_index += (uint64_t) u->write_memchunk.length; - pa_memblock_unref(u->write_memchunk.memblock); - pa_memchunk_reset(&u->write_memchunk); - - ret = 1; - break; - } - - return ret; -} - -/* Run from IO thread */ -static int hsp_process_push(struct userdata *u) { - int ret = 0; - pa_memchunk memchunk; - - pa_assert(u); - pa_assert(u->profile == PA_BLUEZ4_PROFILE_HEADSET_HEAD_UNIT || u->profile == PA_BLUEZ4_PROFILE_HEADSET_AUDIO_GATEWAY); - pa_assert(u->source); - pa_assert(u->read_smoother); - - memchunk.memblock = pa_memblock_new(u->core->mempool, u->read_block_size); - memchunk.index = memchunk.length = 0; - - for (;;) { - ssize_t l; - void *p; - struct msghdr m; - struct cmsghdr *cm; - uint8_t aux[1024]; - struct iovec iov; - bool found_tstamp = false; - pa_usec_t tstamp; - - memset(&m, 0, sizeof(m)); - memset(&aux, 0, sizeof(aux)); - memset(&iov, 0, sizeof(iov)); - - m.msg_iov = &iov; - m.msg_iovlen = 1; - m.msg_control = aux; - m.msg_controllen = sizeof(aux); - - p = pa_memblock_acquire(memchunk.memblock); - iov.iov_base = p; - iov.iov_len = pa_memblock_get_length(memchunk.memblock); - l = recvmsg(u->stream_fd, &m, 0); - pa_memblock_release(memchunk.memblock); - - if (l <= 0) { - - if (l < 0 && errno == EINTR) - /* Retry right away if we got interrupted */ - continue; - - else if (l < 0 && errno == EAGAIN) - /* Hmm, apparently the socket was not readable, give up for now. */ - break; - - pa_log_error("Failed to read data from SCO socket: %s", l < 0 ? pa_cstrerror(errno) : "EOF"); - ret = -1; - break; - } - - pa_assert((size_t) l <= pa_memblock_get_length(memchunk.memblock)); - - /* In some rare occasions, we might receive packets of a very strange - * size. This could potentially be possible if the SCO packet was - * received partially over-the-air, or more probably due to hardware - * issues in our Bluetooth adapter. In these cases, in order to avoid - * an assertion failure due to unaligned data, just discard the whole - * packet */ - if (!pa_frame_aligned(l, &u->sample_spec)) { - pa_log_warn("SCO packet received of unaligned size: %zu", l); - break; - } - - memchunk.length = (size_t) l; - u->read_index += (uint64_t) l; - - for (cm = CMSG_FIRSTHDR(&m); cm; cm = CMSG_NXTHDR(&m, cm)) - if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SO_TIMESTAMP) { - struct timeval *tv = (struct timeval*) CMSG_DATA(cm); - pa_rtclock_from_wallclock(tv); - tstamp = pa_timeval_load(tv); - found_tstamp = true; - break; - } - - if (!found_tstamp) { - pa_log_warn("Couldn't find SO_TIMESTAMP data in auxiliary recvmsg() data!"); - tstamp = pa_rtclock_now(); - } - - pa_smoother_put(u->read_smoother, tstamp, pa_bytes_to_usec(u->read_index, &u->sample_spec)); - pa_smoother_resume(u->read_smoother, tstamp, true); - - pa_source_post(u->source, &memchunk); - - ret = l; - break; - } - - pa_memblock_unref(memchunk.memblock); - - return ret; -} - -/* Run from IO thread */ -static void a2dp_prepare_buffer(struct userdata *u) { - size_t min_buffer_size = PA_MAX(u->read_link_mtu, u->write_link_mtu); - - pa_assert(u); - - if (u->a2dp.buffer_size >= min_buffer_size) - return; - - u->a2dp.buffer_size = 2 * min_buffer_size; - pa_xfree(u->a2dp.buffer); - u->a2dp.buffer = pa_xmalloc(u->a2dp.buffer_size); -} - -/* Run from IO thread */ -static int a2dp_process_render(struct userdata *u) { - struct a2dp_info *a2dp; - struct rtp_header *header; - struct rtp_payload *payload; - size_t nbytes; - void *d; - const void *p; - size_t to_write, to_encode; - unsigned frame_count; - int ret = 0; - - pa_assert(u); - pa_assert(u->profile == PA_BLUEZ4_PROFILE_A2DP_SINK); - pa_assert(u->sink); - - /* First, render some data */ - if (!u->write_memchunk.memblock) - pa_sink_render_full(u->sink, u->write_block_size, &u->write_memchunk); - - pa_assert(u->write_memchunk.length == u->write_block_size); - - a2dp_prepare_buffer(u); - - a2dp = &u->a2dp; - header = a2dp->buffer; - payload = (struct rtp_payload*) ((uint8_t*) a2dp->buffer + sizeof(*header)); - - frame_count = 0; - - /* Try to create a packet of the full MTU */ - - p = (const uint8_t *) pa_memblock_acquire_chunk(&u->write_memchunk); - to_encode = u->write_memchunk.length; - - d = (uint8_t*) a2dp->buffer + sizeof(*header) + sizeof(*payload); - to_write = a2dp->buffer_size - sizeof(*header) - sizeof(*payload); - - while (PA_LIKELY(to_encode > 0 && to_write > 0)) { - ssize_t written; - ssize_t encoded; - - encoded = sbc_encode(&a2dp->sbc, - p, to_encode, - d, to_write, - &written); - - if (PA_UNLIKELY(encoded <= 0)) { - pa_log_error("SBC encoding error (%li)", (long) encoded); - pa_memblock_release(u->write_memchunk.memblock); - return -1; - } - -/* pa_log_debug("SBC: encoded: %lu; written: %lu", (unsigned long) encoded, (unsigned long) written); */ -/* pa_log_debug("SBC: codesize: %lu; frame_length: %lu", (unsigned long) a2dp->codesize, (unsigned long) a2dp->frame_length); */ - - pa_assert_fp((size_t) encoded <= to_encode); - pa_assert_fp((size_t) encoded == a2dp->codesize); - - pa_assert_fp((size_t) written <= to_write); - pa_assert_fp((size_t) written == a2dp->frame_length); - - p = (const uint8_t*) p + encoded; - to_encode -= encoded; - - d = (uint8_t*) d + written; - to_write -= written; - - frame_count++; - } - - pa_memblock_release(u->write_memchunk.memblock); - - pa_assert(to_encode == 0); - - PA_ONCE_BEGIN { - pa_log_debug("Using SBC encoder implementation: %s", pa_strnull(sbc_get_implementation_info(&a2dp->sbc))); - } PA_ONCE_END; - - /* write it to the fifo */ - memset(a2dp->buffer, 0, sizeof(*header) + sizeof(*payload)); - header->v = 2; - header->pt = 1; - header->sequence_number = htons(a2dp->seq_num++); - header->timestamp = htonl(u->write_index / pa_frame_size(&u->sample_spec)); - header->ssrc = htonl(1); - payload->frame_count = frame_count; - - nbytes = (uint8_t*) d - (uint8_t*) a2dp->buffer; - - for (;;) { - ssize_t l; - - l = pa_write(u->stream_fd, a2dp->buffer, nbytes, &u->stream_write_type); - - pa_assert(l != 0); - - if (l < 0) { - - if (errno == EINTR) - /* Retry right away if we got interrupted */ - continue; - - else if (errno == EAGAIN) - /* Hmm, apparently the socket was not writable, give up for now */ - break; - - pa_log_error("Failed to write data to socket: %s", pa_cstrerror(errno)); - ret = -1; - break; - } - - pa_assert((size_t) l <= nbytes); - - if ((size_t) l != nbytes) { - pa_log_warn("Wrote memory block to socket only partially! %llu written, wanted to write %llu.", - (unsigned long long) l, - (unsigned long long) nbytes); - ret = -1; - break; - } - - u->write_index += (uint64_t) u->write_memchunk.length; - pa_memblock_unref(u->write_memchunk.memblock); - pa_memchunk_reset(&u->write_memchunk); - - ret = 1; - - break; - } - - return ret; -} - -static int a2dp_process_push(struct userdata *u) { - int ret = 0; - pa_memchunk memchunk; - - pa_assert(u); - pa_assert(u->profile == PA_BLUEZ4_PROFILE_A2DP_SOURCE); - pa_assert(u->source); - pa_assert(u->read_smoother); - - memchunk.memblock = pa_memblock_new(u->core->mempool, u->read_block_size); - memchunk.index = memchunk.length = 0; - - for (;;) { - bool found_tstamp = false; - pa_usec_t tstamp; - struct a2dp_info *a2dp; - struct rtp_header *header; - struct rtp_payload *payload; - const void *p; - void *d; - ssize_t l; - size_t to_write, to_decode; - size_t total_written = 0; - - a2dp_prepare_buffer(u); - - a2dp = &u->a2dp; - header = a2dp->buffer; - payload = (struct rtp_payload*) ((uint8_t*) a2dp->buffer + sizeof(*header)); - - l = pa_read(u->stream_fd, a2dp->buffer, a2dp->buffer_size, &u->stream_write_type); - - if (l <= 0) { - - if (l < 0 && errno == EINTR) - /* Retry right away if we got interrupted */ - continue; - - else if (l < 0 && errno == EAGAIN) - /* Hmm, apparently the socket was not readable, give up for now. */ - break; - - pa_log_error("Failed to read data from socket: %s", l < 0 ? pa_cstrerror(errno) : "EOF"); - ret = -1; - break; - } - - pa_assert((size_t) l <= a2dp->buffer_size); - - /* TODO: get timestamp from rtp */ - if (!found_tstamp) { - /* pa_log_warn("Couldn't find SO_TIMESTAMP data in auxiliary recvmsg() data!"); */ - tstamp = pa_rtclock_now(); - } - - p = (uint8_t*) a2dp->buffer + sizeof(*header) + sizeof(*payload); - to_decode = l - sizeof(*header) - sizeof(*payload); - - d = pa_memblock_acquire(memchunk.memblock); - to_write = memchunk.length = pa_memblock_get_length(memchunk.memblock); - - while (PA_LIKELY(to_decode > 0)) { - size_t written; - ssize_t decoded; - - decoded = sbc_decode(&a2dp->sbc, - p, to_decode, - d, to_write, - &written); - - if (PA_UNLIKELY(decoded <= 0)) { - pa_log_error("SBC decoding error (%li)", (long) decoded); - pa_memblock_release(memchunk.memblock); - pa_memblock_unref(memchunk.memblock); - return 0; - } - -/* pa_log_debug("SBC: decoded: %lu; written: %lu", (unsigned long) decoded, (unsigned long) written); */ -/* pa_log_debug("SBC: frame_length: %lu; codesize: %lu", (unsigned long) a2dp->frame_length, (unsigned long) a2dp->codesize); */ - - total_written += written; - - /* Reset frame length, it can be changed due to bitpool change */ - a2dp->frame_length = sbc_get_frame_length(&a2dp->sbc); - - pa_assert_fp((size_t) decoded <= to_decode); - pa_assert_fp((size_t) decoded == a2dp->frame_length); - - pa_assert_fp((size_t) written == a2dp->codesize); - - p = (const uint8_t*) p + decoded; - to_decode -= decoded; - - d = (uint8_t*) d + written; - to_write -= written; - } - - u->read_index += (uint64_t) total_written; - pa_smoother_put(u->read_smoother, tstamp, pa_bytes_to_usec(u->read_index, &u->sample_spec)); - pa_smoother_resume(u->read_smoother, tstamp, true); - - memchunk.length -= to_write; - - pa_memblock_release(memchunk.memblock); - - pa_source_post(u->source, &memchunk); - - ret = l; - break; - } - - pa_memblock_unref(memchunk.memblock); - - return ret; -} - -static void a2dp_reduce_bitpool(struct userdata *u) { - struct a2dp_info *a2dp; - uint8_t bitpool; - - pa_assert(u); - - a2dp = &u->a2dp; - - /* Check if bitpool is already at its limit */ - if (a2dp->sbc.bitpool <= BITPOOL_DEC_LIMIT) - return; - - bitpool = a2dp->sbc.bitpool - BITPOOL_DEC_STEP; - - if (bitpool < BITPOOL_DEC_LIMIT) - bitpool = BITPOOL_DEC_LIMIT; - - a2dp_set_bitpool(u, bitpool); -} - -static void thread_func(void *userdata) { - struct userdata *u = userdata; - unsigned do_write = 0; - unsigned pending_read_bytes = 0; - bool writable = false; - - pa_assert(u); - pa_assert(u->transport); - - pa_log_debug("IO Thread starting up"); - - if (u->core->realtime_scheduling) - pa_make_realtime(u->core->realtime_priority); - - pa_thread_mq_install(&u->thread_mq); - - /* Setup the stream only if the transport was already acquired */ - if (u->transport_acquired) - setup_stream(u); - - for (;;) { - struct pollfd *pollfd; - int ret; - bool disable_timer = true; - - pollfd = u->rtpoll_item ? pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL) : NULL; - - if (u->source && PA_SOURCE_IS_LINKED(u->source->thread_info.state)) { - - /* We should send two blocks to the device before we expect - * a response. */ - - if (u->write_index == 0 && u->read_index <= 0) - do_write = 2; - - if (pollfd && (pollfd->revents & POLLIN)) { - int n_read; - - if (u->profile == PA_BLUEZ4_PROFILE_HEADSET_HEAD_UNIT || u->profile == PA_BLUEZ4_PROFILE_HEADSET_AUDIO_GATEWAY) - n_read = hsp_process_push(u); - else - n_read = a2dp_process_push(u); - - if (n_read < 0) - goto io_fail; - - if (n_read > 0) { - /* We just read something, so we are supposed to write something, too */ - pending_read_bytes += n_read; - do_write += pending_read_bytes / u->write_block_size; - pending_read_bytes = pending_read_bytes % u->write_block_size; - } - } - } - - if (u->sink && PA_SINK_IS_LINKED(u->sink->thread_info.state)) { - - if (PA_UNLIKELY(u->sink->thread_info.rewind_requested)) - pa_sink_process_rewind(u->sink, 0); - - if (pollfd) { - if (pollfd->revents & POLLOUT) - writable = true; - - if ((!u->source || !PA_SOURCE_IS_LINKED(u->source->thread_info.state)) && do_write <= 0 && writable) { - pa_usec_t time_passed; - pa_usec_t audio_sent; - - /* Hmm, there is no input stream we could synchronize - * to. So let's do things by time */ - - time_passed = pa_rtclock_now() - u->started_at; - audio_sent = pa_bytes_to_usec(u->write_index, &u->sample_spec); - - if (audio_sent <= time_passed) { - pa_usec_t audio_to_send = time_passed - audio_sent; - - /* Never try to catch up for more than 100ms */ - if (u->write_index > 0 && audio_to_send > MAX_PLAYBACK_CATCH_UP_USEC) { - pa_usec_t skip_usec; - uint64_t skip_bytes; - - skip_usec = audio_to_send - MAX_PLAYBACK_CATCH_UP_USEC; - skip_bytes = pa_usec_to_bytes(skip_usec, &u->sample_spec); - - if (skip_bytes > 0) { - pa_memchunk tmp; - - pa_log_warn("Skipping %llu us (= %llu bytes) in audio stream", - (unsigned long long) skip_usec, - (unsigned long long) skip_bytes); - - pa_sink_render_full(u->sink, skip_bytes, &tmp); - pa_memblock_unref(tmp.memblock); - u->write_index += skip_bytes; - - if (u->profile == PA_BLUEZ4_PROFILE_A2DP_SINK) - a2dp_reduce_bitpool(u); - } - } - - do_write = 1; - pending_read_bytes = 0; - } - } - - if (writable && do_write > 0) { - int n_written; - - if (u->write_index <= 0) - u->started_at = pa_rtclock_now(); - - if (u->profile == PA_BLUEZ4_PROFILE_A2DP_SINK) { - if ((n_written = a2dp_process_render(u)) < 0) - goto io_fail; - } else { - if ((n_written = hsp_process_render(u)) < 0) - goto io_fail; - } - - if (n_written == 0) - pa_log("Broken kernel: we got EAGAIN on write() after POLLOUT!"); - - do_write -= n_written; - writable = false; - } - - if ((!u->source || !PA_SOURCE_IS_LINKED(u->source->thread_info.state)) && do_write <= 0) { - pa_usec_t sleep_for; - pa_usec_t time_passed, next_write_at; - - if (writable) { - /* Hmm, there is no input stream we could synchronize - * to. So let's estimate when we need to wake up the latest */ - time_passed = pa_rtclock_now() - u->started_at; - next_write_at = pa_bytes_to_usec(u->write_index, &u->sample_spec); - sleep_for = time_passed < next_write_at ? next_write_at - time_passed : 0; - /* pa_log("Sleeping for %lu; time passed %lu, next write at %lu", (unsigned long) sleep_for, (unsigned long) time_passed, (unsigned long)next_write_at); */ - } else - /* drop stream every 500 ms */ - sleep_for = PA_USEC_PER_MSEC * 500; - - pa_rtpoll_set_timer_relative(u->rtpoll, sleep_for); - disable_timer = false; - } - } - } - - if (disable_timer) - pa_rtpoll_set_timer_disabled(u->rtpoll); - - /* Hmm, nothing to do. Let's sleep */ - if (pollfd) - pollfd->events = (short) (((u->sink && PA_SINK_IS_LINKED(u->sink->thread_info.state) && !writable) ? POLLOUT : 0) | - (u->source && PA_SOURCE_IS_LINKED(u->source->thread_info.state) ? POLLIN : 0)); - - if ((ret = pa_rtpoll_run(u->rtpoll)) < 0) { - pa_log_debug("pa_rtpoll_run failed with: %d", ret); - goto fail; - } - if (ret == 0) { - pa_log_debug("IO thread shutdown requested, stopping cleanly"); - bt_transport_release(u); - goto finish; - } - - pollfd = u->rtpoll_item ? pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL) : NULL; - - if (pollfd && (pollfd->revents & ~(POLLOUT|POLLIN))) { - pa_log_info("FD error: %s%s%s%s", - pollfd->revents & POLLERR ? "POLLERR " :"", - pollfd->revents & POLLHUP ? "POLLHUP " :"", - pollfd->revents & POLLPRI ? "POLLPRI " :"", - pollfd->revents & POLLNVAL ? "POLLNVAL " :""); - goto io_fail; - } - - continue; - -io_fail: - /* In case of HUP, just tear down the streams */ - if (!pollfd || (pollfd->revents & POLLHUP) == 0) - goto fail; - - do_write = 0; - pending_read_bytes = 0; - writable = false; - - teardown_stream(u); - } - -fail: - /* If this was no regular exit from the loop we have to continue processing messages until we receive PA_MESSAGE_SHUTDOWN */ - pa_log_debug("IO thread failed"); - pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(u->msg), BLUETOOTH_MESSAGE_IO_THREAD_FAILED, NULL, 0, NULL, NULL); - pa_asyncmsgq_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN); - -finish: - pa_log_debug("IO thread shutting down"); -} - -static pa_available_t transport_state_to_availability(pa_bluez4_transport_state_t state) { - if (state == PA_BLUEZ4_TRANSPORT_STATE_DISCONNECTED) - return PA_AVAILABLE_NO; - else if (state >= PA_BLUEZ4_TRANSPORT_STATE_PLAYING) - return PA_AVAILABLE_YES; - else - return PA_AVAILABLE_UNKNOWN; -} - -static pa_direction_t get_profile_direction(pa_bluez4_profile_t p) { - static const pa_direction_t profile_direction[] = { - [PA_BLUEZ4_PROFILE_A2DP_SINK] = PA_DIRECTION_OUTPUT, - [PA_BLUEZ4_PROFILE_A2DP_SOURCE] = PA_DIRECTION_INPUT, - [PA_BLUEZ4_PROFILE_HEADSET_HEAD_UNIT] = PA_DIRECTION_INPUT | PA_DIRECTION_OUTPUT, - [PA_BLUEZ4_PROFILE_HEADSET_AUDIO_GATEWAY] = PA_DIRECTION_INPUT | PA_DIRECTION_OUTPUT, - [PA_BLUEZ4_PROFILE_OFF] = 0 - }; - - return profile_direction[p]; -} - -/* Run from main thread */ -static pa_available_t get_port_availability(struct userdata *u, pa_direction_t direction) { - pa_available_t result = PA_AVAILABLE_NO; - unsigned i; - - pa_assert(u); - pa_assert(u->device); - - for (i = 0; i < PA_BLUEZ4_PROFILE_COUNT; i++) { - pa_bluez4_transport *transport; - - if (!(get_profile_direction(i) & direction)) - continue; - - if (!(transport = u->device->transports[i])) - continue; - - switch(transport->state) { - case PA_BLUEZ4_TRANSPORT_STATE_DISCONNECTED: - continue; - - case PA_BLUEZ4_TRANSPORT_STATE_IDLE: - if (result == PA_AVAILABLE_NO) - result = PA_AVAILABLE_UNKNOWN; - - break; - - case PA_BLUEZ4_TRANSPORT_STATE_PLAYING: - return PA_AVAILABLE_YES; - } - } - - return result; -} - -/* Run from main thread */ -static void handle_transport_state_change(struct userdata *u, struct pa_bluez4_transport *transport) { - bool acquire = false; - bool release = false; - pa_bluez4_profile_t profile; - pa_card_profile *cp; - pa_bluez4_transport_state_t state; - pa_device_port *port; - - pa_assert(u); - pa_assert(transport); - - profile = transport->profile; - state = transport->state; - - /* Update profile availability */ - if (!(cp = pa_hashmap_get(u->card->profiles, pa_bluez4_profile_to_string(profile)))) - return; - - pa_card_profile_set_available(cp, transport_state_to_availability(state)); - - /* Update port availability */ - pa_assert_se(port = pa_hashmap_get(u->card->ports, u->output_port_name)); - pa_device_port_set_available(port, get_port_availability(u, PA_DIRECTION_OUTPUT)); - - pa_assert_se(port = pa_hashmap_get(u->card->ports, u->input_port_name)); - pa_device_port_set_available(port, get_port_availability(u, PA_DIRECTION_INPUT)); - - /* Acquire or release transport as needed */ - acquire = (state == PA_BLUEZ4_TRANSPORT_STATE_PLAYING && u->profile == profile); - release = (state != PA_BLUEZ4_TRANSPORT_STATE_PLAYING && u->profile == profile); - - if (acquire) - if (bt_transport_acquire(u, true) >= 0) { - if (u->source) { - pa_log_debug("Resuming source %s, because the bluetooth audio state changed to 'playing'.", u->source->name); - pa_source_suspend(u->source, false, PA_SUSPEND_IDLE|PA_SUSPEND_USER); - } - - if (u->sink) { - pa_log_debug("Resuming sink %s, because the bluetooth audio state changed to 'playing'.", u->sink->name); - pa_sink_suspend(u->sink, false, PA_SUSPEND_IDLE|PA_SUSPEND_USER); - } - } - - if (release && u->transport_acquired) { - /* FIXME: this release is racy, since the audio stream might have - been set up again in the meantime (but not processed yet by PA). - BlueZ should probably release the transport automatically, and - in that case we would just mark the transport as released */ - - /* Remote side closed the stream so we consider it PA_SUSPEND_USER */ - if (u->source) { - pa_log_debug("Suspending source %s, because the remote end closed the stream.", u->source->name); - pa_source_suspend(u->source, true, PA_SUSPEND_USER); - } - - if (u->sink) { - pa_log_debug("Suspending sink %s, because the remote end closed the stream.", u->sink->name); - pa_sink_suspend(u->sink, true, PA_SUSPEND_USER); - } - } -} - -/* Run from main thread */ -static void sink_set_volume_cb(pa_sink *s) { - uint16_t gain; - pa_volume_t volume; - struct userdata *u; - char *k; - - pa_assert(s); - pa_assert(s->core); - - k = pa_sprintf_malloc("bluetooth-device@%p", (void*) s); - u = pa_shared_get(s->core, k); - pa_xfree(k); - - pa_assert(u); - pa_assert(u->sink == s); - pa_assert(u->profile == PA_BLUEZ4_PROFILE_HEADSET_HEAD_UNIT); - pa_assert(u->transport); - - gain = (dbus_uint16_t) round((double) pa_cvolume_max(&s->real_volume) * HSP_MAX_GAIN / PA_VOLUME_NORM); - volume = (pa_volume_t) round((double) gain * PA_VOLUME_NORM / HSP_MAX_GAIN); - - pa_cvolume_set(&s->real_volume, u->sample_spec.channels, volume); - - pa_bluez4_transport_set_speaker_gain(u->transport, gain); -} - -/* Run from main thread */ -static void source_set_volume_cb(pa_source *s) { - uint16_t gain; - pa_volume_t volume; - struct userdata *u; - char *k; - - pa_assert(s); - pa_assert(s->core); - - k = pa_sprintf_malloc("bluetooth-device@%p", (void*) s); - u = pa_shared_get(s->core, k); - pa_xfree(k); - - pa_assert(u); - pa_assert(u->source == s); - pa_assert(u->profile == PA_BLUEZ4_PROFILE_HEADSET_HEAD_UNIT); - pa_assert(u->transport); - - gain = (dbus_uint16_t) round((double) pa_cvolume_max(&s->real_volume) * HSP_MAX_GAIN / PA_VOLUME_NORM); - volume = (pa_volume_t) round((double) gain * PA_VOLUME_NORM / HSP_MAX_GAIN); - - pa_cvolume_set(&s->real_volume, u->sample_spec.channels, volume); - - pa_bluez4_transport_set_microphone_gain(u->transport, gain); -} - -/* Run from main thread */ -static char *get_name(const char *type, pa_modargs *ma, const char *device_id, const char *profile, bool *namereg_fail) { - char *t; - const char *n; - - pa_assert(type); - pa_assert(ma); - pa_assert(device_id); - pa_assert(namereg_fail); - - t = pa_sprintf_malloc("%s_name", type); - n = pa_modargs_get_value(ma, t, NULL); - pa_xfree(t); - - if (n) { - *namereg_fail = true; - return pa_xstrdup(n); - } - - if ((n = pa_modargs_get_value(ma, "name", NULL))) - *namereg_fail = true; - else { - n = device_id; - *namereg_fail = false; - } - - if (profile) - return pa_sprintf_malloc("bluez_%s.%s.%s", type, n, profile); - else - return pa_sprintf_malloc("bluez_%s.%s", type, n); -} - -static int sco_over_pcm_state_update(struct userdata *u, bool changed) { - pa_assert(u); - pa_assert(USE_SCO_OVER_PCM(u)); - - if (PA_SINK_IS_OPENED(pa_sink_get_state(u->hsp.sco_sink)) || - PA_SOURCE_IS_OPENED(pa_source_get_state(u->hsp.sco_source))) { - - if (u->stream_fd >= 0) - return 0; - - pa_log_debug("Resuming SCO over PCM"); - if (init_profile(u) < 0) { - pa_log("Can't resume SCO over PCM"); - return -1; - } - - if (bt_transport_acquire(u, false) < 0) - return -1; - - setup_stream(u); - - return 0; - } - - if (changed) { - if (u->stream_fd < 0) - return 0; - - pa_log_debug("Closing SCO over PCM"); - - bt_transport_release(u); - } - - return 0; -} - -static pa_hook_result_t sink_state_changed_cb(pa_core *c, pa_sink *s, struct userdata *u) { - pa_assert(c); - pa_sink_assert_ref(s); - pa_assert(u); - - if (!USE_SCO_OVER_PCM(u) || s != u->hsp.sco_sink) - return PA_HOOK_OK; - - sco_over_pcm_state_update(u, true); - - return PA_HOOK_OK; -} - -static pa_hook_result_t source_state_changed_cb(pa_core *c, pa_source *s, struct userdata *u) { - pa_assert(c); - pa_source_assert_ref(s); - pa_assert(u); - - if (!USE_SCO_OVER_PCM(u) || s != u->hsp.sco_source) - return PA_HOOK_OK; - - sco_over_pcm_state_update(u, true); - - return PA_HOOK_OK; -} - -static pa_hook_result_t transport_nrec_changed_cb(pa_bluez4_discovery *y, pa_bluez4_transport *t, struct userdata *u) { - pa_proplist *p; - - pa_assert(t); - pa_assert(u); - - if (t != u->transport) - return PA_HOOK_OK; - - p = pa_proplist_new(); - pa_proplist_sets(p, "bluetooth.nrec", t->nrec ? "1" : "0"); - pa_source_update_proplist(u->source, PA_UPDATE_REPLACE, p); - pa_proplist_free(p); - - return PA_HOOK_OK; -} - -static pa_hook_result_t transport_microphone_gain_changed_cb(pa_bluez4_discovery *y, pa_bluez4_transport *t, - struct userdata *u) { - pa_cvolume v; - - pa_assert(t); - pa_assert(u); - - if (t != u->transport) - return PA_HOOK_OK; - - pa_assert(u->source); - - pa_cvolume_set(&v, u->sample_spec.channels, - (pa_volume_t) round((double) t->microphone_gain * PA_VOLUME_NORM / HSP_MAX_GAIN)); - pa_source_volume_changed(u->source, &v); - - return PA_HOOK_OK; -} - -static pa_hook_result_t transport_speaker_gain_changed_cb(pa_bluez4_discovery *y, pa_bluez4_transport *t, - struct userdata *u) { - pa_cvolume v; - - pa_assert(t); - pa_assert(u); - - if (t != u->transport) - return PA_HOOK_OK; - - pa_assert(u->sink); - - pa_cvolume_set(&v, u->sample_spec.channels, (pa_volume_t) round((double) t->speaker_gain * PA_VOLUME_NORM / HSP_MAX_GAIN)); - pa_sink_volume_changed(u->sink, &v); - - return PA_HOOK_OK; -} - -static void connect_ports(struct userdata *u, void *sink_or_source_new_data, pa_direction_t direction) { - pa_device_port *port; - - if (direction == PA_DIRECTION_OUTPUT) { - pa_sink_new_data *sink_new_data = sink_or_source_new_data; - - pa_assert_se(port = pa_hashmap_get(u->card->ports, u->output_port_name)); - pa_assert_se(pa_hashmap_put(sink_new_data->ports, port->name, port) >= 0); - pa_device_port_ref(port); - } else { - pa_source_new_data *source_new_data = sink_or_source_new_data; - - pa_assert_se(port = pa_hashmap_get(u->card->ports, u->input_port_name)); - pa_assert_se(pa_hashmap_put(source_new_data->ports, port->name, port) >= 0); - pa_device_port_ref(port); - } -} - -static int sink_set_port_cb(pa_sink *s, pa_device_port *p) { - return 0; -} - -static int source_set_port_cb(pa_source *s, pa_device_port *p) { - return 0; -} - -/* Run from main thread */ -static int add_sink(struct userdata *u) { - char *k; - - pa_assert(u->transport); - - if (USE_SCO_OVER_PCM(u)) { - pa_proplist *p; - - u->sink = u->hsp.sco_sink; - p = pa_proplist_new(); - pa_proplist_sets(p, "bluetooth.protocol", pa_bluez4_profile_to_string(u->profile)); - pa_proplist_update(u->sink->proplist, PA_UPDATE_MERGE, p); - pa_proplist_free(p); - } else { - pa_sink_new_data data; - bool b; - - pa_sink_new_data_init(&data); - data.driver = __FILE__; - data.module = u->module; - pa_sink_new_data_set_sample_spec(&data, &u->sample_spec); - pa_proplist_sets(data.proplist, "bluetooth.protocol", pa_bluez4_profile_to_string(u->profile)); - if (u->profile == PA_BLUEZ4_PROFILE_HEADSET_HEAD_UNIT) - pa_proplist_sets(data.proplist, PA_PROP_DEVICE_INTENDED_ROLES, "phone"); - data.card = u->card; - data.name = get_name("sink", u->modargs, u->address, pa_bluez4_profile_to_string(u->profile), &b); - data.namereg_fail = b; - - if (pa_modargs_get_proplist(u->modargs, "sink_properties", data.proplist, PA_UPDATE_REPLACE) < 0) { - pa_log("Invalid properties"); - pa_sink_new_data_done(&data); - return -1; - } - connect_ports(u, &data, PA_DIRECTION_OUTPUT); - - if (!u->transport_acquired) - switch (u->profile) { - case PA_BLUEZ4_PROFILE_A2DP_SINK: - case PA_BLUEZ4_PROFILE_HEADSET_HEAD_UNIT: - pa_assert_not_reached(); /* Profile switch should have failed */ - break; - case PA_BLUEZ4_PROFILE_HEADSET_AUDIO_GATEWAY: - data.suspend_cause = PA_SUSPEND_USER; - break; - case PA_BLUEZ4_PROFILE_A2DP_SOURCE: - case PA_BLUEZ4_PROFILE_OFF: - pa_assert_not_reached(); - } - - u->sink = pa_sink_new(u->core, &data, PA_SINK_HARDWARE|PA_SINK_LATENCY); - pa_sink_new_data_done(&data); - - if (!u->sink) { - pa_log_error("Failed to create sink"); - return -1; - } - - u->sink->userdata = u; - u->sink->parent.process_msg = sink_process_msg; - u->sink->set_state_in_io_thread = sink_set_state_in_io_thread_cb; - u->sink->set_port = sink_set_port_cb; - } - - if (u->profile == PA_BLUEZ4_PROFILE_HEADSET_HEAD_UNIT) { - pa_sink_set_set_volume_callback(u->sink, sink_set_volume_cb); - u->sink->n_volume_steps = 16; - - k = pa_sprintf_malloc("bluetooth-device@%p", (void*) u->sink); - pa_shared_set(u->core, k, u); - pa_xfree(k); - } - - return 0; -} - -/* Run from main thread */ -static int add_source(struct userdata *u) { - char *k; - - pa_assert(u->transport); - - if (USE_SCO_OVER_PCM(u)) { - u->source = u->hsp.sco_source; - pa_proplist_sets(u->source->proplist, "bluetooth.protocol", pa_bluez4_profile_to_string(u->profile)); - } else { - pa_source_new_data data; - bool b; - - pa_source_new_data_init(&data); - data.driver = __FILE__; - data.module = u->module; - pa_source_new_data_set_sample_spec(&data, &u->sample_spec); - pa_proplist_sets(data.proplist, "bluetooth.protocol", pa_bluez4_profile_to_string(u->profile)); - if (u->profile == PA_BLUEZ4_PROFILE_HEADSET_HEAD_UNIT) - pa_proplist_sets(data.proplist, PA_PROP_DEVICE_INTENDED_ROLES, "phone"); - - data.card = u->card; - data.name = get_name("source", u->modargs, u->address, pa_bluez4_profile_to_string(u->profile), &b); - data.namereg_fail = b; - - if (pa_modargs_get_proplist(u->modargs, "source_properties", data.proplist, PA_UPDATE_REPLACE) < 0) { - pa_log("Invalid properties"); - pa_source_new_data_done(&data); - return -1; - } - - connect_ports(u, &data, PA_DIRECTION_INPUT); - - if (!u->transport_acquired) - switch (u->profile) { - case PA_BLUEZ4_PROFILE_HEADSET_HEAD_UNIT: - pa_assert_not_reached(); /* Profile switch should have failed */ - break; - case PA_BLUEZ4_PROFILE_A2DP_SOURCE: - case PA_BLUEZ4_PROFILE_HEADSET_AUDIO_GATEWAY: - data.suspend_cause = PA_SUSPEND_USER; - break; - case PA_BLUEZ4_PROFILE_A2DP_SINK: - case PA_BLUEZ4_PROFILE_OFF: - pa_assert_not_reached(); - } - - u->source = pa_source_new(u->core, &data, PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY); - pa_source_new_data_done(&data); - - if (!u->source) { - pa_log_error("Failed to create source"); - return -1; - } - - u->source->userdata = u; - u->source->parent.process_msg = source_process_msg; - u->source->set_state_in_io_thread = source_set_state_in_io_thread_cb; - u->source->set_port = source_set_port_cb; - } - - if ((u->profile == PA_BLUEZ4_PROFILE_HEADSET_HEAD_UNIT) || (u->profile == PA_BLUEZ4_PROFILE_HEADSET_AUDIO_GATEWAY)) { - pa_bluez4_transport *t = u->transport; - pa_proplist_sets(u->source->proplist, "bluetooth.nrec", t->nrec ? "1" : "0"); - } - - if (u->profile == PA_BLUEZ4_PROFILE_HEADSET_HEAD_UNIT) { - pa_source_set_set_volume_callback(u->source, source_set_volume_cb); - u->source->n_volume_steps = 16; - - k = pa_sprintf_malloc("bluetooth-device@%p", (void*) u->source); - pa_shared_set(u->core, k, u); - pa_xfree(k); - } - - return 0; -} - -static void bt_transport_config_a2dp(struct userdata *u) { - const pa_bluez4_transport *t; - struct a2dp_info *a2dp = &u->a2dp; - a2dp_sbc_t *config; - - t = u->transport; - pa_assert(t); - - config = (a2dp_sbc_t *) t->config; - - u->sample_spec.format = PA_SAMPLE_S16LE; - - if (a2dp->sbc_initialized) - sbc_reinit(&a2dp->sbc, 0); - else - sbc_init(&a2dp->sbc, 0); - a2dp->sbc_initialized = true; - - switch (config->frequency) { - case SBC_SAMPLING_FREQ_16000: - a2dp->sbc.frequency = SBC_FREQ_16000; - u->sample_spec.rate = 16000U; - break; - case SBC_SAMPLING_FREQ_32000: - a2dp->sbc.frequency = SBC_FREQ_32000; - u->sample_spec.rate = 32000U; - break; - case SBC_SAMPLING_FREQ_44100: - a2dp->sbc.frequency = SBC_FREQ_44100; - u->sample_spec.rate = 44100U; - break; - case SBC_SAMPLING_FREQ_48000: - a2dp->sbc.frequency = SBC_FREQ_48000; - u->sample_spec.rate = 48000U; - break; - default: - pa_assert_not_reached(); - } - - switch (config->channel_mode) { - case SBC_CHANNEL_MODE_MONO: - a2dp->sbc.mode = SBC_MODE_MONO; - u->sample_spec.channels = 1; - break; - case SBC_CHANNEL_MODE_DUAL_CHANNEL: - a2dp->sbc.mode = SBC_MODE_DUAL_CHANNEL; - u->sample_spec.channels = 2; - break; - case SBC_CHANNEL_MODE_STEREO: - a2dp->sbc.mode = SBC_MODE_STEREO; - u->sample_spec.channels = 2; - break; - case SBC_CHANNEL_MODE_JOINT_STEREO: - a2dp->sbc.mode = SBC_MODE_JOINT_STEREO; - u->sample_spec.channels = 2; - break; - default: - pa_assert_not_reached(); - } - - switch (config->allocation_method) { - case SBC_ALLOCATION_SNR: - a2dp->sbc.allocation = SBC_AM_SNR; - break; - case SBC_ALLOCATION_LOUDNESS: - a2dp->sbc.allocation = SBC_AM_LOUDNESS; - break; - default: - pa_assert_not_reached(); - } - - switch (config->subbands) { - case SBC_SUBBANDS_4: - a2dp->sbc.subbands = SBC_SB_4; - break; - case SBC_SUBBANDS_8: - a2dp->sbc.subbands = SBC_SB_8; - break; - default: - pa_assert_not_reached(); - } - - switch (config->block_length) { - case SBC_BLOCK_LENGTH_4: - a2dp->sbc.blocks = SBC_BLK_4; - break; - case SBC_BLOCK_LENGTH_8: - a2dp->sbc.blocks = SBC_BLK_8; - break; - case SBC_BLOCK_LENGTH_12: - a2dp->sbc.blocks = SBC_BLK_12; - break; - case SBC_BLOCK_LENGTH_16: - a2dp->sbc.blocks = SBC_BLK_16; - break; - default: - pa_assert_not_reached(); - } - - a2dp->min_bitpool = config->min_bitpool; - a2dp->max_bitpool = config->max_bitpool; - - /* Set minimum bitpool for source to get the maximum possible block_size */ - a2dp->sbc.bitpool = u->profile == PA_BLUEZ4_PROFILE_A2DP_SINK ? a2dp->max_bitpool : a2dp->min_bitpool; - a2dp->codesize = sbc_get_codesize(&a2dp->sbc); - a2dp->frame_length = sbc_get_frame_length(&a2dp->sbc); - - pa_log_info("SBC parameters:\n\tallocation=%u\n\tsubbands=%u\n\tblocks=%u\n\tbitpool=%u", - a2dp->sbc.allocation, a2dp->sbc.subbands, a2dp->sbc.blocks, a2dp->sbc.bitpool); -} - -static void bt_transport_config(struct userdata *u) { - if (u->profile == PA_BLUEZ4_PROFILE_HEADSET_HEAD_UNIT || u->profile == PA_BLUEZ4_PROFILE_HEADSET_AUDIO_GATEWAY) { - u->sample_spec.format = PA_SAMPLE_S16LE; - u->sample_spec.channels = 1; - u->sample_spec.rate = 8000; - } else - bt_transport_config_a2dp(u); -} - -/* Run from main thread */ -static pa_hook_result_t transport_state_changed_cb(pa_bluez4_discovery *y, pa_bluez4_transport *t, struct userdata *u) { - pa_assert(t); - pa_assert(u); - - if (t == u->transport && t->state == PA_BLUEZ4_TRANSPORT_STATE_DISCONNECTED) - pa_assert_se(pa_card_set_profile(u->card, pa_hashmap_get(u->card->profiles, "off"), false) >= 0); - - if (t->device == u->device) - handle_transport_state_change(u, t); - - return PA_HOOK_OK; -} - -/* Run from main thread */ -static int setup_transport(struct userdata *u) { - pa_bluez4_transport *t; - - pa_assert(u); - pa_assert(!u->transport); - pa_assert(u->profile != PA_BLUEZ4_PROFILE_OFF); - - /* check if profile has a transport */ - t = u->device->transports[u->profile]; - if (!t || t->state == PA_BLUEZ4_TRANSPORT_STATE_DISCONNECTED) { - pa_log_warn("Profile has no transport"); - return -1; - } - - u->transport = t; - - if (u->profile == PA_BLUEZ4_PROFILE_A2DP_SOURCE || u->profile == PA_BLUEZ4_PROFILE_HEADSET_AUDIO_GATEWAY) - bt_transport_acquire(u, true); /* In case of error, the sink/sources will be created suspended */ - else if (bt_transport_acquire(u, false) < 0) - return -1; /* We need to fail here until the interactions with module-suspend-on-idle and alike get improved */ - - bt_transport_config(u); - - return 0; -} - -/* Run from main thread */ -static int init_profile(struct userdata *u) { - int r = 0; - pa_assert(u); - pa_assert(u->profile != PA_BLUEZ4_PROFILE_OFF); - - if (setup_transport(u) < 0) - return -1; - - pa_assert(u->transport); - - if (u->profile == PA_BLUEZ4_PROFILE_A2DP_SINK || - u->profile == PA_BLUEZ4_PROFILE_HEADSET_HEAD_UNIT || - u->profile == PA_BLUEZ4_PROFILE_HEADSET_AUDIO_GATEWAY) - if (add_sink(u) < 0) - r = -1; - - if (u->profile == PA_BLUEZ4_PROFILE_HEADSET_HEAD_UNIT || - u->profile == PA_BLUEZ4_PROFILE_A2DP_SOURCE || - u->profile == PA_BLUEZ4_PROFILE_HEADSET_AUDIO_GATEWAY) - if (add_source(u) < 0) - r = -1; - - return r; -} - -/* Run from main thread */ -static void stop_thread(struct userdata *u) { - char *k; - - pa_assert(u); - - if (u->sink && !USE_SCO_OVER_PCM(u)) - pa_sink_unlink(u->sink); - - if (u->source && !USE_SCO_OVER_PCM(u)) - pa_source_unlink(u->source); - - if (u->thread) { - pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL); - pa_thread_free(u->thread); - u->thread = NULL; - } - - if (u->rtpoll_item) { - pa_rtpoll_item_free(u->rtpoll_item); - u->rtpoll_item = NULL; - } - - if (u->rtpoll) { - pa_thread_mq_done(&u->thread_mq); - - pa_rtpoll_free(u->rtpoll); - u->rtpoll = NULL; - } - - if (u->transport) { - bt_transport_release(u); - u->transport = NULL; - } - - if (u->sink) { - if (u->profile == PA_BLUEZ4_PROFILE_HEADSET_HEAD_UNIT) { - k = pa_sprintf_malloc("bluetooth-device@%p", (void*) u->sink); - pa_shared_remove(u->core, k); - pa_xfree(k); - } - - pa_sink_unref(u->sink); - u->sink = NULL; - } - - if (u->source) { - if (u->profile == PA_BLUEZ4_PROFILE_HEADSET_HEAD_UNIT) { - k = pa_sprintf_malloc("bluetooth-device@%p", (void*) u->source); - pa_shared_remove(u->core, k); - pa_xfree(k); - } - - pa_source_unref(u->source); - u->source = NULL; - } - - if (u->read_smoother) { - pa_smoother_free(u->read_smoother); - u->read_smoother = NULL; - } -} - -/* Run from main thread */ -static int start_thread(struct userdata *u) { - pa_assert(u); - pa_assert(!u->thread); - pa_assert(!u->rtpoll); - pa_assert(!u->rtpoll_item); - - u->rtpoll = pa_rtpoll_new(); - - if (pa_thread_mq_init(&u->thread_mq, u->core->mainloop, u->rtpoll) < 0) { - pa_log("pa_thread_mq_init() failed."); - return -1; - } - - if (USE_SCO_OVER_PCM(u)) { - if (sco_over_pcm_state_update(u, false) < 0) { - char *k; - - if (u->sink) { - k = pa_sprintf_malloc("bluetooth-device@%p", (void*) u->sink); - pa_shared_remove(u->core, k); - pa_xfree(k); - u->sink = NULL; - } - if (u->source) { - k = pa_sprintf_malloc("bluetooth-device@%p", (void*) u->source); - pa_shared_remove(u->core, k); - pa_xfree(k); - u->source = NULL; - } - return -1; - } - - pa_sink_ref(u->sink); - pa_source_ref(u->source); - /* FIXME: monitor stream_fd error */ - return 0; - } - - if (!(u->thread = pa_thread_new("bluetooth", thread_func, u))) { - pa_log_error("Failed to create IO thread"); - return -1; - } - - if (u->sink) { - pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq); - pa_sink_set_rtpoll(u->sink, u->rtpoll); - pa_sink_put(u->sink); - - if (u->sink->set_volume) - u->sink->set_volume(u->sink); - } - - if (u->source) { - pa_source_set_asyncmsgq(u->source, u->thread_mq.inq); - pa_source_set_rtpoll(u->source, u->rtpoll); - pa_source_put(u->source); - - if (u->source->set_volume) - u->source->set_volume(u->source); - } - - return 0; -} - -static void save_sco_volume_callbacks(struct userdata *u) { - pa_assert(u); - pa_assert(USE_SCO_OVER_PCM(u)); - - u->hsp.sco_sink_set_volume = u->hsp.sco_sink->set_volume; - u->hsp.sco_source_set_volume = u->hsp.sco_source->set_volume; -} - -static void restore_sco_volume_callbacks(struct userdata *u) { - pa_assert(u); - pa_assert(USE_SCO_OVER_PCM(u)); - - pa_sink_set_set_volume_callback(u->hsp.sco_sink, u->hsp.sco_sink_set_volume); - pa_source_set_set_volume_callback(u->hsp.sco_source, u->hsp.sco_source_set_volume); -} - -/* Run from main thread */ -static int card_set_profile(pa_card *c, pa_card_profile *new_profile) { - struct userdata *u; - pa_bluez4_profile_t *d; - - pa_assert(c); - pa_assert(new_profile); - pa_assert_se(u = c->userdata); - - d = PA_CARD_PROFILE_DATA(new_profile); - - if (*d != PA_BLUEZ4_PROFILE_OFF) { - const pa_bluez4_device *device = u->device; - - if (!device->transports[*d] || device->transports[*d]->state == PA_BLUEZ4_TRANSPORT_STATE_DISCONNECTED) { - pa_log_warn("Profile not connected, refused to switch profile to %s", new_profile->name); - return -PA_ERR_IO; - } - } - - stop_thread(u); - - if (USE_SCO_OVER_PCM(u)) - restore_sco_volume_callbacks(u); - - u->profile = *d; - u->sample_spec = u->requested_sample_spec; - - if (USE_SCO_OVER_PCM(u)) - save_sco_volume_callbacks(u); - - if (u->profile != PA_BLUEZ4_PROFILE_OFF) - if (init_profile(u) < 0) - goto off; - - if (u->sink || u->source) - if (start_thread(u) < 0) - goto off; - - return 0; - -off: - stop_thread(u); - - pa_assert_se(pa_card_set_profile(u->card, pa_hashmap_get(u->card->profiles, "off"), false) >= 0); - - return -PA_ERR_IO; -} - -/* Run from main thread */ -static void create_card_ports(struct userdata *u, pa_hashmap *ports) { - pa_device_port *port; - pa_device_port_new_data port_data; - - const char *name_prefix = NULL; - const char *input_description = NULL; - const char *output_description = NULL; - - pa_assert(u); - pa_assert(ports); - pa_assert(u->device); - - switch (pa_bluez4_get_form_factor(u->device->class)) { - case PA_BLUEZ4_FORM_FACTOR_UNKNOWN: - break; - - case PA_BLUEZ4_FORM_FACTOR_HEADSET: - name_prefix = "headset"; - input_description = output_description = _("Headset"); - break; - - case PA_BLUEZ4_FORM_FACTOR_HANDSFREE: - name_prefix = "handsfree"; - input_description = output_description = _("Handsfree"); - break; - - case PA_BLUEZ4_FORM_FACTOR_MICROPHONE: - name_prefix = "microphone"; - input_description = _("Microphone"); - break; - - case PA_BLUEZ4_FORM_FACTOR_SPEAKER: - name_prefix = "speaker"; - output_description = _("Speaker"); - break; - - case PA_BLUEZ4_FORM_FACTOR_HEADPHONE: - name_prefix = "headphone"; - output_description = _("Headphone"); - break; - - case PA_BLUEZ4_FORM_FACTOR_PORTABLE: - name_prefix = "portable"; - input_description = output_description = _("Portable"); - break; - - case PA_BLUEZ4_FORM_FACTOR_CAR: - name_prefix = "car"; - input_description = output_description = _("Car"); - break; - - case PA_BLUEZ4_FORM_FACTOR_HIFI: - name_prefix = "hifi"; - input_description = output_description = _("HiFi"); - break; - - case PA_BLUEZ4_FORM_FACTOR_PHONE: - name_prefix = "phone"; - input_description = output_description = _("Phone"); - break; - } - - if (!name_prefix) - name_prefix = "unknown"; - - if (!output_description) - output_description = _("Bluetooth Output"); - - if (!input_description) - input_description = _("Bluetooth Input"); - - u->output_port_name = pa_sprintf_malloc("%s-output", name_prefix); - u->input_port_name = pa_sprintf_malloc("%s-input", name_prefix); - - pa_device_port_new_data_init(&port_data); - pa_device_port_new_data_set_name(&port_data, u->output_port_name); - pa_device_port_new_data_set_description(&port_data, output_description); - pa_device_port_new_data_set_direction(&port_data, PA_DIRECTION_OUTPUT); - pa_device_port_new_data_set_available(&port_data, get_port_availability(u, PA_DIRECTION_OUTPUT)); - pa_assert_se(port = pa_device_port_new(u->core, &port_data, 0)); - pa_assert_se(pa_hashmap_put(ports, port->name, port) >= 0); - pa_device_port_new_data_done(&port_data); - - pa_device_port_new_data_init(&port_data); - pa_device_port_new_data_set_name(&port_data, u->input_port_name); - pa_device_port_new_data_set_description(&port_data, input_description); - pa_device_port_new_data_set_direction(&port_data, PA_DIRECTION_INPUT); - pa_device_port_new_data_set_available(&port_data, get_port_availability(u, PA_DIRECTION_INPUT)); - pa_assert_se(port = pa_device_port_new(u->core, &port_data, 0)); - pa_assert_se(pa_hashmap_put(ports, port->name, port) >= 0); - pa_device_port_new_data_done(&port_data); -} - -/* Run from main thread */ -static pa_card_profile *create_card_profile(struct userdata *u, pa_bluez4_profile_t profile, pa_hashmap *ports) { - pa_device_port *input_port, *output_port; - const char *name; - pa_card_profile *p = NULL; - pa_bluez4_profile_t *d = NULL; - pa_bluez4_transport *t; - - pa_assert(u->input_port_name); - pa_assert(u->output_port_name); - pa_assert_se(input_port = pa_hashmap_get(ports, u->input_port_name)); - pa_assert_se(output_port = pa_hashmap_get(ports, u->output_port_name)); - - name = pa_bluez4_profile_to_string(profile); - - switch (profile) { - case PA_BLUEZ4_PROFILE_A2DP_SINK: - p = pa_card_profile_new(name, _("High Fidelity Playback (A2DP)"), sizeof(pa_bluez4_profile_t)); - p->priority = 10; - p->n_sinks = 1; - p->n_sources = 0; - p->max_sink_channels = 2; - p->max_source_channels = 0; - pa_hashmap_put(output_port->profiles, p->name, p); - - d = PA_CARD_PROFILE_DATA(p); - break; - - case PA_BLUEZ4_PROFILE_A2DP_SOURCE: - p = pa_card_profile_new(name, _("High Fidelity Capture (A2DP)"), sizeof(pa_bluez4_profile_t)); - p->priority = 10; - p->n_sinks = 0; - p->n_sources = 1; - p->max_sink_channels = 0; - p->max_source_channels = 2; - pa_hashmap_put(input_port->profiles, p->name, p); - - d = PA_CARD_PROFILE_DATA(p); - break; - - case PA_BLUEZ4_PROFILE_HEADSET_HEAD_UNIT: - p = pa_card_profile_new(name, _("Telephony Duplex (HSP/HFP)"), sizeof(pa_bluez4_profile_t)); - p->priority = 20; - p->n_sinks = 1; - p->n_sources = 1; - p->max_sink_channels = 1; - p->max_source_channels = 1; - pa_hashmap_put(input_port->profiles, p->name, p); - pa_hashmap_put(output_port->profiles, p->name, p); - - d = PA_CARD_PROFILE_DATA(p); - break; - - case PA_BLUEZ4_PROFILE_HEADSET_AUDIO_GATEWAY: - p = pa_card_profile_new(name, _("Handsfree Gateway"), sizeof(pa_bluez4_profile_t)); - p->priority = 20; - p->n_sinks = 1; - p->n_sources = 1; - p->max_sink_channels = 1; - p->max_source_channels = 1; - pa_hashmap_put(input_port->profiles, p->name, p); - pa_hashmap_put(output_port->profiles, p->name, p); - - d = PA_CARD_PROFILE_DATA(p); - break; - - case PA_BLUEZ4_PROFILE_OFF: - pa_assert_not_reached(); - } - - *d = profile; - - if ((t = u->device->transports[*d])) - p->available = transport_state_to_availability(t->state); - - return p; -} - -static int uuid_to_profile(const char *uuid, pa_bluez4_profile_t *_r) { - if (pa_streq(uuid, PA_BLUEZ4_UUID_A2DP_SINK)) - *_r = PA_BLUEZ4_PROFILE_A2DP_SINK; - else if (pa_streq(uuid, PA_BLUEZ4_UUID_A2DP_SOURCE)) - *_r = PA_BLUEZ4_PROFILE_A2DP_SOURCE; - else if (pa_streq(uuid, PA_BLUEZ4_UUID_HSP_HS) || pa_streq(uuid, PA_BLUEZ4_UUID_HFP_HF)) - *_r = PA_BLUEZ4_PROFILE_HEADSET_HEAD_UNIT; - else if (pa_streq(uuid, PA_BLUEZ4_UUID_HSP_AG) || pa_streq(uuid, PA_BLUEZ4_UUID_HFP_AG)) - *_r = PA_BLUEZ4_PROFILE_HEADSET_AUDIO_GATEWAY; - else - return -PA_ERR_INVALID; - - return 0; -} - -/* Run from main thread */ -static int add_card(struct userdata *u) { - pa_card_new_data data; - bool b; - pa_card_profile *p; - pa_bluez4_profile_t *d; - pa_bluez4_form_factor_t ff; - char *n; - const char *profile_str; - const pa_bluez4_device *device; - const char *uuid; - void *state; - - pa_assert(u); - pa_assert(u->device); - - device = u->device; - - pa_card_new_data_init(&data); - data.driver = __FILE__; - data.module = u->module; - - n = pa_utf8_filter(device->alias); - pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, n); - pa_xfree(n); - pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, device->address); - pa_proplist_sets(data.proplist, PA_PROP_DEVICE_API, "bluez"); - pa_proplist_sets(data.proplist, PA_PROP_DEVICE_CLASS, "sound"); - pa_proplist_sets(data.proplist, PA_PROP_DEVICE_BUS, "bluetooth"); - - if ((ff = pa_bluez4_get_form_factor(device->class)) != PA_BLUEZ4_FORM_FACTOR_UNKNOWN) - pa_proplist_sets(data.proplist, PA_PROP_DEVICE_FORM_FACTOR, pa_bluez4_form_factor_to_string(ff)); - - pa_proplist_sets(data.proplist, "bluez.path", device->path); - pa_proplist_setf(data.proplist, "bluez.class", "0x%06x", (unsigned) device->class); - pa_proplist_sets(data.proplist, "bluez.alias", device->alias); - data.name = get_name("card", u->modargs, device->address, NULL, &b); - data.namereg_fail = b; - - if (pa_modargs_get_proplist(u->modargs, "card_properties", data.proplist, PA_UPDATE_REPLACE) < 0) { - pa_log("Invalid properties"); - pa_card_new_data_done(&data); - return -1; - } - - create_card_ports(u, data.ports); - - PA_HASHMAP_FOREACH(uuid, device->uuids, state) { - pa_bluez4_profile_t profile; - - if (uuid_to_profile(uuid, &profile) < 0) - continue; - - if (pa_hashmap_get(data.profiles, pa_bluez4_profile_to_string(profile))) - continue; - - p = create_card_profile(u, profile, data.ports); - pa_hashmap_put(data.profiles, p->name, p); - } - - pa_assert(!pa_hashmap_isempty(data.profiles)); - - p = pa_card_profile_new("off", _("Off"), sizeof(pa_bluez4_profile_t)); - p->available = PA_AVAILABLE_YES; - d = PA_CARD_PROFILE_DATA(p); - *d = PA_BLUEZ4_PROFILE_OFF; - pa_hashmap_put(data.profiles, p->name, p); - - u->card = pa_card_new(u->core, &data); - pa_card_new_data_done(&data); - - if (!u->card) { - pa_log("Failed to allocate card."); - return -1; - } - - u->card->userdata = u; - u->card->set_profile = card_set_profile; - - pa_card_choose_initial_profile(u->card); - - /* If the "profile" modarg is given, we have to override whatever the usual - * policy chose in pa_card_choose_initial_profile(). */ - profile_str = pa_modargs_get_value(u->modargs, "profile", NULL); - if (profile_str) { - pa_card_profile *profile; - - profile = pa_hashmap_get(u->card->profiles, profile_str); - if (!profile) { - pa_log("No such profile: %s", profile_str); - return -1; - } - - pa_card_set_profile(u->card, profile, false); - } - - pa_card_put(u->card); - - d = PA_CARD_PROFILE_DATA(u->card->active_profile); - - if (*d != PA_BLUEZ4_PROFILE_OFF && (!device->transports[*d] || - device->transports[*d]->state == PA_BLUEZ4_TRANSPORT_STATE_DISCONNECTED)) { - pa_log_warn("Default profile not connected, selecting off profile"); - u->card->active_profile = pa_hashmap_get(u->card->profiles, "off"); - u->card->save_profile = false; - } - - d = PA_CARD_PROFILE_DATA(u->card->active_profile); - u->profile = *d; - - if (USE_SCO_OVER_PCM(u)) - save_sco_volume_callbacks(u); - - return 0; -} - -/* Run from main thread */ -static pa_bluez4_device* find_device(struct userdata *u, const char *address, const char *path) { - pa_bluez4_device *d = NULL; - - pa_assert(u); - - if (!address && !path) { - pa_log_error("Failed to get device address/path from module arguments."); - return NULL; - } - - if (path) { - if (!(d = pa_bluez4_discovery_get_by_path(u->discovery, path))) { - pa_log_error("%s is not a valid BlueZ audio device.", path); - return NULL; - } - - if (address && !(pa_streq(d->address, address))) { - pa_log_error("Passed path %s address %s != %s don't match.", path, d->address, address); - return NULL; - } - - } else { - if (!(d = pa_bluez4_discovery_get_by_address(u->discovery, address))) { - pa_log_error("%s is not known.", address); - return NULL; - } - } - - if (d) { - u->address = pa_xstrdup(d->address); - u->path = pa_xstrdup(d->path); - } - - return d; -} - -/* Run from main thread */ -static pa_hook_result_t uuid_added_cb(pa_bluez4_discovery *y, const struct pa_bluez4_hook_uuid_data *data, - struct userdata *u) { - pa_bluez4_profile_t profile; - pa_card_profile *p; - - pa_assert(data); - pa_assert(data->device); - pa_assert(data->uuid); - pa_assert(u); - - if (data->device != u->device) - return PA_HOOK_OK; - - if (uuid_to_profile(data->uuid, &profile) < 0) - return PA_HOOK_OK; - - if (pa_hashmap_get(u->card->profiles, pa_bluez4_profile_to_string(profile))) - return PA_HOOK_OK; - - p = create_card_profile(u, profile, u->card->ports); - pa_card_add_profile(u->card, p); - - return PA_HOOK_OK; -} - -/* Run from main thread */ -static pa_hook_result_t discovery_hook_cb(pa_bluez4_discovery *y, const pa_bluez4_device *d, struct userdata *u) { - pa_assert(u); - pa_assert(d); - - if (d != u->device) - return PA_HOOK_OK; - - if (d->dead) - pa_log_debug("Device %s removed: unloading module", d->path); - else if (!pa_bluez4_device_any_audio_connected(d)) - pa_log_debug("Unloading module, because device %s doesn't have any audio profiles connected anymore.", d->path); - else - return PA_HOOK_OK; - - pa_module_unload(u->module, true); - - return PA_HOOK_OK; -} - -int pa__init(pa_module *m) { - pa_modargs *ma; - uint32_t channels; - struct userdata *u; - const char *address, *path; - pa_bluez4_device *device; - - pa_assert(m); - - if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log_error("Failed to parse module arguments"); - goto fail; - } - - m->userdata = u = pa_xnew0(struct userdata, 1); - u->module = m; - u->core = m->core; - u->stream_fd = -1; - u->sample_spec = m->core->default_sample_spec; - u->modargs = ma; - - if (pa_modargs_get_value(ma, "sco_sink", NULL) && - !(u->hsp.sco_sink = pa_namereg_get(m->core, pa_modargs_get_value(ma, "sco_sink", NULL), PA_NAMEREG_SINK))) { - pa_log("SCO sink not found"); - goto fail; - } - - if (pa_modargs_get_value(ma, "sco_source", NULL) && - !(u->hsp.sco_source = pa_namereg_get(m->core, pa_modargs_get_value(ma, "sco_source", NULL), PA_NAMEREG_SOURCE))) { - pa_log("SCO source not found"); - goto fail; - } - - if (pa_modargs_get_sample_rate(ma, &u->sample_spec.rate) < 0) { - pa_log_error("Failed to get rate from module arguments"); - goto fail; - } - - channels = u->sample_spec.channels; - if (pa_modargs_get_value_u32(ma, "channels", &channels) < 0 || - !pa_channels_valid(channels)) { - pa_log_error("Failed to get channels from module arguments"); - goto fail; - } - u->sample_spec.channels = (uint8_t) channels; - u->requested_sample_spec = u->sample_spec; - - address = pa_modargs_get_value(ma, "address", NULL); - path = pa_modargs_get_value(ma, "path", NULL); - - if (!(u->discovery = pa_bluez4_discovery_get(m->core))) - goto fail; - - if (!(device = find_device(u, address, path))) - goto fail; - - u->device = device; - - u->discovery_slot = - pa_hook_connect(pa_bluez4_discovery_hook(u->discovery, PA_BLUEZ4_HOOK_DEVICE_CONNECTION_CHANGED), - PA_HOOK_NORMAL, (pa_hook_cb_t) discovery_hook_cb, u); - - u->uuid_added_slot = - pa_hook_connect(pa_bluez4_discovery_hook(u->discovery, PA_BLUEZ4_HOOK_DEVICE_UUID_ADDED), - PA_HOOK_NORMAL, (pa_hook_cb_t) uuid_added_cb, u); - - u->sink_state_changed_slot = - pa_hook_connect(&u->core->hooks[PA_CORE_HOOK_SINK_STATE_CHANGED], - PA_HOOK_NORMAL, (pa_hook_cb_t) sink_state_changed_cb, u); - - u->source_state_changed_slot = - pa_hook_connect(&u->core->hooks[PA_CORE_HOOK_SOURCE_STATE_CHANGED], - PA_HOOK_NORMAL, (pa_hook_cb_t) source_state_changed_cb, u); - - u->transport_state_changed_slot = - pa_hook_connect(pa_bluez4_discovery_hook(u->discovery, PA_BLUEZ4_HOOK_TRANSPORT_STATE_CHANGED), - PA_HOOK_NORMAL, (pa_hook_cb_t) transport_state_changed_cb, u); - - u->transport_nrec_changed_slot = - pa_hook_connect(pa_bluez4_discovery_hook(u->discovery, PA_BLUEZ4_HOOK_TRANSPORT_NREC_CHANGED), - PA_HOOK_NORMAL, (pa_hook_cb_t) transport_nrec_changed_cb, u); - - u->transport_microphone_changed_slot = - pa_hook_connect(pa_bluez4_discovery_hook(u->discovery, PA_BLUEZ4_HOOK_TRANSPORT_MICROPHONE_GAIN_CHANGED), - PA_HOOK_NORMAL, (pa_hook_cb_t) transport_microphone_gain_changed_cb, u); - - u->transport_speaker_changed_slot = - pa_hook_connect(pa_bluez4_discovery_hook(u->discovery, PA_BLUEZ4_HOOK_TRANSPORT_SPEAKER_GAIN_CHANGED), - PA_HOOK_NORMAL, (pa_hook_cb_t) transport_speaker_gain_changed_cb, u); - - /* Add the card structure. This will also initialize the default profile */ - if (add_card(u) < 0) - goto fail; - - if (!(u->msg = pa_msgobject_new(bluetooth_msg))) - goto fail; - - u->msg->parent.process_msg = device_process_msg; - u->msg->card = u->card; - - if (u->profile != PA_BLUEZ4_PROFILE_OFF) - if (init_profile(u) < 0) - goto off; - - if (u->sink || u->source) - if (start_thread(u) < 0) - goto off; - - return 0; - -off: - stop_thread(u); - - pa_assert_se(pa_card_set_profile(u->card, pa_hashmap_get(u->card->profiles, "off"), false) >= 0); - - return 0; - -fail: - - pa__done(m); - - return -1; -} - -int pa__get_n_used(pa_module *m) { - struct userdata *u; - - pa_assert(m); - pa_assert_se(u = m->userdata); - - return - (u->sink ? pa_sink_linked_by(u->sink) : 0) + - (u->source ? pa_source_linked_by(u->source) : 0); -} - -void pa__done(pa_module *m) { - struct userdata *u; - - pa_assert(m); - - if (!(u = m->userdata)) - return; - - stop_thread(u); - - if (u->discovery_slot) - pa_hook_slot_free(u->discovery_slot); - - if (u->uuid_added_slot) - pa_hook_slot_free(u->uuid_added_slot); - - if (u->sink_state_changed_slot) - pa_hook_slot_free(u->sink_state_changed_slot); - - if (u->source_state_changed_slot) - pa_hook_slot_free(u->source_state_changed_slot); - - if (u->transport_state_changed_slot) - pa_hook_slot_free(u->transport_state_changed_slot); - - if (u->transport_nrec_changed_slot) - pa_hook_slot_free(u->transport_nrec_changed_slot); - - if (u->transport_microphone_changed_slot) - pa_hook_slot_free(u->transport_microphone_changed_slot); - - if (u->transport_speaker_changed_slot) - pa_hook_slot_free(u->transport_speaker_changed_slot); - - if (USE_SCO_OVER_PCM(u)) - restore_sco_volume_callbacks(u); - - if (u->msg) - pa_xfree(u->msg); - - if (u->card) - pa_card_free(u->card); - - if (u->a2dp.buffer) - pa_xfree(u->a2dp.buffer); - - sbc_finish(&u->a2dp.sbc); - - if (u->modargs) - pa_modargs_free(u->modargs); - - pa_xfree(u->output_port_name); - pa_xfree(u->input_port_name); - - pa_xfree(u->address); - pa_xfree(u->path); - - if (u->discovery) - pa_bluez4_discovery_unref(u->discovery); - - pa_xfree(u); -} diff --git a/src/modules/bluetooth/module-bluez4-discover.c b/src/modules/bluetooth/module-bluez4-discover.c deleted file mode 100644 index 2813cd54f..000000000 --- a/src/modules/bluetooth/module-bluez4-discover.c +++ /dev/null @@ -1,187 +0,0 @@ -/*** - This file is part of PulseAudio. - - Copyright 2008-2013 João Paulo Rechi Vita - - PulseAudio is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - PulseAudio is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. -***/ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdio.h> -#include <stdlib.h> - -#include <pulse/xmalloc.h> -#include <pulsecore/module.h> -#include <pulsecore/core-util.h> -#include <pulsecore/modargs.h> -#include <pulsecore/macro.h> -#include <pulsecore/core-util.h> -#include <pulsecore/dbus-shared.h> - -#include "bluez4-util.h" - -PA_MODULE_AUTHOR("João Paulo Rechi Vita"); -PA_MODULE_DESCRIPTION("Detect available BlueZ 4 Bluetooth audio devices and load BlueZ 4 Bluetooth audio drivers"); -PA_MODULE_VERSION(PACKAGE_VERSION); -PA_MODULE_USAGE("sco_sink=<name of sink> " - "sco_source=<name of source> "); -PA_MODULE_LOAD_ONCE(true); - -static const char* const valid_modargs[] = { - "sco_sink", - "sco_source", - "async", /* deprecated */ - NULL -}; - -struct userdata { - pa_module *module; - pa_modargs *modargs; - pa_core *core; - pa_bluez4_discovery *discovery; - pa_hook_slot *slot; - pa_hashmap *hashmap; -}; - -struct pa_module_info { - char *path; - uint32_t module; -}; - -static pa_hook_result_t load_module_for_device(pa_bluez4_discovery *y, const pa_bluez4_device *d, struct userdata *u) { - struct pa_module_info *mi; - - pa_assert(u); - pa_assert(d); - - mi = pa_hashmap_get(u->hashmap, d->path); - - if (pa_bluez4_device_any_audio_connected(d)) { - - if (!mi) { - pa_module *m = NULL; - char *args; - - /* Oh, awesome, a new device has shown up and been connected! */ - - args = pa_sprintf_malloc("address=\"%s\" path=\"%s\"", d->address, d->path); - - if (pa_modargs_get_value(u->modargs, "sco_sink", NULL) && - pa_modargs_get_value(u->modargs, "sco_source", NULL)) { - char *tmp; - - tmp = pa_sprintf_malloc("%s sco_sink=\"%s\" sco_source=\"%s\"", args, - pa_modargs_get_value(u->modargs, "sco_sink", NULL), - pa_modargs_get_value(u->modargs, "sco_source", NULL)); - pa_xfree(args); - args = tmp; - } - - pa_log_debug("Loading module-bluez4-device %s", args); - pa_module_load(&m, u->module->core, "module-bluez4-device", args); - pa_xfree(args); - - if (m) { - mi = pa_xnew(struct pa_module_info, 1); - mi->module = m->index; - mi->path = pa_xstrdup(d->path); - - pa_hashmap_put(u->hashmap, mi->path, mi); - } else - pa_log_debug("Failed to load module for device %s", d->path); - } - - } else { - - if (mi) { - - /* Hmm, disconnection? Then the module unloads itself */ - - pa_log_debug("Unregistering module for %s", d->path); - pa_hashmap_remove(u->hashmap, mi->path); - pa_xfree(mi->path); - pa_xfree(mi); - } - } - - return PA_HOOK_OK; -} - -int pa__init(pa_module* m) { - struct userdata *u; - pa_modargs *ma; - - pa_assert(m); - - if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { - pa_log("Failed to parse module arguments"); - goto fail; - } - - if (pa_modargs_get_value(ma, "async", NULL)) - pa_log_warn("The 'async' argument is deprecated and does nothing."); - - m->userdata = u = pa_xnew0(struct userdata, 1); - u->module = m; - u->core = m->core; - u->modargs = ma; - u->hashmap = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); - - if (!(u->discovery = pa_bluez4_discovery_get(u->core))) - goto fail; - - u->slot = pa_hook_connect(pa_bluez4_discovery_hook(u->discovery, PA_BLUEZ4_HOOK_DEVICE_CONNECTION_CHANGED), - PA_HOOK_NORMAL, (pa_hook_cb_t) load_module_for_device, u); - - return 0; - -fail: - pa__done(m); - - return -1; -} - -void pa__done(pa_module* m) { - struct userdata *u; - - pa_assert(m); - - if (!(u = m->userdata)) - return; - - if (u->slot) - pa_hook_slot_free(u->slot); - - if (u->discovery) - pa_bluez4_discovery_unref(u->discovery); - - if (u->hashmap) { - struct pa_module_info *mi; - - while ((mi = pa_hashmap_steal_first(u->hashmap))) { - pa_xfree(mi->path); - pa_xfree(mi); - } - - pa_hashmap_free(u->hashmap); - } - - if (u->modargs) - pa_modargs_free(u->modargs); - - pa_xfree(u); -} -- 2.14.3