16.04 Bluetooth A2DP-Kopfhörer können nicht verwendet werden, werden gepaart, es wird jedoch keine Verbindung hergestellt. Loggen Sie sich ein


15

Zunächst habe ich versucht, diese beiden zu befolgen: https://vilimpoc.org/blog/2016/04/30/ubuntu-16-04-bluetooth-speakers/ und PulseAudio können das Bluetooth-Modul 15.10 / 16.04 / 16.10 nicht laden

Wenn ich versuche, eine Verbindung zu meinem Jaybird X2 herzustellen (versucht auf Desktop und Laptop, Broadcom und Intel), wird die Verbindung für zwei Sekunden hergestellt und dann getrennt.

Protokollformular Syslog (von meinem Desktop mit Broadcom BT)

May 31 23:50:54 desktop pulseaudio[6247]: [pulseaudio] socket-server.c: bind(): Address already in use
May 31 23:50:54 desktop pulseaudio[6247]: [pulseaudio] module.c: Failed to load module "module-cli-protocol-unix" (argument: ""): initialization failed.
May 31 23:50:54 desktop pulseaudio[6247]: [pulseaudio] socket-server.c: bind(): Address already in use
May 31 23:50:54 desktop pulseaudio[6247]: [pulseaudio] module.c: Failed to load module "module-cli-protocol-unix" (argument: ""): initialization failed.

Und zu anderen Zeiten:

a2dp-sink profile connect failed for xxxxxxx Protocol not available

BEARBEITEN .. WICHTIG:

Ich habe jetzt herausgefunden, dass der Versuch, eine Verbindung zu anderen Geräten herzustellen, die meiste Zeit gut funktioniert (Micropod BT und Samsung AirTrack), aber sobald ich Jaybird X2 ausprobiere, deaktiviert / entlädt es das Modul-Bluetooth-Discovery und ich muss pactl load-module module-bluetooth-discoverfür das andere zwei wieder zu funktionieren ..

Nun passiert das mit Laptop:

May 31 17:02:58 vooze-x1 pulseaudio[3534]: [pulseaudio] backend-native.c: connect(): Function not implemented
May 31 17:02:58 vooze-x1 pulseaudio[3534]: [pulseaudio] volume.c: Assertion 'pa_channels_valid(channels)' failed at pulse/volume.c:74, function pa_cvolume_set(). Aborting.
May 31 17:02:58 vooze-x1 bluetoothd[865]: Endpoint unregistered: sender=:1.130 path=/MediaEndpoint/A2DPSource
May 31 17:02:58 vooze-x1 bluetoothd[865]: Endpoint unregistered: sender=:1.130 path=/MediaEndpoint/A2DPSink
May 31 17:03:00 vooze-x1 pulseaudio[3764]: [pulseaudio] main.c: User-configured server at {ddcf951d58914c47b9adca0056c50142}unix:/run/user/1000/pulse/native, which appears to be local. Probing deeper.
May 31 17:03:00 vooze-x1 pulseaudio[3767]: [pulseaudio] pid.c: Stale PID file, overwriting.

Ich konnte es vorher kurz auf meinem Desktop verbinden, aber A2DP funktionierte die meiste Zeit nicht.

Zwei verschiedene Fehler, aber dasselbe Problem. Was ist los?

Ist Bluetooth in Ubuntu 16.04 nur kaputt? Es funktioniert unter Windows und mit meinem Android Phone.

Jede Hilfe wäre super! :) Ich habe es irgendwie geschafft, dass es kurz funktioniert, zuerst hat es funktioniert, dann hat A2DP nicht funktioniert. Ich vermute, dass dies etwas mit A2DP zu tun hat. Nicht sicher.


Haben Sie Ihr Headset vor dem Herstellen der Verbindung in den Pairing-Modus versetzt? Halten Sie bei ausgeschaltetem Gerät die mittlere Taste 4 s lang gedrückt, bis rot / grün blinkend leuchtet. Suche danach in Ubuntu und verbinde dich. Siehe askubuntu.com/questions/259354/…
Takkat

Ja, und das Pairing funktioniert einwandfrei. Das Problem ist nicht das Paring, sondern das "Verbinden". Es verbindet sich und sagt "Kopfhörer angeschlossen" und trennt sich dann 2 Sekunden später.
Joakim Koed

Ich frage nur, weil es ein Symptom dafür ist, dass Geräte nicht richtig gekoppelt sind, um eine Verbindung herzustellen, aber dann scheitern. Es kann sich lohnen, es erneut zu versuchen (nachdem das Gerät von bekannten Geräten entfernt wurde).
Takkat

Takket: Ich habe es wahrscheinlich 20 Mal gemacht. Hard-Reset-Headset usw. usw.
Joakim Koed

1
Vielen Dank, dass Sie den Fehler gemeldet haben, @RobertIanHawdon. Ich habe mich als betroffen markiert.
Joakim Koed

Antworten:


12

Es ist ein bekannter Fehler. Versuchen Sie es rmmod btusb ; modprobe btusb. Ich musste es bis zu vier Mal machen.

Ich habe dies bei meinem Lenovo P50 mit Intel 8260 WLAN / Bluetooth gesehen. Manchmal wird die Bluetooth-Firmware beim Booten nicht richtig geladen. Ein anderes Mal funktioniert es einfach nicht.


2
In Bezug auf die Bluetooth-Unterstützung hat es für den 16.04. Einige gravierende Rückschritte gegeben.
Amias

@Amias Nun, ich konnte Bluetooth auch in 14.04 nicht zum Laufen bringen.
Jarno

1
Funktioniert für mich auf meinem Lenovo Y510P mit 16.04. Ich habe meinem ~ / .bashrc einen Alias ​​hinzugefügt:alias headphones='sudo rmmod btusb ; sudo modprobe btusb'
BenB

3

Ich hatte das gleiche Problem mit Jaybird X2 und Bluebuds X, obwohl andere Bluetooth-Audiogeräte problemlos funktionierten. Mit den Kopfhörern habe ich diesen Fehler bekommen:

Assertion 'pa_channels_valid(channels)' failed at pulse/volume.c:74, function pa_cvolume_set(). Aborting.

und pulseaudio stürzte ab. Was das Problem löste, war die Installation von pulseaudio aus folgenden Quellen:

  • Installieren Sie alle erforderlichen Pakete: sudo apt-get build-dep pulseaudio
  • Laden Sie https://freedesktop.org/software/pulseaudio/releases/pulseaudio-9.0.tar.gz herunter und entpacken Sie es.
  • In der Quelle dir laufen: ./bootstrap.sh --prefix=/usr. Wenn Sie möchten, können Sie die CFLAGSVariable ändern , um Compiler-Optimierungen zu ermöglichen, z . B. verwenden -O2anstelle von -O0.
  • Dann makeundsudo make install

Dies überschreibt die Standardsysteminstallation, funktioniert jedoch, bis die Pakete aktualisiert werden. Um Updates zu verhindern, können wir die pulseaudio-Pakete zurückstellen:

sudo apt-mark hold libpulse-dev libpulse0 libpulse-mainloop-glib0 pulseaudio pulseaudio-module-bluetooth pulseaudio-utils libpulsedsp pulseaudio-module-x11

Beachten Sie, dass ich pulseaudio 9.0 installiert habe, aber es ist nicht die Version, die es zum Laufen gebracht hat. Ich habe versucht, die Paketversion von pulseaudio 9.0 von der PPA zu verwenden , aber es stürzte auch mit demselben Fehler ab.


Hallo. Kompiliert das auch alle Währungen? Eigentlich habe ich gestern von schlau auf 6 herabgestuft. Hat perfekt funktioniert.
Joakim Koed

Bei der Zusammenstellung gab es keine Probleme. Was meinen Sie?
Andrzej Pronobis

Wenn nicht die Version, was hat den Unterschied gemacht?
Daniel Szmulewicz

2

Ich hatte dieses Problem mit meinem Bluedio T + 3-Headset und denke, dass ein Verbindungs-Timeout vorliegt. Sie müssen die Zeile ; exit-idle-time = 20in der Datei /etc/pulse/daemon.confaus dem Kommentar entfernen, indem Sie das Semikolon (;) entfernen.

Ändern Sie den Wert in -1:

exit-idle-time = -1

Nach diesem Einsatz bluetoothctlnoch einmal zu versuchen und an das Gerät anschließen. Anweisungen finden Sie hier:

Arch-Wiki: Bluetooth-Headset


1

Stellen Sie Folgendes sicher:

  • Jaybird X2 ist gepaart
  • Es wird als vertrauenswürdig markiert (entweder über bluetoothctlund trust XX:XX:XX:XX(wo XX:XX:XX:XXist die MAC-Adresse Ihres Jaybird) oder überblueman-manager )
  • es ist eingeschaltet

Drücken Sie einmal den Ein- / Ausschalter Ihres Jaybird X2. Dies löst wahrscheinlich eine automatische Verbindung zu bekannten Geräten aus. Daher müssen Sie möglicherweise sicherstellen, dass andere Geräte hier nicht stören. Von da an war die Verbindung stabil und es wird auch nach einem Neustart automatisch eine Verbindung hergestellt.

Lassen Sie mich wissen, ob dies auch Ihr Problem gelöst hat. Ich habe auch viele andere Dinge getan und beinahe aufgegeben, als ich versehentlich den Ein- / Ausschalter gedrückt habe ;-) Es könnte also auch sein, dass eines dieser anderen Dinge das Problem gelöst hat. (habe schon nach dingen rund um bluetooth, pulseaudio, bluez, pactl load-module gesucht und diese ausprobiert; also habe ich noch viele andere hinweise :-D)

UPDATE (nach erneuten Verbindungsproblemen)

Nachdem ich Jaybird X2 mit meinem Android-Handy verbunden hatte, konnte ich keine Verbindung mehr zu meinem Laptop herstellen, selbst nachdem ich die Verbindung von meinem Android-Handy getrennt hatte. Ich weiß noch nicht, wo genau das Problem liegt, aber um die Verbindung wieder herzustellen, musste ich Folgendes tun:

  1. Trennen Sie Jaybird X2 von meinem Android-Handy (oder einem anderen Gerät)
  2. ubuntu neu starten
  3. Das erneute Verbinden funktioniert und die Verbindung ist stabil (normalerweise hat es beim ersten Pairing nicht funktioniert ... danach musste ich auch neu gestartet werden)

Ich habe auch einige andere Dinge ausprobiert und es scheint, dass dies zumindest pulseaudio-module-bluetootherforderlich ist. Auch die WLAN / Bluetooth-Koexistenz-Konfiguration ist zumindest auf meinem Rechner erforderlich (siehe: /ubuntu//a/645072/558838 ). Und zu guter Letzt: Es ist immer ein Neustart erforderlich, um die Verbindung wiederherzustellen, falls ich auf ein anderes Gerät umgestiegen bin.

Zusammenfassend: Mit diesem Neustart kann ich den Jaybird X2 erfolgreich wieder verbinden und die Verbindung ist stabil. Wenn jemand einen einfacheren Weg kennt, um den Neustart-Schritt auszulassen, trage bitte bei :) /etc/init.d/bluetooth restart reicht nicht aus.

(zusätzliche Schritte, die ich ausprobiert habe):

Ich habe in meine Geschichte geschaut. Ich habe auch Folgendes ausprobiert, wobei der eine oder andere zur obigen Lösung beigetragen haben könnte:

  • apt-get install pulseaudio-module-bluetooth (auf meinem System war es nicht installiert)
  • In den Protokollen wurde etwas über das Fehlen erwähnt ofono, daher habe ich das auch installiert
  • tat ein sudo chown -R $USER ~/*
  • auch angewendet: /ubuntu//a/691299/558838 (Ich habe es jedoch zurückgesetzt, da es nicht geholfen hat. Es war möglicherweise noch aktiv, als ich die automatische Verbindung versuchte.)
  • habe auch das pulseaudio, blueman, bluetooth packag gelöscht / installiert

Vielen Dank, dass Sie versucht haben zu helfen, haben es gerade getestet und sind abgestürzt, sobald ich es versuchte. Ich habe dann versucht: Pactl Load-Modul-Modul-Bluetooth-Discover und drücken Sie die Power erneut, stürzte es wieder pulseaudio: /
Joakim Koed

Der Antwort, die ich ausprobiert habe, wurden zusätzliche Schritte hinzugefügt. Wenn Sie weitere Informationen benötigen, fragen Sie einfach.
Roland

IN ORDNUNG. Fand heute etwas anderes heraus: Nach einem Schlaf konnte ich es nicht wieder zum Laufen bringen. Trotzdem funktioniert es nach einem Neustart. Schlimmer noch: Sobald die Bluetooth-Verbindung hergestellt ist, funktioniert meine drahtlose Verbindung nicht mehr. Es bleibt in Verbindung, überträgt aber nichts. Ich muss das weiter untersuchen.
Roland

Fühlen Sie sich frei, sich als betroffen zu markieren: bugs.launchpad.net/ubuntu/+source/pulseaudio/+bug/1574324
Joakim Koed

Ich habe das Problem mit der Wi-Fi / Bluetooth-Koexistenz folgendermaßen behoben : askubuntu.com/a/645072/558838 :) Hat wieder geschlafen und die Bluetooth-Verbindung wurde wiederhergestellt ... daher muss ich möglicherweise überprüfen, was ich sonst noch getan habe es funktioniert jetzt ... Vielleicht war der Koexistenzfehler auch das Problem für die stabile Verbindung? Zumindest klingt es vernünftiger als die anderen Dinge, die ich aufgelistet habe :-) Könntest du das auch versuchen?
Roland

1

Führen Sie das Skript hier auf GitHub aus

Und das Problem wird verschwinden.

#! /usr/bin/env python3.5
"""

Fixing bluetooth stereo headphone/headset problem in ubuntu 16.04 and also debian jessie, with bluez5.

Workaround for bug: https://bugs.launchpad.net/ubuntu/+source/indicator-sound/+bug/1577197
Run it with python3.5 or higher after pairing/connecting the bluetooth stereo headphone.

This will be only fixes the bluez5 problem mentioned above .

Licence: Freeware

See ``python3.5 a2dp.py -h``.

Shorthands:

    $ alias speakers="a2dp.py 10:08:C1:44:AE:BC"
    $ alias headphones="a2dp.py 00:22:37:3D:DA:50"
    $ alias headset="a2dp.py 00:22:37:F8:A0:77 -p hsp"

    $ speakers



Check here for the latest updates: https://gist.github.com/pylover/d68be364adac5f946887b85e6ed6e7ae

Thanks to:

 * https://github.com/DominicWatson, for adding the ``-p/--profile`` argument.
 * https://github.com/IzzySoft, for mentioning wait before connecting again.
 * https://github.com/AmploDev, for v0.4.0

Change Log
----------

- 0.4.1
  * Sorting device list

- 0.4.0
  * Adding ignore_fail argument by @AmploDev.
  * Sending all available streams into selected sink, after successfull connection by @AmploDev.

- 0.3.3
  * Updating default sink before turning to ``off`` profile.

- 0.3.2
  * Waiting a bit: ``-w/--wait`` before connecting again.

- 0.3.0
  * Adding -p / --profile option for using the same script to switch between headset and A2DP audio profiles

- 0.2.5
  * Mentioning [mac] argument.

- 0.2.4
  * Removing duplicated devices in select device list.

- 0.2.3
  * Matching ANSI escape characters. Tested on 16.10 & 16.04

- 0.2.2
  * Some sort of code enhancements.

- 0.2.0
  * Adding `-V/--version`, `-w/--wait` and `-t/--tries` CLI arguments.

- 0.1.1
  * Supporting the `[NEW]` prefix for devices & controllers as advised by @wdullaer
  * Drying the code.

"""

import sys
import re
import asyncio
import subprocess as sb
import argparse


__version__ = '0.4.0'


HEX_DIGIT_PATTERN = '[0-9A-F]'
HEX_BYTE_PATTERN = '%s{2}' % HEX_DIGIT_PATTERN
MAC_ADDRESS_PATTERN = ':'.join((HEX_BYTE_PATTERN, ) * 6)
DEVICE_PATTERN = re.compile('^(?:.*\s)?Device\s(?P<mac>%s)\s(?P<name>.*)' % MAC_ADDRESS_PATTERN)
CONTROLLER_PATTERN = re.compile('^(?:.*\s)?Controller\s(?P<mac>%s)\s(?P<name>.*)' % MAC_ADDRESS_PATTERN)
WAIT_TIME = .75
TRIES = 4
PROFILE = 'a2dp'


_profiles = {
    'a2dp': 'a2dp_sink',
    'hsp': 'headset_head_unit',
    'off': 'off'
}

# CLI Arguments
parser = argparse.ArgumentParser(prog=sys.argv[0])
parser.add_argument('-e', '--echo', action='store_true', default=False,
                    help='If given, the subprocess stdout will be also printed on stdout.')
parser.add_argument('-w', '--wait', default=WAIT_TIME, type=float,
                    help='The seconds to wait for subprocess output, default is: %s' % WAIT_TIME)
parser.add_argument('-t', '--tries', default=TRIES, type=int,
                    help='The number of tries if subprocess is failed. default is: %s' % TRIES)
parser.add_argument('-p', '--profile', default=PROFILE,
                    help='The profile to switch to. available options are: hsp, a2dp. default is: %s' % PROFILE)
parser.add_argument('-V', '--version', action='store_true', help='Show the version.')
parser.add_argument('mac', nargs='?', default=None)


# Exceptions
class SubprocessError(Exception):
    pass


class RetryExceededError(Exception):
    pass


class BluetoothctlProtocol(asyncio.SubprocessProtocol):
    def __init__(self, exit_future, echo=True):
        self.exit_future = exit_future
        self.transport = None
        self.output = None
        self.echo = echo

    def listen_output(self):
        self.output = ''

    def not_listen_output(self):
        self.output = None

    def pipe_data_received(self, fd, raw):
        d = raw.decode()
        if self.echo:
            print(d, end='')

        if self.output is not None:
            self.output += d

    def process_exited(self):
        self.exit_future.set_result(True)

    def connection_made(self, transport):
        self.transport = transport
        print('Connection MADE')

    async def send_command(self, c):
        stdin_transport = self.transport.get_pipe_transport(0)
        # noinspection PyProtectedMember
        stdin_transport._pipe.write(('%s\n' % c).encode())

    async def search_in_output(self, expression, fail_expression=None):
        if self.output is None:
            return None

        for l in self.output.splitlines():
            if fail_expression and re.search(fail_expression, l, re.IGNORECASE):
                raise SubprocessError('Expression "%s" failed with fail pattern: "%s"' % (l, fail_expression))

            if re.search(expression, l, re.IGNORECASE):
                return True

    async def send_and_wait(self, cmd, wait_expression, fail_expression='fail'):
        try:
            self.listen_output()
            await self.send_command(cmd)
            while not await self.search_in_output(wait_expression.lower(), fail_expression=fail_expression):
                await wait()
        finally:
            self.not_listen_output()

    async def disconnect(self, mac):
        print('Disconnecting the device.')
        await self.send_and_wait('disconnect %s' % ':'.join(mac), 'Successful disconnected')

    async def connect(self, mac):
        print('Connecting again.')
        await self.send_and_wait('connect %s' % ':'.join(mac), 'Connection successful')

    async def trust(self, mac):
        await self.send_and_wait('trust %s' % ':'.join(mac), 'trust succeeded')

    async def quit(self):
        await self.send_command('quit')

    async def get_list(self, command, pattern):
        result = set()
        try:
            self.listen_output()
            await self.send_command(command)
            await wait()
            for l in self.output.splitlines():
                m = pattern.match(l)
                if m:
                    result.add(m.groups())
            return sorted(list(result), key=lambda i: i[1])
        finally:
            self.not_listen_output()

    async def list_devices(self):
        return await self.get_list('devices', DEVICE_PATTERN)

    async def list_paired_devices(self):
        return await self.get_list('paired-devices', DEVICE_PATTERN)

    async def list_controllers(self):
        return await self.get_list('list', CONTROLLER_PATTERN)

    async def select_paired_device(self):
        print('Selecting device:')
        devices = await self.list_paired_devices()
        count = len(devices)

        if count < 1:
            raise SubprocessError('There is no connected device.')
        elif count == 1:
            return devices[0]

        for i, d in enumerate(devices):
            print('%d. %s %s' % (i+1, d[0], d[1]))
        print('Select device[1]:')
        selected = input()
        return devices[0 if not selected.strip() else (int(selected) - 1)]


async def wait():
    return await asyncio.sleep(WAIT_TIME)


async def execute_command(cmd, ignore_fail=False):
    p = await asyncio.create_subprocess_shell(cmd, stdout=sb.PIPE, stderr=sb.PIPE)
    stdout, stderr = await p.communicate()
    stdout, stderr = \
        stdout.decode() if stdout is not None else '', \
        stderr.decode() if stderr is not None else ''
    if p.returncode != 0 or stderr.strip() != '':
        message = 'Command: %s failed with status: %s\nstderr: %s' % (cmd, p.returncode, stderr)
        if ignore_fail:
            print('Ignoring: %s' % message)
        else:
            raise SubprocessError(message)
    return stdout


async def execute_find(cmd, pattern, tries=0, fail_safe=False):
    tries = tries or TRIES

    message = 'Cannot find `%s` using `%s`.' % (pattern, cmd)
    retry_message = message + ' Retrying %d more times'
    while True:
        stdout = await execute_command(cmd)
        match = re.search(pattern, stdout)

        if match:
            return match.group()
        elif tries > 0:
            await wait()
            print(retry_message % tries)
            tries -= 1
            continue

        if fail_safe:
            return None

        raise RetryExceededError('Retry times exceeded: %s' % message)


async def find_dev_id(mac, **kw):
    return await execute_find('pactl list cards short', 'bluez_card.%s' % '_'.join(mac), **kw)


async def find_sink(mac, **kw):
    return await execute_find('pacmd list-sinks', 'bluez_sink.%s' % '_'.join(mac), **kw)


async def set_profile(device_id, profile):
    print('Setting the %s profile' % profile)
    try:
        return await execute_command('pactl set-card-profile %s %s' % (device_id, _profiles[profile]))
    except KeyError:
        print('Invalid profile: %s, please select one one of a2dp or hsp.' % profile, file=sys.stderr)
        raise SystemExit(1)


async def set_default_sink(sink):
    print('Updating default sink to %s' % sink)
    return await execute_command('pacmd set-default-sink %s' % sink)


async def move_streams_to_sink(sink):
    streams = await execute_command('pacmd list-sink-inputs | grep "index:"', True)
    for i in streams.split():
        i = ''.join(n for n in i if n.isdigit())
        if i != '':
            print('Moving stream %s to sink' % i)
            await execute_command('pacmd move-sink-input %s %s' % (i, sink))
    return sink


async def main(args):
    global WAIT_TIME, TRIES

    if args.version:
        print(__version__)
        return 0

    mac = args.mac

    # Hacking, Changing the constants!
    WAIT_TIME = args.wait
    TRIES = args.tries

    exit_future = asyncio.Future()
    transport, protocol = await asyncio.get_event_loop().subprocess_exec(
        lambda: BluetoothctlProtocol(exit_future, echo=args.echo), 'bluetoothctl'
    )

    try:

        if mac is None:
            mac, _ = await protocol.select_paired_device()

        mac = mac.split(':' if ':' in mac else '_')
        print('Device MAC: %s' % ':'.join(mac))

        device_id = await find_dev_id(mac, fail_safe=True)
        if device_id is None:
            print('It seems device: %s is not connected yet, trying to connect.' % ':'.join(mac))
            await protocol.trust(mac)
            await protocol.connect(mac)
            device_id = await find_dev_id(mac)

        sink = await find_sink(mac, fail_safe=True)
        if sink is None:
            await set_profile(device_id, args.profile)
            sink = await find_sink(mac)

        print('Device ID: %s' % device_id)
        print('Sink: %s' % sink)

        await set_default_sink(sink)
        await wait()

        await set_profile(device_id, 'off')

        if args.profile is 'a2dp':
            await protocol.disconnect(mac)
            await wait()
            await protocol.connect(mac)

        device_id = await find_dev_id(mac)
        print('Device ID: %s' % device_id)

        await set_profile(device_id, args.profile)
        await set_default_sink(sink)
        await move_streams_to_sink(sink)

    except (SubprocessError, RetryExceededError) as ex:
        print(str(ex), file=sys.stderr)
        return 1
    finally:
        print('Exiting bluetoothctl')
        await protocol.quit()
        await exit_future

        # Close the stdout pipe
        transport.close()

    if args.profile == 'a2dp':
        print('"Enjoy" the HiFi stereo music :)')
    else:
        print('"Enjoy" your headset audio :)')


if __name__ == '__main__':
    sys.exit(asyncio.get_event_loop().run_until_complete(main(parser.parse_args())))
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.