Fix [theoretically possible] memory corruption.
[jackdbus.git] / dbus / device_reservation.c
blob4320c2c0a7d285274cb2a5212c483206724a3065
1 /*
2 Copyright (C) 2009 Grame
3 Copyright (C) 2024 Nedko Arnaudov
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include <string.h>
21 #include <unistd.h>
22 #include <errno.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <assert.h>
26 #include <stdint.h>
28 #include "reserve.h"
29 #include "device_reservation.h"
30 #include "jack/control.h"
32 #define DEVICE_MAX 2
34 /* string like "Audio2", "Midi5" or "Video3" */
35 #define MAX_DEVICE_NAME 63
37 typedef struct reserved_audio_device {
39 char device_name[MAX_DEVICE_NAME+1];
40 rd_device * reserved_device;
42 } reserved_audio_device;
44 static DBusConnection* gConnection = NULL;
45 static reserved_audio_device gReservedDevice[DEVICE_MAX];
46 static int gReserveCount = 0;
48 int device_reservation_init(void)
50 DBusError error;
51 dbus_error_init(&error);
53 if (!(gConnection = dbus_bus_get(DBUS_BUS_SESSION, &error))) {
54 jack_error("Failed to connect to session bus for device reservation: %s\n", error.message);
55 return -1;
58 jack_info("audio_reservation_init");
59 return 0;
62 int device_reservation_finish(void)
64 if (gConnection) {
65 dbus_connection_unref(gConnection);
66 gConnection = NULL;
67 jack_info("audio_reservation_finish");
69 return 0;
72 bool device_reservation_acquire(const char * device_name)
74 DBusError error;
75 int ret;
77 // Open DBus connection first time
78 if (gReserveCount == 0) {
79 if (device_reservation_init() != 0) {
80 return false;
84 assert(gReserveCount < DEVICE_MAX);
86 if (gReserveCount != 0) {
87 jack_error("Ignoring reservation for more than one device (acquire)");
88 return false;
91 strncpy(gReservedDevice[gReserveCount].device_name, device_name, MAX_DEVICE_NAME);
92 if (strcmp(gReservedDevice[gReserveCount].device_name, device_name) != 0)
94 jack_error("Ignoring reservation for device with too long name");
95 return false;
98 dbus_error_init(&error);
100 if ((ret= rd_acquire(
101 &gReservedDevice[gReserveCount].reserved_device,
102 gConnection,
103 device_name,
104 "Jack audio server",
105 INT32_MAX,
106 NULL,
107 &error)) < 0) {
109 jack_error("Failed to acquire device name : %s error : %s", device_name, (error.message ? error.message : strerror(-ret)));
110 dbus_error_free(&error);
111 return false;
114 gReserveCount++;
115 jack_info("Acquire audio card %s", device_name);
116 return true;
119 void device_reservation_release(const char * device_name)
121 int i;
123 // Look for corresponding reserved device
124 for (i = 0; i < DEVICE_MAX; i++) {
125 if (strcmp(gReservedDevice[i].device_name, device_name) == 0)
126 break;
129 if (i < DEVICE_MAX) {
130 jack_info("Released audio card %s", device_name);
131 rd_release(gReservedDevice[i].reserved_device);
132 } else {
133 jack_error("Audio card %s not found!!", device_name);
136 // Close DBus connection last time
137 gReserveCount--;
138 if (gReserveCount == 0)
139 device_reservation_finish();
142 void device_reservation_loop(void)
144 if (gConnection != NULL) {
145 dbus_connection_read_write_dispatch (gConnection, 200);