Bug Summary

File:common.c
Warning:line 141, column 17
Potential leak of memory pointed to by 'c'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name common.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -menable-no-infs -menable-no-nans -fapprox-func -menable-unsafe-fp-math -fno-signed-zeros -mreassociate -freciprocal-math -fdenormal-fp-math=preserve-sign,preserve-sign -ffp-contract=fast -fno-rounding-math -ffast-math -ffinite-math-only -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/rootdir/src -resource-dir /usr/lib/llvm-14/lib/clang/14.0.6 -D HAVE_CONFIG_H -I . -I .. -D KA_PLUGIN_PATH="/usr/local/lib/libkanberra-0.31" -D KA_MACHINE_ID="/usr/local/var/lib/dbus/machine-id" -D PIC -internal-isystem /usr/lib/llvm-14/lib/clang/14.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/12/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wwrite-strings -Wno-long-long -Wno-overlength-strings -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unused-result -fconst-strings -fdebug-compilation-dir=/rootdir/src -ferror-limit 19 -fgnuc-version=4.2.1 -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2022-12-30-182728-18487-1 -x c common.c
1/*-*- Mode: C; c-basic-offset: 8 -*-*/
2
3/***
4 This file is part of libkanberra.
5
6 Copyright 2008 Lennart Poettering
7
8 libkanberra is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as
10 published by the Free Software Foundation, either version 2.1 of the
11 License, or (at your option) any later version.
12
13 libkanberra is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public
19 License along with libkanberra. If not, see
20 <http://www.gnu.org/licenses/>.
21***/
22
23#ifdef HAVE_CONFIG_H1
24#include <config.h>
25#endif
26
27#include <stdarg.h>
28
29#include "kanberra.h"
30#include "common.h"
31#include "malloc.h"
32#include "driver.h"
33#include "proplist.h"
34#include "macro.h"
35#include "fork-detect.h"
36
37/**
38 * SECTION:kanberra
39 * @short_description: General libkanberra API
40 *
41 * libkanberra defines a simple abstract interface for playing event sounds.
42 *
43 * libkanberra relies on the XDG sound naming specification for
44 * identifying event sounds. On Unix/Linux the right sound to play is
45 * found via the mechanisms defined in the XDG sound themeing
46 * specification. On other systems the XDG sound name is translated to
47 * the native sound id for the operating system.
48 *
49 * An event sound is triggered via libkanberra by calling the
50 * ka_context_play() function on a previously created ka_context
51 * object. The ka_context_play() takes a list of key-value pairs that
52 * describe the event sound to generate as closely as possible. The
53 * most important property is %KA_PROP_EVENT_ID which defines the XDG
54 * sound name for the sound to play.
55 *
56 * libkanberra is not a generic event abstraction system. It's only
57 * purpose is playing sounds -- however in a very elaborate way. As
58 * much information about the context the sound is triggered from
59 * shall be supplied to the sound system as possible, so that it can
60 * replace the sound with some other kind of feedback for a11y
61 * cases. Also this additional information can be used to enhance user
62 * experience (e.g. by positioning sounds in space depending on the
63 * place on the screen the sound was triggered from, and similar
64 * uses).
65 *
66 * The set of properties defined for event sounds is extensible and
67 * shared with other audio systems, such as PulseAudio. Some of
68 * the properties that may be set are specific to an application, to a
69 * window, to an input event or to the media being played back.
70 *
71 * The user can attach a set of properties to the context itself,
72 * which is than automatically inherited by each sample being played
73 * back. (ka_context_change_props()).
74 *
75 * Some of the properties can be filled in by libkanberra or one of
76 * its backends automatically and thus need not be be filled in by the
77 * application (such as %KA_PROP_APPLICATION_PROCESS_ID and
78 * friends). However the application can always overwrite any of these
79 * implicit properties.
80 *
81 * libkanberra is thread-safe and OOM-safe (as far as the backend
82 * allows this). It is not async-signal safe.
83 *
84 * Most libkanberra functions return an integer that indicates success
85 * when 0 (%KA_SUCCESS) or an error when negative. In the latter case
86 * ka_strerror() can be used to convert this code into a human
87 * readable string.
88 *
89 * libkanberra property names need to be in 7bit ASCII, string
90 * property values UTF8.
91 *
92 * Optionally a libkanberra backend can support caching of sounds in a
93 * sound system. If this functionality is used, the latencies for
94 * event sound playback can be much smaller and fewer resources are
95 * needed to start playback. If a backend does not support cacheing,
96 * the respective functions will return an error code of
97 * %KA_ERROR_NOTSUPPORTED.
98 *
99 * It is highly recommended that the application sets the
100 * %KA_PROP_APPLICATION_NAME, %KA_PROP_APPLICATION_ID,
101 * %KA_PROP_APPLICATION_ICON_NAME/%KA_PROP_APPLICATION_ICON properties
102 * immediately after creating the ka_context, before calling
103 * ka_context_open() or ka_context_play().
104 *
105 * Its is highly recommended to pass at least %KA_PROP_EVENT_ID,
106 * %KA_PROP_EVENT_DESCRIPTION to ka_context_play() for each event
107 * sound generated. For sound events based on mouse inputs events
108 * %KA_PROP_EVENT_MOUSE_X, %KA_PROP_EVENT_MOUSE_Y, %KA_PROP_EVENT_MOUSE_HPOS,
109 * %KA_PROP_EVENT_MOUSE_VPOS, %KA_PROP_EVENT_MOUSE_BUTTON should be
110 * passed. For sound events attached to a widget on the screen, the
111 * %KA_PROP_WINDOW_xxx properties should be set.
112 *
113 *
114 */
115
116/**
117 * ka_context_create:
118 * @c: A pointer wheere to fill in the newly created context object.
119 *
120 * Create an (unconnected) context object. This call will not connect
121 * to the sound system, calling this function might even suceed if no
122 * working driver backend is available. To find out if one is
123 * available call ka_context_open().
124 *
125 * Returns: 0 on success, negative error code on error.
126 */
127
128int ka_context_create(ka_context **_c) {
129 ka_context *c;
130 int ret;
131 const char *d;
132
133 ka_return_val_if_fail(!ka_detect_fork(), KA_ERROR_FORKED)do { if ((__builtin_expect((!(!ka_detect_fork())),0))) { if (
ka_debug()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n"
, "!ka_detect_fork()" , "common.c", 133, __PRETTY_FUNCTION__)
; return (KA_ERROR_FORKED); } } while((0))
;
1
Assuming the condition is true
2
Taking false branch
3
Loop condition is false. Exiting loop
134 ka_return_val_if_fail(_c, KA_ERROR_INVALID)do { if ((__builtin_expect((!(_c)),0))) { if (ka_debug()) fprintf
(stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "_c"
, "common.c", 134, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID
); } } while((0))
;
4
Assuming '_c' is non-null
5
Taking false branch
6
Loop condition is false. Exiting loop
135
136 if (!(c = ka_new0(ka_context, 1)((ka_context*) calloc(1, (sizeof(ka_context)*(1))))))
7
Memory is allocated
8
Assuming 'c' is non-null
9
Taking false branch
137 return KA_ERROR_OOM;
138
139 if (!(c->mutex = ka_mutex_new())) {
10
Assuming field 'mutex' is null
11
Taking true branch
140 ka_context_destroy(c);
141 return KA_ERROR_OOM;
12
Potential leak of memory pointed to by 'c'
142 }
143
144 if ((ret = ka_proplist_create(&c->props)) < 0) {
145 ka_context_destroy(c);
146 return ret;
147 }
148
149 if ((d = getenv("KANBERRA_DRIVER"))) {
150 if ((ret = ka_context_set_driver(c, d)) < 0) {
151 ka_context_destroy(c);
152 return ret;
153 }
154 }
155
156 if ((d = getenv("KANBERRA_DEVICE"))) {
157 if ((ret = ka_context_change_device(c, d)) < 0) {
158 ka_context_destroy(c);
159 return ret;
160 }
161 }
162
163 *_c = c;
164 return KA_SUCCESS;
165}
166
167/**
168 * ka_context_destroy:
169 * @c: the context to destroy.
170 *
171 * Destroy a (connected or unconnected) context object.
172 *
173 * Returns: 0 on success, negative error code on error.
174 */
175int ka_context_destroy(ka_context *c) {
176 int ret = KA_SUCCESS;
177
178 ka_return_val_if_fail(!ka_detect_fork(), KA_ERROR_FORKED)do { if ((__builtin_expect((!(!ka_detect_fork())),0))) { if (
ka_debug()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n"
, "!ka_detect_fork()" , "common.c", 178, __PRETTY_FUNCTION__)
; return (KA_ERROR_FORKED); } } while((0))
;
179 ka_return_val_if_fail(c, KA_ERROR_INVALID)do { if ((__builtin_expect((!(c)),0))) { if (ka_debug()) fprintf
(stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "c"
, "common.c", 179, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID
); } } while((0))
;
180
181 /* There's no locking necessary here, because the application is
182 * broken anyway if it destructs this object in one thread and
183 * still is calling a method of it in another. */
184
185 if (c->opened)
186 ret = driver_destroy(c);
187
188 if (c->props)
189 ka_assert_se(ka_proplist_destroy(c->props) == KA_SUCCESS)do { if ((__builtin_expect((!(ka_proplist_destroy(c->props
) == KA_SUCCESS)),0))) { fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s(). Aborting.\n"
, "ka_proplist_destroy(c->props) == KA_SUCCESS" , "common.c"
, 189, __PRETTY_FUNCTION__); abort(); } } while ((0))
;
190
191 if (c->mutex)
192 ka_mutex_free(c->mutex);
193
194 ka_freefree(c->driver);
195 ka_freefree(c->device);
196 ka_freefree(c);
197
198 return ret;
199}
200
201/**
202 * ka_context_set_driver:
203 * @c: the context to change the backend driver for
204 * @driver: the backend driver to use (e.g. "alsa", "pulse", "null", ...)
205 *
206 * Specify the backend driver used. This function may not be called again after
207 * ka_context_open() suceeded. This function might suceed even when
208 * the specified driver backend is not available. Use
209 * ka_context_open() to find out whether the backend is available.
210 *
211 * Returns: 0 on success, negative error code on error.
212 */
213int ka_context_set_driver(ka_context *c, const char *driver) {
214 char *n;
215 int ret;
216
217 ka_return_val_if_fail(!ka_detect_fork(), KA_ERROR_FORKED)do { if ((__builtin_expect((!(!ka_detect_fork())),0))) { if (
ka_debug()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n"
, "!ka_detect_fork()" , "common.c", 217, __PRETTY_FUNCTION__)
; return (KA_ERROR_FORKED); } } while((0))
;
218 ka_return_val_if_fail(c, KA_ERROR_INVALID)do { if ((__builtin_expect((!(c)),0))) { if (ka_debug()) fprintf
(stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "c"
, "common.c", 218, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID
); } } while((0))
;
219 ka_mutex_lock(c->mutex);
220 ka_return_val_if_fail_unlock(!c->opened, KA_ERROR_STATE, c->mutex)do { if ((__builtin_expect((!(!c->opened)),0))) { if (ka_debug
()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n"
, "!c->opened" , "common.c", 220, __PRETTY_FUNCTION__); ka_mutex_unlock
(c->mutex); return (KA_ERROR_STATE); } } while((0))
;
221
222 if (!driver)
223 n = NULL((void*)0);
224 else if (!(n = ka_strdupstrdup(driver))) {
225 ret = KA_ERROR_OOM;
226 goto fail;
227 }
228
229 ka_freefree(c->driver);
230 c->driver = n;
231
232 ret = KA_SUCCESS;
233
234fail:
235 ka_mutex_unlock(c->mutex);
236
237 return ret;
238}
239
240/**
241 * ka_context_change_device:
242 * @c: the context to change the backend device for
243 * @device: the backend device to use, in a format that is specific to the backend.
244 *
245 * Specify the backend device to use. This function may be called not be called after
246 * ka_context_open() suceeded. This function might suceed even when
247 * the specified driver backend is not available. Use
248 * ka_context_open() to find out whether the backend is available
249 *
250 * Depending on the backend use this might or might not cause all
251 * currently playing event sounds to be moved to the new device..
252 *
253 * Returns: 0 on success, negative error code on error.
254 */
255int ka_context_change_device(ka_context *c, const char *device) {
256 char *n;
257 int ret;
258
259 ka_return_val_if_fail(!ka_detect_fork(), KA_ERROR_FORKED)do { if ((__builtin_expect((!(!ka_detect_fork())),0))) { if (
ka_debug()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n"
, "!ka_detect_fork()" , "common.c", 259, __PRETTY_FUNCTION__)
; return (KA_ERROR_FORKED); } } while((0))
;
260 ka_return_val_if_fail(c, KA_ERROR_INVALID)do { if ((__builtin_expect((!(c)),0))) { if (ka_debug()) fprintf
(stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "c"
, "common.c", 260, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID
); } } while((0))
;
261 ka_mutex_lock(c->mutex);
262
263 if (!device)
264 n = NULL((void*)0);
265 else if (!(n = ka_strdupstrdup(device))) {
266 ret = KA_ERROR_OOM;
267 goto fail;
268 }
269
270 ret = c->opened ? driver_change_device(c, n) : KA_SUCCESS;
271
272 if (ret == KA_SUCCESS) {
273 ka_freefree(c->device);
274 c->device = n;
275 } else
276 ka_freefree(n);
277
278fail:
279 ka_mutex_unlock(c->mutex);
280
281 return ret;
282}
283
284static int context_open_unlocked(ka_context *c) {
285 int ret;
286
287 ka_return_val_if_fail(!ka_detect_fork(), KA_ERROR_FORKED)do { if ((__builtin_expect((!(!ka_detect_fork())),0))) { if (
ka_debug()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n"
, "!ka_detect_fork()" , "common.c", 287, __PRETTY_FUNCTION__)
; return (KA_ERROR_FORKED); } } while((0))
;
288 ka_return_val_if_fail(c, KA_ERROR_INVALID)do { if ((__builtin_expect((!(c)),0))) { if (ka_debug()) fprintf
(stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "c"
, "common.c", 288, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID
); } } while((0))
;
289
290 if (c->opened)
291 return KA_SUCCESS;
292
293 if ((ret = driver_open(c)) == KA_SUCCESS)
294 c->opened = TRUE(!(0));
295
296 return ret;
297}
298
299/**
300 * ka_context_open:
301 * @c: the context to connect.
302 *
303 * Connect the context to the sound system. This call is implicitly
304 * called in ka_context_play() or ka_context_cache() if not called
305 * explicitly. It is recommended to initialize application properties
306 * with ka_context_change_props() before calling this function.
307 *
308 * Returns: 0 on success, negative error code on error.
309 */
310int ka_context_open(ka_context *c) {
311 int ret;
312
313 ka_return_val_if_fail(!ka_detect_fork(), KA_ERROR_FORKED)do { if ((__builtin_expect((!(!ka_detect_fork())),0))) { if (
ka_debug()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n"
, "!ka_detect_fork()" , "common.c", 313, __PRETTY_FUNCTION__)
; return (KA_ERROR_FORKED); } } while((0))
;
314 ka_return_val_if_fail(c, KA_ERROR_INVALID)do { if ((__builtin_expect((!(c)),0))) { if (ka_debug()) fprintf
(stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "c"
, "common.c", 314, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID
); } } while((0))
;
315 ka_mutex_lock(c->mutex);
316 ka_return_val_if_fail_unlock(!c->opened, KA_ERROR_STATE, c->mutex)do { if ((__builtin_expect((!(!c->opened)),0))) { if (ka_debug
()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n"
, "!c->opened" , "common.c", 316, __PRETTY_FUNCTION__); ka_mutex_unlock
(c->mutex); return (KA_ERROR_STATE); } } while((0))
;
317
318 ret = context_open_unlocked(c);
319
320 ka_mutex_unlock(c->mutex);
321
322 return ret;
323}
324
325/**
326 * ka_context_change_props:
327 * @c: the context to set the properties on.
328 * @...: the list of string pairs for the properties. Needs to be a NULL terminated list.
329 *
330 * Write one or more string properties to the context object. Requires
331 * final NULL sentinel. Properties set like this will be attached to
332 * both the client object of the sound server and to all event sounds
333 * played or cached. It is recommended to call this function at least
334 * once before calling ka_context_open(), so that the initial
335 * application properties are set properly before the initial
336 * connection to the sound system. This function can be called both
337 * before and after the ka_context_open() call. Properties that have
338 * already been set before will be overwritten.
339 *
340 * Returns: 0 on success, negative error code on error.
341 */
342
343int ka_context_change_props(ka_context *c, ...) {
344 va_list ap;
345 int ret;
346 ka_proplist *p = NULL((void*)0);
347
348 ka_return_val_if_fail(!ka_detect_fork(), KA_ERROR_FORKED)do { if ((__builtin_expect((!(!ka_detect_fork())),0))) { if (
ka_debug()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n"
, "!ka_detect_fork()" , "common.c", 348, __PRETTY_FUNCTION__)
; return (KA_ERROR_FORKED); } } while((0))
;
349 ka_return_val_if_fail(c, KA_ERROR_INVALID)do { if ((__builtin_expect((!(c)),0))) { if (ka_debug()) fprintf
(stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "c"
, "common.c", 349, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID
); } } while((0))
;
350
351 va_start(ap, c)__builtin_va_start(ap, c);
352 ret = ka_proplist_from_ap(&p, ap);
353 va_end(ap)__builtin_va_end(ap);
354
355 if (ret < 0)
356 return ret;
357
358 ret = ka_context_change_props_full(c, p);
359
360 ka_assert_se(ka_proplist_destroy(p) == 0)do { if ((__builtin_expect((!(ka_proplist_destroy(p) == 0)),0
))) { fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s(). Aborting.\n"
, "ka_proplist_destroy(p) == 0" , "common.c", 360, __PRETTY_FUNCTION__
); abort(); } } while ((0))
;
361
362 return ret;
363}
364
365/**
366 * ka_context_change_props_full:
367 * @c: the context to set the properties on.
368 * @p: the property list to set.
369 *
370 * Similar to ka_context_change_props(), but takes a ka_proplist
371 * instead of a variable list of properties. Can be used to set binary
372 * properties such as %KA_PROP_APPLICATION_ICON.
373 *
374 * Returns: 0 on success, negative error code on error.
375 */
376
377int ka_context_change_props_full(ka_context *c, ka_proplist *p) {
378 int ret;
379 ka_proplist *merged;
380
381 ka_return_val_if_fail(!ka_detect_fork(), KA_ERROR_FORKED)do { if ((__builtin_expect((!(!ka_detect_fork())),0))) { if (
ka_debug()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n"
, "!ka_detect_fork()" , "common.c", 381, __PRETTY_FUNCTION__)
; return (KA_ERROR_FORKED); } } while((0))
;
382 ka_return_val_if_fail(c, KA_ERROR_INVALID)do { if ((__builtin_expect((!(c)),0))) { if (ka_debug()) fprintf
(stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "c"
, "common.c", 382, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID
); } } while((0))
;
383 ka_return_val_if_fail(p, KA_ERROR_INVALID)do { if ((__builtin_expect((!(p)),0))) { if (ka_debug()) fprintf
(stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "p"
, "common.c", 383, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID
); } } while((0))
;
384
385 ka_mutex_lock(c->mutex);
386
387 if ((ret = ka_proplist_merge(&merged, c->props, p)) < 0)
388 goto finish;
389
390 ret = c->opened ? driver_change_props(c, p, merged) : KA_SUCCESS;
391
392 if (ret == KA_SUCCESS) {
393 ka_assert_se(ka_proplist_destroy(c->props) == KA_SUCCESS)do { if ((__builtin_expect((!(ka_proplist_destroy(c->props
) == KA_SUCCESS)),0))) { fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s(). Aborting.\n"
, "ka_proplist_destroy(c->props) == KA_SUCCESS" , "common.c"
, 393, __PRETTY_FUNCTION__); abort(); } } while ((0))
;
394 c->props = merged;
395 } else
396 ka_assert_se(ka_proplist_destroy(merged) == KA_SUCCESS)do { if ((__builtin_expect((!(ka_proplist_destroy(merged) == KA_SUCCESS
)),0))) { fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s(). Aborting.\n"
, "ka_proplist_destroy(merged) == KA_SUCCESS" , "common.c", 396
, __PRETTY_FUNCTION__); abort(); } } while ((0))
;
397
398finish:
399
400 ka_mutex_unlock(c->mutex);
401
402 return ret;
403}
404
405/**
406 * ka_context_play:
407 * @c: the context to play the event sound on
408 * @id: an integer id this sound can later be identified with when calling ka_context_cancel()
409 * @...: additional properties for this sound event.
410 *
411 * Play one event sound. id can be any numeric value which later can
412 * be used to cancel an event sound that is currently being
413 * played. You may use the same id twice or more times if you want to
414 * cancel multiple event sounds with a single ka_context_cancel() call
415 * at once. It is recommended to pass 0 for the id if the event sound
416 * shall never be canceled. If the requested sound is not cached in
417 * the server yet this call might result in the sample being uploaded
418 * temporarily or permanently (this may be controlled with %KA_PROP_KANBERRA_CACHE_CONTROL). This function will start playback
419 * in the background. It will not wait until playback
420 * completed. Depending on the backend used a sound that is started
421 * shortly before your application terminates might or might not continue to
422 * play after your application terminated. If you want to make sure
423 * that all sounds finish to play you need to wait synchronously for
424 * the callback function of ka_context_play_full() to be called before you
425 * terminate your application.
426 *
427 * The sample to play is identified by the %KA_PROP_EVENT_ID
428 * property. If it is already cached in the server the cached version
429 * is played. The properties passed in this call are merged with the
430 * properties supplied when the sample was cached (if applicable)
431 * and the context properties as set with ka_context_change_props().
432 *
433 * If %KA_PROP_EVENT_ID is not defined the sound file passed in the
434 * %KA_PROP_MEDIA_FILENAME is played.
435 *
436 * On Linux/Unix the right sound to play is determined according to
437 * %KA_PROP_EVENT_ID,
438 * %KA_PROP_APPLICATION_LANGUAGE/%KA_PROP_MEDIA_LANGUAGE, the system
439 * locale, %KA_PROP_KANBERRA_XDG_THEME_NAME and
440 * %KA_PROP_KANBERRA_XDG_THEME_OUTPUT_PROFILE, following the XDG Sound
441 * Theming Specification. On non-Unix systems the native event sound
442 * that matches the XDG sound name in %KA_PROP_EVENT_ID is played.
443 *
444 * Returns: 0 on success, negative error code on error.
445 */
446
447int ka_context_play(ka_context *c, uint32_t id, ...) {
448 int ret;
449 va_list ap;
450 ka_proplist *p = NULL((void*)0);
451
452 ka_return_val_if_fail(!ka_detect_fork(), KA_ERROR_FORKED)do { if ((__builtin_expect((!(!ka_detect_fork())),0))) { if (
ka_debug()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n"
, "!ka_detect_fork()" , "common.c", 452, __PRETTY_FUNCTION__)
; return (KA_ERROR_FORKED); } } while((0))
;
453 ka_return_val_if_fail(c, KA_ERROR_INVALID)do { if ((__builtin_expect((!(c)),0))) { if (ka_debug()) fprintf
(stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "c"
, "common.c", 453, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID
); } } while((0))
;
454
455 va_start(ap, id)__builtin_va_start(ap, id);
456 ret = ka_proplist_from_ap(&p, ap);
457 va_end(ap)__builtin_va_end(ap);
458
459 if (ret < 0)
460 return ret;
461
462 ret = ka_context_play_full(c, id, p, NULL((void*)0), NULL((void*)0));
463
464 ka_assert_se(ka_proplist_destroy(p) == 0)do { if ((__builtin_expect((!(ka_proplist_destroy(p) == 0)),0
))) { fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s(). Aborting.\n"
, "ka_proplist_destroy(p) == 0" , "common.c", 464, __PRETTY_FUNCTION__
); abort(); } } while ((0))
;
465
466 return ret;
467}
468
469/**
470 * ka_context_play_full:
471 * @c: the context to play the event sound on
472 * @id: an integer id this sound can be later be identified with when calling ka_context_cancel() or when the callback is called.
473 * @p: A property list of properties for this event sound
474 * @cb: A callback to call when this sound event sucessfully finished playing or when an error occured during playback.
475 *
476 * Play one event sound, and call the specified callback function when
477 * completed. See ka_finish_callback_t for the semantics the callback
478 * is called in. Also see ka_context_play().
479 *
480 * It is guaranteed that the callback is called exactly once if
481 * ka_context_play_full() returns KA_SUCCESS. You thus may safely pass
482 * allocated memory to the callback and assume that it is freed
483 * properly.
484 *
485 * Returns: 0 on success, negative error code on error.
486 */
487
488int ka_context_play_full(ka_context *c, uint32_t id, ka_proplist *p, ka_finish_callback_t cb, void *userdata) {
489 int ret;
490 const char *t;
491 ka_bool_t enabled = TRUE(!(0));
492
493 ka_return_val_if_fail(!ka_detect_fork(), KA_ERROR_FORKED)do { if ((__builtin_expect((!(!ka_detect_fork())),0))) { if (
ka_debug()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n"
, "!ka_detect_fork()" , "common.c", 493, __PRETTY_FUNCTION__)
; return (KA_ERROR_FORKED); } } while((0))
;
494 ka_return_val_if_fail(c, KA_ERROR_INVALID)do { if ((__builtin_expect((!(c)),0))) { if (ka_debug()) fprintf
(stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "c"
, "common.c", 494, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID
); } } while((0))
;
495 ka_return_val_if_fail(p, KA_ERROR_INVALID)do { if ((__builtin_expect((!(p)),0))) { if (ka_debug()) fprintf
(stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "p"
, "common.c", 495, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID
); } } while((0))
;
496 ka_return_val_if_fail(!userdata || cb, KA_ERROR_INVALID)do { if ((__builtin_expect((!(!userdata || cb)),0))) { if (ka_debug
()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n"
, "!userdata || cb" , "common.c", 496, __PRETTY_FUNCTION__); return
(KA_ERROR_INVALID); } } while((0))
;
497
498 ka_mutex_lock(c->mutex);
499
500 ka_return_val_if_fail_unlock(ka_proplist_contains(p, KA_PROP_EVENT_ID) ||do { if ((__builtin_expect((!(ka_proplist_contains(p, "event.id"
) || ka_proplist_contains(c->props, "event.id") || ka_proplist_contains
(p, "media.filename") || ka_proplist_contains(c->props, "media.filename"
))),0))) { if (ka_debug()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n"
, "ka_proplist_contains(p, KA_PROP_EVENT_ID) || ka_proplist_contains(c->props, KA_PROP_EVENT_ID) || ka_proplist_contains(p, KA_PROP_MEDIA_FILENAME) || ka_proplist_contains(c->props, KA_PROP_MEDIA_FILENAME)"
, "common.c", 503, __PRETTY_FUNCTION__); ka_mutex_unlock(c->
mutex); return (KA_ERROR_INVALID); } } while((0))
501 ka_proplist_contains(c->props, KA_PROP_EVENT_ID) ||do { if ((__builtin_expect((!(ka_proplist_contains(p, "event.id"
) || ka_proplist_contains(c->props, "event.id") || ka_proplist_contains
(p, "media.filename") || ka_proplist_contains(c->props, "media.filename"
))),0))) { if (ka_debug()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n"
, "ka_proplist_contains(p, KA_PROP_EVENT_ID) || ka_proplist_contains(c->props, KA_PROP_EVENT_ID) || ka_proplist_contains(p, KA_PROP_MEDIA_FILENAME) || ka_proplist_contains(c->props, KA_PROP_MEDIA_FILENAME)"
, "common.c", 503, __PRETTY_FUNCTION__); ka_mutex_unlock(c->
mutex); return (KA_ERROR_INVALID); } } while((0))
502 ka_proplist_contains(p, KA_PROP_MEDIA_FILENAME) ||do { if ((__builtin_expect((!(ka_proplist_contains(p, "event.id"
) || ka_proplist_contains(c->props, "event.id") || ka_proplist_contains
(p, "media.filename") || ka_proplist_contains(c->props, "media.filename"
))),0))) { if (ka_debug()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n"
, "ka_proplist_contains(p, KA_PROP_EVENT_ID) || ka_proplist_contains(c->props, KA_PROP_EVENT_ID) || ka_proplist_contains(p, KA_PROP_MEDIA_FILENAME) || ka_proplist_contains(c->props, KA_PROP_MEDIA_FILENAME)"
, "common.c", 503, __PRETTY_FUNCTION__); ka_mutex_unlock(c->
mutex); return (KA_ERROR_INVALID); } } while((0))
503 ka_proplist_contains(c->props, KA_PROP_MEDIA_FILENAME), KA_ERROR_INVALID, c->mutex)do { if ((__builtin_expect((!(ka_proplist_contains(p, "event.id"
) || ka_proplist_contains(c->props, "event.id") || ka_proplist_contains
(p, "media.filename") || ka_proplist_contains(c->props, "media.filename"
))),0))) { if (ka_debug()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n"
, "ka_proplist_contains(p, KA_PROP_EVENT_ID) || ka_proplist_contains(c->props, KA_PROP_EVENT_ID) || ka_proplist_contains(p, KA_PROP_MEDIA_FILENAME) || ka_proplist_contains(c->props, KA_PROP_MEDIA_FILENAME)"
, "common.c", 503, __PRETTY_FUNCTION__); ka_mutex_unlock(c->
mutex); return (KA_ERROR_INVALID); } } while((0))
;
504
505 ka_mutex_lock(c->props->mutex);
506 if ((t = ka_proplist_gets_unlocked(c->props, KA_PROP_KANBERRA_ENABLE"kanberra.enable")))
507 enabled = !ka_streq(t, "0")(strcmp((t),("0")) == 0);
508 ka_mutex_unlock(c->props->mutex);
509
510 ka_mutex_lock(p->mutex);
511 if ((t = ka_proplist_gets_unlocked(p, KA_PROP_KANBERRA_ENABLE"kanberra.enable")))
512 enabled = !ka_streq(t, "0")(strcmp((t),("0")) == 0);
513 ka_mutex_unlock(p->mutex);
514
515 ka_return_val_if_fail_unlock(enabled, KA_ERROR_DISABLED, c->mutex)do { if ((__builtin_expect((!(enabled)),0))) { if (ka_debug()
) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n"
, "enabled" , "common.c", 515, __PRETTY_FUNCTION__); ka_mutex_unlock
(c->mutex); return (KA_ERROR_DISABLED); } } while((0))
;
516
517 if ((ret = context_open_unlocked(c)) < 0)
518 goto finish;
519
520 ka_assert(c->opened)do { if ((__builtin_expect((!(c->opened)),0))) { fprintf(stderr
, "Assertion '%s' failed at %s:%u, function %s(). Aborting.\n"
, "c->opened" , "common.c", 520, __PRETTY_FUNCTION__); abort
(); } } while ((0))
;
521
522 ret = driver_play(c, id, p, cb, userdata);
523
524finish:
525
526 ka_mutex_unlock(c->mutex);
527
528 return ret;
529}
530
531/**
532 *
533 * ka_context_cancel:
534 * @c: the context to cancel the sounds on
535 * @id: the id that identify the sounds to cancel.
536 *
537 * Cancel one or more event sounds that have been started via
538 * ka_context_play(). If the sound was started with
539 * ka_context_play_full() and a callback function was passed this
540 * might cause this function to be called with %KA_ERROR_CANCELED as
541 * error code.
542 *
543 * Returns: 0 on success, negative error code on error.
544 */
545int ka_context_cancel(ka_context *c, uint32_t id) {
546 int ret;
547
548 ka_return_val_if_fail(!ka_detect_fork(), KA_ERROR_FORKED)do { if ((__builtin_expect((!(!ka_detect_fork())),0))) { if (
ka_debug()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n"
, "!ka_detect_fork()" , "common.c", 548, __PRETTY_FUNCTION__)
; return (KA_ERROR_FORKED); } } while((0))
;
549 ka_return_val_if_fail(c, KA_ERROR_INVALID)do { if ((__builtin_expect((!(c)),0))) { if (ka_debug()) fprintf
(stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "c"
, "common.c", 549, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID
); } } while((0))
;
550 ka_mutex_lock(c->mutex);
551 ka_return_val_if_fail_unlock(c->opened, KA_ERROR_STATE, c->mutex)do { if ((__builtin_expect((!(c->opened)),0))) { if (ka_debug
()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n"
, "c->opened" , "common.c", 551, __PRETTY_FUNCTION__); ka_mutex_unlock
(c->mutex); return (KA_ERROR_STATE); } } while((0))
;
552
553 ret = driver_cancel(c, id);
554
555 ka_mutex_unlock(c->mutex);
556
557 return ret;
558}
559
560/**
561 * ka_context_cache:
562 * @c: The context to use for uploading.
563 * @...: The properties for this event sound. Terminated with NULL.
564 *
565 * Upload the specified sample into the audio server and attach the
566 * specified properties to it. This function will only return after
567 * the sample upload was finished.
568 *
569 * The sound to cache is found with the same algorithm that is used to
570 * find the sounds for ka_context_play().
571 *
572 * If the backend doesn't support caching sound samples this function
573 * will return %KA_ERROR_NOTSUPPORTED.
574 *
575 * Returns: 0 on success, negative error code on error.
576 */
577
578int ka_context_cache(ka_context *c, ...) {
579 int ret;
580 va_list ap;
581 ka_proplist *p = NULL((void*)0);
582
583 ka_return_val_if_fail(!ka_detect_fork(), KA_ERROR_FORKED)do { if ((__builtin_expect((!(!ka_detect_fork())),0))) { if (
ka_debug()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n"
, "!ka_detect_fork()" , "common.c", 583, __PRETTY_FUNCTION__)
; return (KA_ERROR_FORKED); } } while((0))
;
584 ka_return_val_if_fail(c, KA_ERROR_INVALID)do { if ((__builtin_expect((!(c)),0))) { if (ka_debug()) fprintf
(stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "c"
, "common.c", 584, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID
); } } while((0))
;
585
586 va_start(ap, c)__builtin_va_start(ap, c);
587 ret = ka_proplist_from_ap(&p, ap);
588 va_end(ap)__builtin_va_end(ap);
589
590 if (ret < 0)
591 return ret;
592
593 ret = ka_context_cache_full(c, p);
594
595 ka_assert_se(ka_proplist_destroy(p) == 0)do { if ((__builtin_expect((!(ka_proplist_destroy(p) == 0)),0
))) { fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s(). Aborting.\n"
, "ka_proplist_destroy(p) == 0" , "common.c", 595, __PRETTY_FUNCTION__
); abort(); } } while ((0))
;
596
597 return ret;
598}
599
600/**
601 * ka_context_cache_full:
602 * @c: The context to use for uploading.
603 * @p: The property list for this event sound.
604 *
605 * Upload the specified sample into the server and attach the
606 * specified properties to it. Similar to ka_context_cache() but takes
607 * a ka_proplist instead of a variable number of arguments.
608 *
609 * If the backend doesn't support caching sound samples this function
610 * will return KA_ERROR_NOTSUPPORTED.
611 *
612 * Returns: 0 on success, negative error code on error.
613 */
614int ka_context_cache_full(ka_context *c, ka_proplist *p) {
615 int ret;
616
617 ka_return_val_if_fail(!ka_detect_fork(), KA_ERROR_FORKED)do { if ((__builtin_expect((!(!ka_detect_fork())),0))) { if (
ka_debug()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n"
, "!ka_detect_fork()" , "common.c", 617, __PRETTY_FUNCTION__)
; return (KA_ERROR_FORKED); } } while((0))
;
618 ka_return_val_if_fail(c, KA_ERROR_INVALID)do { if ((__builtin_expect((!(c)),0))) { if (ka_debug()) fprintf
(stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "c"
, "common.c", 618, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID
); } } while((0))
;
619 ka_return_val_if_fail(p, KA_ERROR_INVALID)do { if ((__builtin_expect((!(p)),0))) { if (ka_debug()) fprintf
(stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "p"
, "common.c", 619, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID
); } } while((0))
;
620
621 ka_mutex_lock(c->mutex);
622
623 ka_return_val_if_fail_unlock(ka_proplist_contains(p, KA_PROP_EVENT_ID) ||do { if ((__builtin_expect((!(ka_proplist_contains(p, "event.id"
) || ka_proplist_contains(c->props, "event.id"))),0))) { if
(ka_debug()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n"
, "ka_proplist_contains(p, KA_PROP_EVENT_ID) || ka_proplist_contains(c->props, KA_PROP_EVENT_ID)"
, "common.c", 624, __PRETTY_FUNCTION__); ka_mutex_unlock(c->
mutex); return (KA_ERROR_INVALID); } } while((0))
624 ka_proplist_contains(c->props, KA_PROP_EVENT_ID), KA_ERROR_INVALID, c->mutex)do { if ((__builtin_expect((!(ka_proplist_contains(p, "event.id"
) || ka_proplist_contains(c->props, "event.id"))),0))) { if
(ka_debug()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n"
, "ka_proplist_contains(p, KA_PROP_EVENT_ID) || ka_proplist_contains(c->props, KA_PROP_EVENT_ID)"
, "common.c", 624, __PRETTY_FUNCTION__); ka_mutex_unlock(c->
mutex); return (KA_ERROR_INVALID); } } while((0))
;
625
626 if ((ret = context_open_unlocked(c)) < 0)
627 goto finish;
628
629 ka_assert(c->opened)do { if ((__builtin_expect((!(c->opened)),0))) { fprintf(stderr
, "Assertion '%s' failed at %s:%u, function %s(). Aborting.\n"
, "c->opened" , "common.c", 629, __PRETTY_FUNCTION__); abort
(); } } while ((0))
;
630
631 ret = driver_cache(c, p);
632
633finish:
634
635 ka_mutex_unlock(c->mutex);
636
637 return ret;
638}
639
640/**
641 * ka_strerror:
642 * @code: Numerical error code as returned by a libkanberra API function
643 *
644 * Converts a numerical error code as returned by most libkanberra API functions into a human readable error string.
645 *
646 * Returns: a human readable error string.
647 */
648const char *ka_strerror(int code) {
649
650 const char * const error_table[-_KA_ERROR_MAX] = {
651 [-KA_SUCCESS] = "Success",
652 [-KA_ERROR_NOTSUPPORTED] = "Operation not supported",
653 [-KA_ERROR_INVALID] = "Invalid argument",
654 [-KA_ERROR_STATE] = "Invalid state",
655 [-KA_ERROR_OOM] = "Out of memory",
656 [-KA_ERROR_NODRIVER] = "No such driver",
657 [-KA_ERROR_SYSTEM] = "System error",
658 [-KA_ERROR_CORRUPT] = "File or data corrupt",
659 [-KA_ERROR_TOOBIG] = "File or data too large",
660 [-KA_ERROR_NOTFOUND] = "File or data not found",
661 [-KA_ERROR_DESTROYED] = "Destroyed",
662 [-KA_ERROR_CANCELED] = "Canceled",
663 [-KA_ERROR_NOTAVAILABLE] = "Not available",
664 [-KA_ERROR_ACCESS] = "Access forbidden",
665 [-KA_ERROR_IO] = "IO error",
666 [-KA_ERROR_INTERNAL] = "Internal error",
667 [-KA_ERROR_DISABLED] = "Sound disabled",
668 [-KA_ERROR_FORKED] = "Process forked",
669 [-KA_ERROR_DISCONNECTED] = "Disconnected"
670 };
671
672 ka_return_val_if_fail(code <= 0, NULL)do { if ((__builtin_expect((!(code <= 0)),0))) { if (ka_debug
()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n"
, "code <= 0" , "common.c", 672, __PRETTY_FUNCTION__); return
(((void*)0)); } } while((0))
;
673 ka_return_val_if_fail(code > _KA_ERROR_MAX, NULL)do { if ((__builtin_expect((!(code > _KA_ERROR_MAX)),0))) {
if (ka_debug()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n"
, "code > _KA_ERROR_MAX" , "common.c", 673, __PRETTY_FUNCTION__
); return (((void*)0)); } } while((0))
;
674
675 return error_table[-code];
676}
677
678/* Not exported */
679int ka_parse_cache_control(ka_cache_control_t *control, const char *c) {
680 ka_return_val_if_fail(control, KA_ERROR_INVALID)do { if ((__builtin_expect((!(control)),0))) { if (ka_debug()
) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n"
, "control" , "common.c", 680, __PRETTY_FUNCTION__); return (
KA_ERROR_INVALID); } } while((0))
;
681 ka_return_val_if_fail(c, KA_ERROR_INVALID)do { if ((__builtin_expect((!(c)),0))) { if (ka_debug()) fprintf
(stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "c"
, "common.c", 681, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID
); } } while((0))
;
682
683 if (ka_streq(c, "never")(strcmp((c),("never")) == 0))
684 *control = KA_CACHE_CONTROL_NEVER;
685 else if (ka_streq(c, "permanent")(strcmp((c),("permanent")) == 0))
686 *control = KA_CACHE_CONTROL_PERMANENT;
687 else if (ka_streq(c, "volatile")(strcmp((c),("volatile")) == 0))
688 *control = KA_CACHE_CONTROL_VOLATILE;
689 else
690 return KA_ERROR_INVALID;
691
692 return KA_SUCCESS;
693}
694
695/**
696 * ka_context_playing:
697 * @c: the context to check if sound is still playing
698 * @id: the id that identify the sounds to check
699 * @playing: a pointer to a boolean that will be updated with the play status
700 *
701 * Check if at least one sound with the specified id is still
702 * playing. Returns 0 in *playing if no sound with this id is playing
703 * anymore or non-zero if there is at least one playing.
704 *
705 * Returns: 0 on success, negative error code on error.
706 * Since: 0.16
707 */
708int ka_context_playing(ka_context *c, uint32_t id, int *playing) {
709 int ret;
710
711 ka_return_val_if_fail(!ka_detect_fork(), KA_ERROR_FORKED)do { if ((__builtin_expect((!(!ka_detect_fork())),0))) { if (
ka_debug()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n"
, "!ka_detect_fork()" , "common.c", 711, __PRETTY_FUNCTION__)
; return (KA_ERROR_FORKED); } } while((0))
;
712 ka_return_val_if_fail(c, KA_ERROR_INVALID)do { if ((__builtin_expect((!(c)),0))) { if (ka_debug()) fprintf
(stderr, "Assertion '%s' failed at %s:%u, function %s().\n", "c"
, "common.c", 712, __PRETTY_FUNCTION__); return (KA_ERROR_INVALID
); } } while((0))
;
713 ka_return_val_if_fail(playing, KA_ERROR_INVALID)do { if ((__builtin_expect((!(playing)),0))) { if (ka_debug()
) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n"
, "playing" , "common.c", 713, __PRETTY_FUNCTION__); return (
KA_ERROR_INVALID); } } while((0))
;
714 ka_mutex_lock(c->mutex);
715 ka_return_val_if_fail_unlock(c->opened, KA_ERROR_STATE, c->mutex)do { if ((__builtin_expect((!(c->opened)),0))) { if (ka_debug
()) fprintf(stderr, "Assertion '%s' failed at %s:%u, function %s().\n"
, "c->opened" , "common.c", 715, __PRETTY_FUNCTION__); ka_mutex_unlock
(c->mutex); return (KA_ERROR_STATE); } } while((0))
;
716
717 ret = driver_playing(c, id, playing);
718
719 ka_mutex_unlock(c->mutex);
720
721 return ret;
722}