1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
|
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.
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
|