Skip to content

LADI/dbus-device-reservation

Repository files navigation

A SIMPLE DEVICE RESERVATION SCHEME WITH D-BUS

	This is supposed to bring peace to applications which require
	exclusive access to audio devices, such as PulseAudio or JACK,
	that currently fight a constant war about which application
	gets access. This interface is supposed to be very simple and
	implementable with only a few lines of code. Beyond improving
	cooperaton between JACK and PulseAudio this might be useful
	for other applications that need to access the audio device
	directly, for example for supporting functionality that is
	not available in these sound servers. e.g. media players
	might use this for implementing clean AC3 pass-thru bypassing
	PulseAudio, since PulseAudio doesn't support AC3 pass-thru for
	now.

	We version all services, objects, and interfaces to make them
	future proof.

	This is supposed to live on the session bus. Bus activation
	shall not be used for the service defined in this document.

	Interface and methods are intended to be abstract enough so
	that they may be reused for other resources than just sound
	cards.

	Code name: PAX SOUND SERVERIS

INTERFACE DEFINITION

	Service name:
		org.freedesktop.ReserveDevice1.<device name>

	Object name:
		/org/freedesktop/ReserveDevice1/<device name>

	Interface name:
		org.freedesktop.ReserveDevice1

	Methods:
		BOOL RequestRelease(INT32 priority)
                        (mandatory unless own priority is INT32_MAX)

			Ask the current owner of the device to release
			the device for take-over. The application
			requesting this should pass its priority. The
			owning application should then compare this
			priority with its own and release device
			access and return TRUE (in this order!) if the
			client's priority is greater than its own.

			If the client's priority is lower than its own
			the service should return FALSE and do nothing
			further.

                        The current owner doesn't need to base its
                        decision whether to return TRUE or FALSE
                        solely on the value of priority. It may take
                        other facts into consideration. However this
                        function is supposed to return quickly,
                        i.e. no user interaction shall be involved.

	Properties:
		INT32 Priority
                        (optional)

			The priority of the current owner of the
			device

		STRING ApplicationName
                        (optional)

			The name of the application currently holding
			the device

		STRING ApplicationDeviceName
                        (optional)

			The name of the device how it is presented in
			the application's context. This is supposed to
			be human readable device identification
			string.  This is intended to be used in user
			dialogs which inform which application blocks
			the device right now and help the user to make
			that application release it.

			Again, this is supposed to contain the device
			name in the *application's* context. Devices
			might appear under different names in
			different applications. e.g.  PulseAudio might
			list a device as "Intel HDA" while a
			different application might call it "hw:0". To
			help the user to free the right device in the
			application this property should hence contain
			the name in the owner application's
			context.

LOGIC

	When an audio application that requires exclusive access to
	the audio device starts up it shall first request the service
	name org.freedesktop.ReserveDevice1.<device name> on the
	session bus. <device name> shall be replaced by some form of
	device identifier. For sound cards supported by normal kernel
	drivers (i.e. ALSA/OSS kernel drivers) <device name> shall be
	replaced by "Audio<n>" where <n> refers to the numeric
	ALSA/OSS sound card index, 0 for the first card, 1 for the
	second card, ... Example: "Audio0"). If that succeeds it may
	access the audio device exclusively as long as it holds this
	service name. Similarly, for ALSA MIDI devices "Midi<n>" shall
	be used, while for /dev/video* devices Video<n> shall be used.

	The initial request shall be made with
	DBUS_NAME_FLAG_DO_NOT_QUEUE and
	DBUS_NAME_FLAG_ALLOW_REPLACEMENT (exception see
	below). DBUS_NAME_FLAG_REPLACE_EXISTING shall not be set.

	If the name request fails, the application may issue the
	RequestRelease() method on the service. It shall pass a
	priority value.  If that priority is greater than the one of
	the current owner the owner should release the device access,
	and return TRUE (in this order!). The client shall then
	request the name again, this time with
	DBUS_NAME_FLAG_REPLACE_EXISTING, DBUS_NAME_FLAG_DO_NOT_QUEUE,
	DBUS_NAME_FLAG_ALLOW_REPLACEMENT (exception see below) set. If
	the priority is lower then the owner should return FALSE and
	the client shall not try further access to the device.

	An application shall watch for
	org.freedesktop.DBus.LostName signals and give up
	device access in case its service name is forcibly taken
	away.

	While an application holds the service name it may exclusively
	access the device. It doesn't need to always keep it open
	during that time however. OTOH it shall not assume that
	opening the device actually always succeeds if it owns the
	name.

        We always reserve entire devices. Partial device reservation
        (as in only reserving playback, not capturing) shall not be
        implemented.

        As an exception to the rules above if an application has a
        priority of INT32_MAX DBUS_NAME_FLAG_ALLOW_REPLACEMENT should
        not be set when requesting the name. Also, in this case
        implementing the RequestRelease() method is
        optional.

        Implementations that call RequestName() MUST be able to handle
        the org.freedesktop.DBus.Error.UnknownMethod,
        org.freedesktop.DBus.Error.NoReply and
        org.freedesktop.DBus.Error.TimedOut error conditions. All
        three cases should NOT be treated as errors but as negative
        replies.

PRIORITIES

	Priorities may use the full INT32 range. Normal applications
	shall use priority 0. System services shall use positive
	priorities (i.e. because they are probably more important than
	normal applications).  "Unimportant" applications shall use
	negative priorities.

	Higher priority values win.

	INT32_MAX shall be considered the priority that always wins.

	INT32_MIN shall be considered the priority that always loses.

PROPERTIES

	Optionally the owner of the device access may export a few
	properties with a bit of descriptive information about
	itself. This is supposed to be useful to show a nice message
	to the user: "Application %s is blocking device %s. Please
	close this application or make sure it closes the access to
	that device." with ApplicationName and ApplicationDeviceName
	filled in.

        This data can be augmented by the data that is available from
        org.freedesktop.DBus.GetConnectionUnixUser and
        org.freedesktop.DBus.GetConnectionUnixProcessID.

RATIONALE

	There are two reasons to have RequestRelease instead of simply
	requesting the name right-away with
	DBUS_NAME_FLAG_REPLACE_EXISTING: firstly this fixes a race
	condition: the application giving up the name should first
	release the device and then release the name. If we take away
	the name forcibly right-away then the appliction needs to
	react to that and close the device while the new owner might
	already have tried to access it without success. Secondly, the
	priority logic requires an explicit method likes this.

	If an application dies its service name will automatically be
	released by the D-Bus bus daemon.

IMPLEMENTATION

        A trivial implementation of this interface uses INT32_MAX as
        priority value and does not implement RequestRelease or any
        other function or property of the interface defined above. An
        application written like this would always get access to the
        device (unless the device is already owned by an application
        that uses a similar trivial implementation) and would never
        need to give it up again.

Lennart Poettering