mirror of
https://github.com/ZDoom/fluidsynth.git
synced 2025-04-22 07:30:50 +00:00
D-Bus and rtkit support
This commit is contained in:
parent
a4977b83d6
commit
6c0ef45e0e
5 changed files with 478 additions and 4 deletions
|
@ -160,6 +160,26 @@ PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.6.5 gthread-2.0 >= 2.6.5)
|
|||
AC_SUBST(GLIB_CFLAGS)
|
||||
AC_SUBST(GLIB_LIBS)
|
||||
|
||||
dnl - Check for DBUS support
|
||||
|
||||
AC_ARG_ENABLE(dbus-support, AS_HELP_STRING([--disable-dbus-support],
|
||||
[Do not compile with support for D-Bus (default=auto)]),
|
||||
enable_dbus_support=$enableval, enable_dbus_support="yes")
|
||||
|
||||
if test "x$enable_dbus_support" != "xno"; then
|
||||
PKG_CHECK_MODULES(DBUS, dbus-1 >= 1.0.0, DBUS_SUPPORT=1, DBUS_SUPPORT=0)
|
||||
else
|
||||
DBUS_SUPPORT=0
|
||||
fi
|
||||
|
||||
if test "$DBUS_SUPPORT" = "1"; then
|
||||
AC_DEFINE(DBUS_SUPPORT, 1, [Define to enable D-Bus support])
|
||||
fi
|
||||
AM_CONDITIONAL(DBUS_SUPPORT, test "$DBUS_SUPPORT" = "1")
|
||||
AC_SUBST(DBUS_CFLAGS)
|
||||
AC_SUBST(DBUS_LIBS)
|
||||
|
||||
|
||||
dnl Check for libsndfile support
|
||||
|
||||
AC_ARG_ENABLE(libsndfile-support, AS_HELP_STRING([--disable-libsndfile-support],
|
||||
|
@ -205,6 +225,7 @@ if test "x${enable_aufile_support}" != "xno"; then
|
|||
AC_DEFINE(AUFILE_SUPPORT, 1, [Define to activate sound output to files])
|
||||
fi
|
||||
|
||||
|
||||
dnl - Check for PulseAudio support
|
||||
|
||||
AC_ARG_ENABLE(pulse-support, AS_HELP_STRING([--disable-pulse-support],
|
||||
|
@ -463,6 +484,12 @@ else
|
|||
echo "libsndfile: no (raw audio file rendering only)"
|
||||
fi
|
||||
|
||||
if test "${DBUS_SUPPORT}" = "1"; then
|
||||
echo "D-Bus: yes"
|
||||
else
|
||||
echo "D-Bus: no"
|
||||
fi
|
||||
|
||||
if test "${PULSE_SUPPORT}" = "1"; then
|
||||
echo "PulseAudio: yes"
|
||||
else
|
||||
|
|
|
@ -17,6 +17,10 @@ if COREMIDI_SUPPORT
|
|||
fluid_coremidi = fluid_coremidi.c
|
||||
endif
|
||||
|
||||
if DBUS_SUPPORT
|
||||
fluid_rtkit = fluid_rtkit.c
|
||||
endif
|
||||
|
||||
if JACK_SUPPORT
|
||||
fluid_jack = fluid_jack.c
|
||||
endif
|
||||
|
@ -67,6 +71,7 @@ libfluidsynth_la_SOURCES = \
|
|||
$(fluid_pulse) \
|
||||
$(fluid_windows) \
|
||||
$(fluid_dart) \
|
||||
$(fluid_rtkit) \
|
||||
fluid_adriver.c \
|
||||
fluid_adriver.h \
|
||||
fluid_chan.c \
|
||||
|
@ -126,12 +131,13 @@ libfluidsynth_la_SOURCES = \
|
|||
|
||||
INCLUDES = -I$(top_srcdir)/include $(LASH_CFLAGS) $(LADCCA_CFLAGS) \
|
||||
$(READLINE_CFLAGS) $(JACK_CFLAGS) $(ALSA_CFLAGS) $(PULSE_CFLAGS) \
|
||||
$(PORTAUDIO_CFLAGS) $(DART_CFLAGS) $(GLIB_CFLAGS) $(LIBSNDFILE_CFLAGS)
|
||||
$(PORTAUDIO_CFLAGS) $(DART_CFLAGS) $(GLIB_CFLAGS) $(LIBSNDFILE_CFLAGS) \
|
||||
$(DBUS_CFLAGS)
|
||||
|
||||
libfluidsynth_la_LIBADD = $(LIBFLUID_LIBS) $(LASH_LIBS) $(LADCCA_LIBS) \
|
||||
$(READLINE_LIBS) $(COREAUDIO_LIBS) $(COREMIDI_LIBS) $(JACK_LIBS) \
|
||||
$(ALSA_LIBS) $(PULSE_LIBS) $(PORTAUDIO_LIBS) $(DART_LIBS) \
|
||||
$(GLIB_LIBS) $(LIBSNDFILE_LIBS)
|
||||
$(GLIB_LIBS) $(LIBSNDFILE_LIBS) $(DBUS_LIBS)
|
||||
|
||||
libfluidsynth_la_LDFLAGS = \
|
||||
-version-info @LT_VERSION_INFO@ \
|
||||
|
|
366
fluidsynth/src/fluid_rtkit.c
Normal file
366
fluidsynth/src/fluid_rtkit.c
Normal file
|
@ -0,0 +1,366 @@
|
|||
/*-*- Mode: C; c-basic-offset: 8 -*-*/
|
||||
|
||||
/***
|
||||
Copyright 2009 Lennart Poettering
|
||||
Copyright 2010 David Henningsson
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation files
|
||||
(the "Software"), to deal in the Software without restriction,
|
||||
including without limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
***/
|
||||
|
||||
#include "fluidsynth_priv.h"
|
||||
|
||||
#ifdef DBUS_SUPPORT
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "fluid_rtkit.h"
|
||||
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
|
||||
static pid_t _gettid(void) {
|
||||
return (pid_t) syscall(SYS_gettid);
|
||||
}
|
||||
|
||||
static int translate_error(const char *name) {
|
||||
if (strcmp(name, DBUS_ERROR_NO_MEMORY) == 0)
|
||||
return -ENOMEM;
|
||||
if (strcmp(name, DBUS_ERROR_SERVICE_UNKNOWN) == 0 ||
|
||||
strcmp(name, DBUS_ERROR_NAME_HAS_NO_OWNER) == 0)
|
||||
return -ENOENT;
|
||||
if (strcmp(name, DBUS_ERROR_ACCESS_DENIED) == 0 ||
|
||||
strcmp(name, DBUS_ERROR_AUTH_FAILED) == 0)
|
||||
return -EACCES;
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static long long rtkit_get_int_property(DBusConnection *connection, const char* propname, long long* propval) {
|
||||
DBusMessage *m = NULL, *r = NULL;
|
||||
DBusMessageIter iter, subiter;
|
||||
dbus_int64_t i64;
|
||||
dbus_int32_t i32;
|
||||
DBusError error;
|
||||
int current_type;
|
||||
long long ret;
|
||||
const char * interfacestr = "org.freedesktop.RealtimeKit1";
|
||||
|
||||
dbus_error_init(&error);
|
||||
|
||||
if (!(m = dbus_message_new_method_call(
|
||||
RTKIT_SERVICE_NAME,
|
||||
RTKIT_OBJECT_PATH,
|
||||
"org.freedesktop.DBus.Properties",
|
||||
"Get"))) {
|
||||
ret = -ENOMEM;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (!dbus_message_append_args(
|
||||
m,
|
||||
DBUS_TYPE_STRING, &interfacestr,
|
||||
DBUS_TYPE_STRING, &propname,
|
||||
DBUS_TYPE_INVALID)) {
|
||||
ret = -ENOMEM;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (!(r = dbus_connection_send_with_reply_and_block(connection, m, -1, &error))) {
|
||||
ret = translate_error(error.name);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (dbus_set_error_from_message(&error, r)) {
|
||||
ret = translate_error(error.name);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
ret = -EBADMSG;
|
||||
dbus_message_iter_init(r, &iter);
|
||||
while ((current_type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID) {
|
||||
|
||||
if (current_type == DBUS_TYPE_VARIANT) {
|
||||
dbus_message_iter_recurse(&iter, &subiter);
|
||||
|
||||
while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID) {
|
||||
|
||||
if (current_type == DBUS_TYPE_INT32) {
|
||||
dbus_message_iter_get_basic(&subiter, &i32);
|
||||
*propval = i32;
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
if (current_type == DBUS_TYPE_INT64) {
|
||||
dbus_message_iter_get_basic(&subiter, &i64);
|
||||
*propval = i64;
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
dbus_message_iter_next (&subiter);
|
||||
}
|
||||
}
|
||||
dbus_message_iter_next (&iter);
|
||||
}
|
||||
|
||||
finish:
|
||||
|
||||
if (m)
|
||||
dbus_message_unref(m);
|
||||
|
||||
if (r)
|
||||
dbus_message_unref(r);
|
||||
|
||||
dbus_error_free(&error);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int rtkit_get_max_realtime_priority(DBusConnection *connection) {
|
||||
long long retval;
|
||||
int err;
|
||||
|
||||
err = rtkit_get_int_property(connection, "MaxRealtimePriority", &retval);
|
||||
return err < 0 ? err : retval;
|
||||
}
|
||||
|
||||
int rtkit_get_min_nice_level(DBusConnection *connection, int* min_nice_level) {
|
||||
long long retval;
|
||||
int err;
|
||||
|
||||
err = rtkit_get_int_property(connection, "MinNiceLevel", &retval);
|
||||
if (err >= 0)
|
||||
*min_nice_level = retval;
|
||||
return err;
|
||||
}
|
||||
|
||||
long long rtkit_get_rttime_nsec_max(DBusConnection *connection) {
|
||||
long long retval;
|
||||
int err;
|
||||
|
||||
err = rtkit_get_int_property(connection, "RTTimeNSecMax", &retval);
|
||||
return err < 0 ? err : retval;
|
||||
}
|
||||
|
||||
int rtkit_make_realtime(DBusConnection *connection, pid_t thread, int priority) {
|
||||
DBusMessage *m = NULL, *r = NULL;
|
||||
dbus_uint64_t u64;
|
||||
dbus_uint32_t u32;
|
||||
DBusError error;
|
||||
int ret;
|
||||
|
||||
|
||||
dbus_error_init(&error);
|
||||
|
||||
if (thread == 0)
|
||||
thread = _gettid();
|
||||
|
||||
if (!(m = dbus_message_new_method_call(
|
||||
RTKIT_SERVICE_NAME,
|
||||
RTKIT_OBJECT_PATH,
|
||||
"org.freedesktop.RealtimeKit1",
|
||||
"MakeThreadRealtime"))) {
|
||||
ret = -ENOMEM;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
u64 = (dbus_uint64_t) thread;
|
||||
u32 = (dbus_uint32_t) priority;
|
||||
|
||||
if (!dbus_message_append_args(
|
||||
m,
|
||||
DBUS_TYPE_UINT64, &u64,
|
||||
DBUS_TYPE_UINT32, &u32,
|
||||
DBUS_TYPE_INVALID)) {
|
||||
ret = -ENOMEM;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (!(r = dbus_connection_send_with_reply_and_block(connection, m, -1, &error))) {
|
||||
ret = translate_error(error.name);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
|
||||
if (dbus_set_error_from_message(&error, r)) {
|
||||
ret = translate_error(error.name);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
finish:
|
||||
|
||||
if (m)
|
||||
dbus_message_unref(m);
|
||||
|
||||
if (r)
|
||||
dbus_message_unref(r);
|
||||
|
||||
dbus_error_free(&error);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int rtkit_make_high_priority(DBusConnection *connection, pid_t thread, int nice_level) {
|
||||
DBusMessage *m = NULL, *r = NULL;
|
||||
dbus_uint64_t u64;
|
||||
dbus_int32_t s32;
|
||||
DBusError error;
|
||||
int ret;
|
||||
|
||||
dbus_error_init(&error);
|
||||
|
||||
if (thread == 0)
|
||||
thread = _gettid();
|
||||
|
||||
if (!(m = dbus_message_new_method_call(
|
||||
RTKIT_SERVICE_NAME,
|
||||
RTKIT_OBJECT_PATH,
|
||||
"org.freedesktop.RealtimeKit1",
|
||||
"MakeThreadHighPriority"))) {
|
||||
ret = -ENOMEM;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
u64 = (dbus_uint64_t) thread;
|
||||
s32 = (dbus_int32_t) nice_level;
|
||||
|
||||
if (!dbus_message_append_args(
|
||||
m,
|
||||
DBUS_TYPE_UINT64, &u64,
|
||||
DBUS_TYPE_INT32, &s32,
|
||||
DBUS_TYPE_INVALID)) {
|
||||
ret = -ENOMEM;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (!(r = dbus_connection_send_with_reply_and_block(connection, m, -1, &error))) {
|
||||
ret = translate_error(error.name);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
|
||||
if (dbus_set_error_from_message(&error, r)) {
|
||||
ret = translate_error(error.name);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
finish:
|
||||
|
||||
if (m)
|
||||
dbus_message_unref(m);
|
||||
|
||||
if (r)
|
||||
dbus_message_unref(r);
|
||||
|
||||
dbus_error_free(&error);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int rtkit_make_realtime(DBusConnection *connection, pid_t thread, int priority) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
int rtkit_make_high_priority(DBusConnection *connection, pid_t thread, int nice_level) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
int rtkit_get_max_realtime_priority(DBusConnection *connection) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
int rtkit_get_min_nice_level(DBusConnection *connection, int* min_nice_level) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
long long rtkit_get_rttime_nsec_max(DBusConnection *connection) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef RLIMIT_RTTIME
|
||||
# define RLIMIT_RTTIME 15
|
||||
#endif
|
||||
|
||||
int fluid_rtkit_make_realtime(pid_t thread, int priority) {
|
||||
DBusConnection *conn = NULL;
|
||||
DBusError error;
|
||||
int max_prio, res;
|
||||
long long max_rttime;
|
||||
struct rlimit old_limit, new_limit;
|
||||
|
||||
/* Initialize system bus connection */
|
||||
dbus_error_init(&error);
|
||||
conn = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
|
||||
if (conn == NULL) {
|
||||
res = translate_error(error.name);
|
||||
dbus_error_free(&error);
|
||||
return res;
|
||||
}
|
||||
dbus_error_free(&error);
|
||||
|
||||
/* Make sure we don't fail by wanting too much */
|
||||
max_prio = rtkit_get_max_realtime_priority(conn);
|
||||
if (max_prio < 0)
|
||||
return max_prio;
|
||||
if (priority >= max_prio)
|
||||
priority = max_prio;
|
||||
|
||||
/* Enforce RLIMIT_RTTIME, also a must for obtaining rt prio through rtkit */
|
||||
max_rttime = rtkit_get_rttime_nsec_max(conn);
|
||||
if (max_rttime < 0)
|
||||
return max_rttime;
|
||||
new_limit.rlim_cur = new_limit.rlim_max = max_rttime;
|
||||
if (getrlimit(RLIMIT_RTTIME, &old_limit) < 0)
|
||||
return -1;
|
||||
if (setrlimit(RLIMIT_RTTIME, &new_limit) < 0)
|
||||
return -1;
|
||||
|
||||
/* Finally, let's try */
|
||||
res = rtkit_make_realtime(conn, thread, priority);
|
||||
if (res != 0) {
|
||||
setrlimit(RLIMIT_RTTIME, &old_limit);
|
||||
}
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
60
fluidsynth/src/fluid_rtkit.h
Normal file
60
fluidsynth/src/fluid_rtkit.h
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*-*- Mode: C; c-basic-offset: 8 -*-*/
|
||||
|
||||
#ifndef foortkithfoo
|
||||
#define foortkithfoo
|
||||
|
||||
/***
|
||||
Copyright 2009 Lennart Poettering
|
||||
Copyright 2010 David Henningsson <diwic@ubuntu.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation files
|
||||
(the "Software"), to deal in the Software without restriction,
|
||||
including without limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
***/
|
||||
|
||||
#ifdef DBUS_SUPPORT
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <dbus/dbus.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* This is the reference implementation for a client for
|
||||
* RealtimeKit. You don't have to use this, but if do, just copy these
|
||||
* sources into your repository */
|
||||
|
||||
#define RTKIT_SERVICE_NAME "org.freedesktop.RealtimeKit1"
|
||||
#define RTKIT_OBJECT_PATH "/org/freedesktop/RealtimeKit1"
|
||||
|
||||
/* This is mostly equivalent to sched_setparam(thread, SCHED_RR, {
|
||||
* .sched_priority = priority }). 'thread' needs to be a kernel thread
|
||||
* id as returned by gettid(), not a pthread_t! If 'thread' is 0 the
|
||||
* current thread is used. The returned value is a negative errno
|
||||
* style error code, or 0 on success. */
|
||||
int fluid_rtkit_make_realtime(pid_t thread, int priority);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -26,6 +26,10 @@
|
|||
#include <readline/history.h>
|
||||
#endif
|
||||
|
||||
#ifdef DBUS_SUPPORT
|
||||
#include "fluid_rtkit.h"
|
||||
#endif
|
||||
|
||||
/* WIN32 HACK - Flag used to differentiate between a file descriptor and a socket.
|
||||
* Should work, so long as no SOCKET or file descriptor ends up with this bit set. - JG */
|
||||
#define WIN32_SOCKET_FLAG 0x40000000
|
||||
|
@ -421,10 +425,21 @@ fluid_thread_self_set_prio (int prio_level)
|
|||
|
||||
if (prio_level > 0)
|
||||
{
|
||||
|
||||
memset(&priority, 0, sizeof(priority));
|
||||
priority.sched_priority = prio_level;
|
||||
|
||||
if (pthread_setschedparam (pthread_self (), SCHED_FIFO, &priority) != 0)
|
||||
FLUID_LOG(FLUID_WARN, "Failed to set thread to high priority");
|
||||
if (pthread_setschedparam (pthread_self (), SCHED_FIFO, &priority) == 0) {
|
||||
return;
|
||||
}
|
||||
#ifdef DBUS_SUPPORT
|
||||
/* Try to gain high priority via rtkit */
|
||||
|
||||
if (fluid_rtkit_make_realtime(0, prio_level) == 0) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
FLUID_LOG(FLUID_WARN, "Failed to set thread to high priority");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue