1 /*
2 Copyright (C) 2009 Grame
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16
17 */
18
19 #include <string.h>
20 #include <unistd.h>
21 #include <errno.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <assert.h>
25 #include <stdint.h>
26
27 #include "reserve.h"
28 #include "audio_reserve.h"
29 #include "jack/control.h"
30
31 #define DEVICE_MAX 2
32
33 typedef struct reserved_audio_device {
34
35 char device_name[64];
36 rd_device * reserved_device;
37
38 } reserved_audio_device;
39
40 static DBusConnection* gConnection = NULL;
41 static reserved_audio_device gReservedDevice[DEVICE_MAX];
42 static int gReserveCount = 0;
43
audio_reservation_init()44 SERVER_EXPORT int audio_reservation_init()
45 {
46 DBusError error;
47 dbus_error_init(&error);
48
49 if (!(gConnection = dbus_bus_get(DBUS_BUS_SESSION, &error))) {
50 jack_error("Failed to connect to session bus for device reservation: %s\n", error.message);
51 jack_info("To bypass device reservation via session bus, set JACK_NO_AUDIO_RESERVATION=1 prior to starting jackd.\n");
52 return -1;
53 }
54
55 jack_info("audio_reservation_init");
56 return 0;
57 }
58
audio_reservation_finish()59 SERVER_EXPORT int audio_reservation_finish()
60 {
61 if (gConnection) {
62 dbus_connection_unref(gConnection);
63 gConnection = NULL;
64 jack_info("audio_reservation_finish");
65 }
66 return 0;
67 }
68
audio_acquire(const char * device_name)69 SERVER_EXPORT bool audio_acquire(const char * device_name)
70 {
71 DBusError error;
72 int ret;
73
74 // Open DBus connection first time
75 if (gReserveCount == 0) {
76 if (audio_reservation_init() != 0) {
77 return false;
78 }
79 }
80
81 assert(gReserveCount < DEVICE_MAX);
82
83 dbus_error_init(&error);
84
85 if ((ret= rd_acquire(
86 &gReservedDevice[gReserveCount].reserved_device,
87 gConnection,
88 device_name,
89 "Jack audio server",
90 INT32_MAX,
91 NULL,
92 &error)) < 0) {
93
94 jack_error("Failed to acquire device name : %s error : %s", device_name, (error.message ? error.message : strerror(-ret)));
95 dbus_error_free(&error);
96 return false;
97 }
98
99 strcpy(gReservedDevice[gReserveCount].device_name, device_name);
100 gReserveCount++;
101 jack_info("Acquire audio card %s", device_name);
102 return true;
103 }
104
audio_release(const char * device_name)105 SERVER_EXPORT void audio_release(const char * device_name)
106 {
107 int i;
108
109 // Look for corresponding reserved device
110 for (i = 0; i < DEVICE_MAX; i++) {
111 if (strcmp(gReservedDevice[i].device_name, device_name) == 0)
112 break;
113 }
114
115 if (i < DEVICE_MAX) {
116 jack_info("Released audio card %s", device_name);
117 rd_release(gReservedDevice[i].reserved_device);
118 } else {
119 jack_error("Audio card %s not found!!", device_name);
120 }
121
122 // Close DBus connection last time
123 gReserveCount--;
124 if (gReserveCount == 0)
125 audio_reservation_finish();
126 }
127
audio_reserve_loop()128 SERVER_EXPORT void audio_reserve_loop()
129 {
130 if (gConnection != NULL) {
131 dbus_connection_read_write_dispatch (gConnection, 200);
132 }
133 }
134
135