[proaudio] [993] add dbus patches for jack svn, thanks MarcOChapeau

[ Thread Index | Date Index | More lists.tuxfamily.org/proaudio Archives ]


Revision: 993
Author:   gimpel
Date:     2007-12-10 21:09:08 +0000 (Mon, 10 Dec 2007)

Log Message:
-----------
add dbus patches for jack svn, thanks MarcOChapeau

Modified Paths:
--------------
    trunk/overlays/proaudio/media-sound/jack-audio-connection-kit/Manifest
    trunk/overlays/proaudio/media-sound/jack-audio-connection-kit/jack-audio-connection-kit-9999.ebuild

Added Paths:
-----------
    trunk/overlays/proaudio/media-sound/jack-audio-connection-kit/files/jack-dbus-20071209-r1070.patch
    trunk/overlays/proaudio/media-sound/jack-audio-connection-kit/files/jack-logs-20071209-r1070.patch
    trunk/overlays/proaudio/media-sound/jack-audio-connection-kit/files/jackd-midi-alsa-munge-r1051.patch


Modified: trunk/overlays/proaudio/media-sound/jack-audio-connection-kit/Manifest
===================================================================
--- trunk/overlays/proaudio/media-sound/jack-audio-connection-kit/Manifest	2007-12-09 21:31:09 UTC (rev 992)
+++ trunk/overlays/proaudio/media-sound/jack-audio-connection-kit/Manifest	2007-12-10 21:09:08 UTC (rev 993)
@@ -6,10 +6,22 @@
 MD5 8e9c72734364a9d7e4a6d781e13beec8 files/jack-audio-connection-kit-transport.patch 309
 RMD160 7b7130dd922ed14988eb591059d643ece39f6757 files/jack-audio-connection-kit-transport.patch 309
 SHA256 74f1d155f365deb1461d070b37ccd7836c32c521d31960a3f4e6c3f2e528bada files/jack-audio-connection-kit-transport.patch 309
+AUX jack-dbus-20071209-r1070.patch 113742 RMD160 e1e10d6868bd1858f25350f3f5000bb6043e5e16 SHA1 deadaccd987df25f72fe41d3ce3c32e77c354041 SHA256 72f76060e37344248b5ec8b2a110477f321b05f596cb304ef083f0aab289fd91
+MD5 d918a96c3a1abb522c4e4124ba10f49b files/jack-dbus-20071209-r1070.patch 113742
+RMD160 e1e10d6868bd1858f25350f3f5000bb6043e5e16 files/jack-dbus-20071209-r1070.patch 113742
+SHA256 72f76060e37344248b5ec8b2a110477f321b05f596cb304ef083f0aab289fd91 files/jack-dbus-20071209-r1070.patch 113742
+AUX jack-logs-20071209-r1070.patch 65264 RMD160 c0c459971cde07c042c1822d537d7fc623293a08 SHA1 62716ba3b9f87794c9767e131a6f58e48185a876 SHA256 edd469124acf1b40cf3852aaaf6d990fe4393a034426cbc23603dd1d65a6a6b5
+MD5 7fb69654caa569e6a210558de25dcba0 files/jack-logs-20071209-r1070.patch 65264
+RMD160 c0c459971cde07c042c1822d537d7fc623293a08 files/jack-logs-20071209-r1070.patch 65264
+SHA256 edd469124acf1b40cf3852aaaf6d990fe4393a034426cbc23603dd1d65a6a6b5 files/jack-logs-20071209-r1070.patch 65264
 AUX jack-transport-start-at-zero-fix.diff 1613 RMD160 aa2e1492841c4299647af812d68e9585ebd53b10 SHA1 9e18d8ed0fa755fcd4aa53e82693e03d71a94b7b SHA256 f836d29c3ee71624968e8befb3f9972c1906b926d4737e02499a6bec646b5a1f
 MD5 91af67d40f1c1da258e3ed63d1081e5a files/jack-transport-start-at-zero-fix.diff 1613
 RMD160 aa2e1492841c4299647af812d68e9585ebd53b10 files/jack-transport-start-at-zero-fix.diff 1613
 SHA256 f836d29c3ee71624968e8befb3f9972c1906b926d4737e02499a6bec646b5a1f files/jack-transport-start-at-zero-fix.diff 1613
+AUX jackd-midi-alsa-munge-r1051.patch 6779 RMD160 c28114880739578a1916f51257cdcd48011e4fda SHA1 6b3387eabffbf40aef74898c9139bdde9366ba34 SHA256 0d4d155fbcda8bd48efd40559316bdfab7732624ed4918751c65a101a40e5b40
+MD5 17a521d186ffbf68a9571943fd289293 files/jackd-midi-alsa-munge-r1051.patch 6779
+RMD160 c28114880739578a1916f51257cdcd48011e4fda files/jackd-midi-alsa-munge-r1051.patch 6779
+SHA256 0d4d155fbcda8bd48efd40559316bdfab7732624ed4918751c65a101a40e5b40 files/jackd-midi-alsa-munge-r1051.patch 6779
 AUX jackmidi_01dec05.patch 34782 RMD160 151415df3439c7d7b6f4109559ed3b212316e6bb SHA1 60d8a3064f349fa0897c78ded0e7d14a64f0f533 SHA256 3c0d5097f7b2fda5c35c963224dd7a59b097181415956317cf6f161d5e48048a
 MD5 7647467867c81df137fb20b7d18ede84 files/jackmidi_01dec05.patch 34782
 RMD160 151415df3439c7d7b6f4109559ed3b212316e6bb files/jackmidi_01dec05.patch 34782
@@ -40,10 +52,10 @@
 MD5 2862b39b03dc21b759f685e4897a4851 jack-audio-connection-kit-0.103.0.ebuild 4016
 RMD160 e8e807988fb0ecc419ed51bedbcad17a51d43e13 jack-audio-connection-kit-0.103.0.ebuild 4016
 SHA256 8786bc424e9ffe2e2f6d7a7af9ee86e267a05c4b74364b28a483268e7bb69456 jack-audio-connection-kit-0.103.0.ebuild 4016
-EBUILD jack-audio-connection-kit-9999.ebuild 3616 RMD160 eea4163b66f3ca84bf007b93438574cf41f0774b SHA1 05d66b6985d5add610bea1e2d31262eff3a0f4f9 SHA256 7369b1854b3e73416868a99ba940c5c85eeac2f98d745cc5c9d5b457936eb1db
-MD5 4985713d58b3d3c089299bd355ea5a65 jack-audio-connection-kit-9999.ebuild 3616
-RMD160 eea4163b66f3ca84bf007b93438574cf41f0774b jack-audio-connection-kit-9999.ebuild 3616
-SHA256 7369b1854b3e73416868a99ba940c5c85eeac2f98d745cc5c9d5b457936eb1db jack-audio-connection-kit-9999.ebuild 3616
+EBUILD jack-audio-connection-kit-9999.ebuild 4065 RMD160 127b2316d6a5f4b09917283fbfa7a5ec8ed2e99d SHA1 ff5b2072f515373b25f0c1c51c12b061fdb3128a SHA256 323214467708dddf2943c01d5f7f9b7dd81d876d696279b7d26b53d38a1680b7
+MD5 03c6d2c9f0dc02f91d70fd421bda40c2 jack-audio-connection-kit-9999.ebuild 4065
+RMD160 127b2316d6a5f4b09917283fbfa7a5ec8ed2e99d jack-audio-connection-kit-9999.ebuild 4065
+SHA256 323214467708dddf2943c01d5f7f9b7dd81d876d696279b7d26b53d38a1680b7 jack-audio-connection-kit-9999.ebuild 4065
 MD5 df2adc4b2299bdce5818a7cb6e76835a files/digest-jack-audio-connection-kit-0.100.7-r2 551
 RMD160 18c6046126c81aa039ea118aa6129a600e215837 files/digest-jack-audio-connection-kit-0.100.7-r2 551
 SHA256 bc7f285778b0a81e16e9de873c5246f1b52c477282c7b239286a198091fc11b4 files/digest-jack-audio-connection-kit-0.100.7-r2 551

Added: trunk/overlays/proaudio/media-sound/jack-audio-connection-kit/files/jack-dbus-20071209-r1070.patch
===================================================================
--- trunk/overlays/proaudio/media-sound/jack-audio-connection-kit/files/jack-dbus-20071209-r1070.patch	                        (rev 0)
+++ trunk/overlays/proaudio/media-sound/jack-audio-connection-kit/files/jack-dbus-20071209-r1070.patch	2007-12-10 21:09:08 UTC (rev 993)
@@ -0,0 +1,4141 @@
+diff --git a/TODO.dbus b/TODO.dbus
+new file mode 100644
+--- /dev/null
++++ b/TODO.dbus
+@@ -0,0 +1,5 @@
++ * Provide access to clock source parameter (tricky)
++ * Provide access to debug-timer parameter (not fully documented - optarg)
++ * Send signals to (control) apps (status changes, connections, clients, port renames, xruns, error and info logs)
++ * In client library, when compiled with dbus support, try to start via dbus frontend first (auto-activation)
++ * Implement configurator supporting multiple user configurations (separate D-Bus object)
+diff --git a/configure.ac b/configure.ac
+--- a/configure.ac
++++ b/configure.ac
+@@ -547,6 +547,39 @@ fi
+ # PKG_CHECK_MODULES inside a --disable-whatever check, you need to
+ # do it somewhere *below* this comment.
+ 
++AC_ARG_ENABLE(dbus, [  --disable-dbus          don't build D-Bus integration ],
++			TRY_DBUS=$enableval , TRY_DBUS=yes ) 
++HAVE_DBUS=false
++if test "x$TRY_DBUS" = "xyes"
++then
++	PKG_CHECK_MODULES(DBUSGLIB, dbus-glib-1, [AC_DEFINE([HAVE_DBUS], 1, [Defined if D-Bus support needs to be built.]) HAVE_DBUS=true], [true])
++fi
++
++AM_CONDITIONAL(HAVE_DBUS, $HAVE_DBUS)
++
++AC_ARG_ENABLE(pkg-config-dbus-service-dir,
++	[  --enable-pkg-config-dbus-service-dir    force D-Bus service install dir to be one returned by pkg-config ],
++	DBUS_SERVICES_DIR_FORCE_REAL=$enableval , DBUS_SERVICES_DIR_FORCE_REAL=no ) 
++
++if test "x$HAVE_DBUS" = "xtrue"
++then
++	DBUS_SERVICES_DIR_REAL=`$PKG_CONFIG --variable=session_bus_services_dir dbus-1`
++	if test "x$DBUS_SERVICES_DIR_FORCE_REAL" = "xyes"
++	then
++		AC_MSG_WARN([overriding D-Bus service install dir])
++		DBUS_SERVICES_DIR="$DBUS_SERVICES_DIR_REAL"
++	else
++		AS_AC_EXPAND(DATADIR, $datadir)
++		DBUS_SERVICES_DIR="$DATADIR/dbus-1/services"
++	fi
++	AC_SUBST(DBUS_SERVICES_DIR)
++	AC_DEFINE_UNQUOTED(DBUS_SERVICES_DIR, "$DBUS_SERVICES_DIR", [Where services dir for DBUS is])
++fi
++
++HAVE_LIBXML2=false
++PKG_CHECK_MODULES(LIBXML2, libxml-2.0, [AC_DEFINE([HAVE_LIBXML2], 1, [Defined if libxml2 is present.]) HAVE_LIBXML2=true], [true])
++AM_CONDITIONAL(HAVE_LIBXML2, $HAVE_LIBXML2)
++
+ # Check which backend drivers can be built.  The last one successfully
+ # configured becomes the default JACK driver; so the order of
+ # precedence is: alsa, oss, coreaudio, portaudio, dummy.
+@@ -749,6 +782,20 @@ echo \|
+ echo \|
+ echo \| Default driver backend................................ : $JACK_DEFAULT_DRIVER
+ echo \| Shared memory interface............................... : $JACK_SHM_TYPE
++echo \| D-Bus integration .................................... : $HAVE_DBUS
++if test "x$HAVE_DBUS" = "xtrue"
++then
++echo \| D-Bus service install dir............................. : $DBUS_SERVICES_DIR
++echo \| Settings persistence.................................. : $HAVE_LIBXML2
++fi
+ echo \| Install prefix........................................ : $prefix
+ echo
+ 
++if test "x$HAVE_DBUS" = "xtrue" -a "x$DBUS_SERVICES_DIR_REAL" != "x$DBUS_SERVICES_DIR"
++then
++	AC_MSG_WARN([D-Bus session services directory as reported by pkg-config is $DBUS_SERVICES_DIR_REAL])
++	AC_MSG_WARN([but service file will be installed in $DBUS_SERVICES_DIR])
++	AC_MSG_WARN([You may need to adjust your D-Bus configuration after installing jackdbus])
++	AC_MSG_WARN([You can override dbus service install dir])
++	AC_MSG_WARN([with --enable-pkg-config-dbus-service-dir option to this script])
++fi
+diff --git a/example-clients/Makefile.am b/example-clients/Makefile.am
+--- a/example-clients/Makefile.am
++++ b/example-clients/Makefile.am
+@@ -42,6 +42,10 @@ bin_PROGRAMS = jack_load \
+ 	       $(JACK_TRANSPORT) \
+ 		   jack_midisine \
+ 		   jack_midiseq
++
++if HAVE_DBUS
++bin_SCRIPTS = jack_control
++endif
+ 
+ noinst_PROGRAMS = jack_thread_wait
+ 
+diff --git a/example-clients/jack_control b/example-clients/jack_control
+new file mode 100755
+--- /dev/null
++++ b/example-clients/jack_control
+@@ -0,0 +1,250 @@
++#!/usr/bin/env python
++
++name_base = 'org.jackaudio'
++controller_interface_name = name_base + '.JackController'
++service_name = name_base + '.service'
++
++import sys
++import os
++from traceback import print_exc
++
++import dbus
++
++def bool_convert(str_value):
++    if str_value.lower() == "false":
++	return False
++
++    if str_value.lower() == "off":
++	return False
++
++    if str_value.lower() == "no":
++	return False
++
++    if str_value == "0":
++	return False
++
++    if str_value.lower() == "(null)":
++	return False
++
++    return bool(str_value)
++
++def main():
++    if len(sys.argv) == 1:
++        print "Usage: %s [command] [command] ..." % os.path.basename(sys.argv[0])
++        print "Commands:"
++        print "    exit                 - exit jack dbus service (stops jack server if currently running)"
++#       print "    isr                  - check whether jack server is running, return value is 0 if runing and 1 otherwise"
++#       print "    status               - get string describing jack server status"
++        print "    start                - start jack server if not currently started"
++        print "    stop                 - stop jack server if currenly started"
++        print "    dl                   - get list of available drivers"
++        print "    dg                   - get currently selected driver"
++        print "    ds <driver>          - select driver"
++        print "    dp                   - get parameters of currently selected driver"
++        print "    dpd <param>          - get long description for driver parameter"
++        print "    dps <param> <value>  - set driver parameter"
++        print "    ep                   - get engine parameters"
++        print "    epd <param>          - get long description for engine parameter"
++        print "    eps <param> <value>  - set engine parameter"
++	sys.exit(0)
++    
++    bus = dbus.SessionBus()
++
++    controller = bus.get_object(service_name, "/DefaultController")
++    iface = dbus.Interface(controller, controller_interface_name)
++
++    # check arguments
++    index = 1
++    while index < len(sys.argv):
++	arg = sys.argv[index]
++	index += 1
++        try:
++            if arg == "exit":
++		print "--- exit"
++                iface.Exit()
++            elif arg == "isr":
++		print "--- isr"
++                if iface.IsRunning():
++                    sys.exit(0)
++                else:
++                    sys.exit(1)
++            elif arg == 'status':
++		print "--- status"
++                print iface.GetStatus()
++            elif arg == 'start':
++		print "--- start"
++                iface.StartServer()
++            elif arg == 'stop':
++		print "--- stop"
++                iface.StopServer()
++            elif arg == 'test':
++		print "--- test"
++                iface.Test()
++            elif arg == 'ism':
++		if iface.IsManuallyActivated():
++		    print "Manually activated"
++		else:
++		    print "Automatically activated"
++            elif arg == 'dl':
++		print "--- drivers list"
++                drivers = iface.GetAvailableDrivers()
++		for driver in drivers:
++		    print driver
++            elif arg == 'dg':
++		print "--- get selected driver"
++                driver = iface.GetSelectedDriver()
++		if not driver:
++		    print "no driver selected"
++		else:
++		    print driver
++            elif arg == 'ds':
++		if index >= len(sys.argv):
++		    print "driver select command requires driver name argument"
++		    sys.exit()
++
++		arg = sys.argv[index]
++		index += 1
++
++		print "--- driver select \"%s\"" % arg
++                iface.SelectDriver(arg)
++            elif arg == 'dp':
++		print "--- get driver parameters (type:isset:default:value)"
++                params = iface.GetDriverParameterNames()
++		for param in params:
++		    descr = iface.GetDriverParameterShortDescription(param)
++		    typestr = iface.GetDriverParameterTypeString(param)
++
++		    if typestr == "str":
++			isset, default, value = iface.GetDriverParameterValueString(param)
++		    elif typestr == "bool":
++			isset, default, value = iface.GetDriverParameterValueBool(param)
++			value = bool(value)
++			default = bool(default)
++		    elif typestr == "char":
++			isset, default, value = iface.GetDriverParameterValueChar(param)
++		    elif typestr == "sint":
++			isset, default, value = iface.GetDriverParameterValueInt(param)
++			value = int(value)
++			default = int(default)
++		    elif typestr == "uint":
++			isset, default, value = iface.GetDriverParameterValueUint(param)
++			value = int(value)
++			default = int(default)
++		    else:
++			isset = None
++			default = None
++			value = None
++
++		    isset = bool(isset)
++
++		    print "%20s: %s (%s:%s:%s:%s)" %(param, descr, typestr, isset, default, value)
++            elif arg == 'dpd':
++		if index >= len(sys.argv):
++		    print "get driver parameter long description command requires driver name argument"
++		    sys.exit()
++
++		param = sys.argv[index]
++		index += 1
++
++		print "--- get driver parameter description (%s)" % param
++		descr = iface.GetDriverParameterLongDescription(param)
++		print descr,
++            elif arg == 'dps':
++		if index + 1 >= len(sys.argv):
++		    print "driver parameter set command requires parametr name and value arguments"
++		    sys.exit()
++
++		param = sys.argv[index]
++		index += 1
++		value = sys.argv[index]
++		index += 1
++
++		print "--- driver param set \"%s\" -> \"%s\"" % (param, value)
++
++		typestr = iface.GetDriverParameterTypeString(param)
++
++		if typestr == "str":
++		    iface.SetDriverParameterValueString(param, value)
++		elif typestr == "bool":
++		    iface.SetDriverParameterValueBool(param, bool_convert(value))
++		elif typestr == "char":
++		    iface.SetDriverParameterValueChar(param, value)
++		elif typestr == "sint":
++		    iface.SetDriverParameterValueInt(param, int(value))
++		elif typestr == "uint":
++		    iface.SetDriverParameterValueUint(param, int(value))
++		else:
++		    print "driver parameter \"%s\" is of unknown type \"%s\"" % (param, typestr)
++		    sys.exit()
++            elif arg == 'ep':
++		print "--- get engine parameters (type:value)"
++                params = iface.GetEngineParameterNames()
++		#print params
++		for param in params:
++		    descr = iface.GetEngineParameterShortDescription(param)
++		    typestr = iface.GetEngineParameterTypeString(param)
++		    #print descr
++		    #print typestr
++
++		    if typestr == "str":
++			value = iface.GetEngineParameterValueString(param)
++		    elif typestr == "bool":
++			value = iface.GetEngineParameterValueBool(param)
++			value = bool(value)
++		    elif typestr == "char":
++			value = iface.GetEngineParameterValueChar(param)
++		    elif typestr == "sint":
++			value = iface.GetEngineParameterValueInt(param)
++			value = int(value)
++		    elif typestr == "uint":
++			value = iface.GetEngineParameterValueUint(param)
++			value = int(value)
++		    else:
++			value = None
++
++		    print "%20s: %s (%s:%s)" %(param, descr, typestr, value)
++            elif arg == 'epd':
++		if index >= len(sys.argv):
++		    print "get engine parameter long description command requires driver name argument"
++		    sys.exit()
++
++		param = sys.argv[index]
++		index += 1
++
++		print "--- get engine parameter description (%s)" % param
++		descr = iface.GetEngineParameterLongDescription(param)
++		print descr,
++            elif arg == 'eps':
++		if index + 1 >= len(sys.argv):
++		    print "engine parameter set command requires parametr name and value arguments"
++		    sys.exit()
++
++		param = sys.argv[index]
++		index += 1
++		value = sys.argv[index]
++		index += 1
++
++		print "--- engine param set \"%s\" -> \"%s\"" % (param, value)
++
++		typestr = iface.GetEngineParameterTypeString(param)
++
++		if typestr == "str":
++		    iface.SetEngineParameterValueString(param, value)
++		elif typestr == "bool":
++		    iface.SetEngineParameterValueBool(param, bool_convert(value))
++		elif typestr == "char":
++		    iface.SetEngineParameterValueChar(param, value)
++		elif typestr == "sint":
++		    iface.SetEngineParameterValueInt(param, int(value))
++		elif typestr == "uint":
++		    iface.SetEngineParameterValueUint(param, int(value))
++		else:
++		    print "engine parameter \"%s\" is of unknown type \"%s\"" % (param, typestr)
++		    sys.exit()
++            else:
++                print "Unknown command '%s'" % arg
++        except dbus.DBusException, e:
++            print "DBus exception: %s" % str(e)
++
++if __name__ == '__main__':
++    main()
+diff --git a/jackd/Makefile.am b/jackd/Makefile.am
+--- a/jackd/Makefile.am
++++ b/jackd/Makefile.am
+@@ -21,14 +21,21 @@ endif
+ 
+ bin_PROGRAMS = jackd $(CAP_PROGS)
+ 
+-AM_CFLAGS = $(JACK_CFLAGS) -DJACK_LOCATION=\"$(bindir)\"
++if HAVE_DBUS
++bin_PROGRAMS += jackdbus
++endif
+ 
+-jackd_SOURCES = jackd.c engine.c clientengine.c transengine.c
+-jackd_LDADD = ../libjack/libjack.la $(CAP_LIBS) @OS_LDFLAGS@
++AM_CFLAGS = $(JACK_CFLAGS) -DJACK_LOCATION=\"$(bindir)\" $(DBUSGLIB_CFLAGS) $(LIBXML2_CFLAGS)
++
++COMMON_SOURCES = engine.c clientengine.c transengine.c
++COMMON_LIBS = ../libjack/libjack.la $(CAP_LIBS) @OS_LDFLAGS@
++
++jackd_SOURCES = jackd.c $(COMMON_SOURCES)
++jackd_LDADD = $(COMMON_LIBS)
+ noinst_HEADERS = jack_md5.h md5.h md5_loc.h \
+ 		 clientengine.h transengine.h
+ 
+-BUILT_SOURCES = jack_md5.h
++BUILT_SOURCES = jack_md5.h jackcontroller-glue.h
+ 
+ jack_md5.h: jackd
+ if STRIPPED_JACKD
+@@ -39,6 +46,26 @@ jackstart_SOURCES = jackstart.c md5.c
+ jackstart_SOURCES = jackstart.c md5.c
+ jackstart_LDFLAGS = -lcap
+ 
++if HAVE_DBUS
++jackcontroller-glue.h: jackcontroller.xml
++	dbus-binding-tool --mode=glib-server --prefix=jackcontroller jackcontroller.xml > jackcontroller-glue.h
++
++jackdbus_SOURCES = jackdbus.c $(COMMON_SOURCES) jackcontroller.c jackcontroller.h jackcontroller.xml
++jackdbus_LDADD = $(COMMON_LIBS) $(DBUSGLIB_LIBS) $(LIBXML2_LIBS)
++
++# Dbus service file
++servicedir = $(DBUS_SERVICES_DIR)
++service_in_files = org.jackaudio.service.in
++service_DATA = $(service_in_files:.service.in=.service)
++
++# Rule to make the service file with bindir expanded
++$(service_DATA): $(service_in_files) Makefile
++	@sed -e "s|\@bindir\@|$(bindir)|" $< > $@
++
++jackdbus_EXTRA_DIST = $(service_in_files)
++
++endif
++
+ man_MANS = jackd.1 jackstart.1
+ EXTRA_DIST = $(man_MANS)
+ 
+diff --git a/jackd/jackcontroller.c b/jackd/jackcontroller.c
+new file mode 100644
+--- /dev/null
++++ b/jackd/jackcontroller.c
+@@ -0,0 +1,2851 @@
++/* -*- mode: c; c-file-style: "bsd"; -*- */
++/*
++    Copyright (C) 2007 Nedko Arnaudov
++    
++    This program is free software; you can redistribute it and/or modify
++    it under the terms of the GNU General Public License as published by
++    the Free Software Foundation; either version 2 of the License.
++
++    This program is distributed in the hope that it will be useful,
++    but WITHOUT ANY WARRANTY; without even the implied warranty of
++    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++    GNU General Public License for more details.
++
++    You should have received a copy of the GNU General Public License
++    along with this program; if not, write to the Free Software
++    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++
++*/
++
++#include <config.h>
++
++#include <stdio.h>
++#include <ctype.h>
++#include <signal.h>
++#include <getopt.h>
++#include <sys/types.h>
++#include <sys/shm.h>
++#include <sys/wait.h>
++#include <string.h>
++#include <errno.h>
++#include <stdlib.h>
++#include <dirent.h>
++#include <dlfcn.h>
++#include <assert.h>
++
++#include <jack/engine.h>
++#include <jack/internal.h>
++#include <jack/driver.h>
++#include <jack/shm.h>
++#include <jack/messagebuffer.h>
++
++#include <dbus/dbus-glib.h>
++
++#if HAVE_LIBXML2
++#include <libxml/xmlwriter.h>
++#include <libxml/parser.h>
++#include <libxml/xpath.h>
++
++/* XPath expression used for engine options selection */
++#define XPATH_ENGINE_OPTIONS_EXPRESSION "/jack/engine/option"
++
++/* XPath expression used for drivers selection */
++#define XPATH_DRIVERS_EXPRESSION "/jack/drivers/driver"
++
++/* XPath expression used for driver options selection */
++#define XPATH_DRIVER_OPTIONS_EXPRESSION "/jack/drivers/driver[@name = '%s']/option"
++#endif
++
++#include "jackcontroller.h"
++#include "jackcontroller-glue.h"
++
++#include "jackdbus.h"
++
++struct jack_controller_driver
++{
++	char * filename;
++	jack_driver_desc_t * desc_ptr;
++	JSList * params;
++};
++
++struct jack_controller
++{
++	gboolean dispose_has_run;
++
++	GMainLoop *loop;
++	gboolean manually_started;
++
++	unsigned int drivers_count;
++	JSList *drivers;
++
++	/* current driver, NULL if not driver is selected */
++	struct jack_controller_driver *driver_ptr;
++
++	jack_engine_t *engine;
++
++	int realtime;		/* boolean, whether to be "realtime" */
++	int realtime_priority;
++
++	char *server_name;
++
++	int do_mlock;		/* boolean, whether to do memory locking */
++	int temporary;		/* boolean, whether to exit once all clients have closed their connections */
++	int verbose;		/* boolean, whether to be verbose */
++	int client_timeout;	/* msecs; if zero, use period size. */
++	unsigned int port_max;	/* maximum number of ports the JACK server can manage */
++	int do_unlock;		/* boolean, whether to unlock libraries GTK+, QT, FLTK, Wine */
++	jack_nframes_t frame_time_offset;
++	int nozombies;		/* boolean, whether to prevent from ever kicking out clients because they were too slow */
++};
++
++/** Parameter types, intentionally similar to jack_driver_param_type_t */
++typedef enum
++{
++  JackParamInt = 1,
++  JackParamUInt,
++  JackParamChar,
++  JackParamString,
++  JackParamBool
++
++} jack_param_type_t;
++
++struct jack_engine_parameter_descriptor
++{
++	const char *name;
++	jack_param_type_t type;
++	const char *description_short;
++	const char *description_long;
++};
++
++struct jack_engine_parameter_descriptor jack_engine_parameters[] =
++{
++	{"realtime", JackParamBool, "Whether to use realtime mode", "Use realtime scheduling. This is needed for reliable low-latency performance. On most systems, it requires JACK to run with special scheduler and memory allocation privileges, which may be obtained in several ways. On Linux you should use PAM."},
++	{"realtime-priority", JackParamInt, "Scheduler priority when running in realtime mode.", NULL},
++	{"no-mem-lock", JackParamBool, "Do not attempt to lock memory, even in realtime mode.", NULL},
++	{"temporary", JackParamBool, "Exit once all clients have closed their connections.", NULL},
++	{"verbose", JackParamBool, "Verbose mode", NULL},
++	{"client-timeout", JackParamInt, "Client timeout limit in milliseconds", "Client timeout limit in milliseconds. In realtime mode the client timeout must be smaller than the watchdog timeout (5000 msec)."},
++	{"no-zombies", JackParamBool, "Prevent JACK from ever kicking out clients because they were too slow.", "Prevent JACK from ever kicking out clients because they were too slow. JACK and its clients are still subject to the supervision of the watchdog thread or its equivalent."},
++	{"port-max", JackParamUInt, "Maximum number of ports the JACK server can manage", NULL},
++	{"libs-unlock", JackParamBool, "Unlock libraries GTK+, QT, FLTK, Wine.", NULL},
++};
++
++#define JACK_ENGINE_PARAMS_COUNT (sizeof(jack_engine_parameters)/sizeof(struct jack_engine_parameter_descriptor))
++
++gboolean
++jack_controller_load_descriptor(
++	struct jack_controller * controller_ptr,
++	struct jack_controller_driver * driver_ptr)
++{
++	jack_driver_desc_t * descriptor;
++	JackDriverDescFunction so_get_descriptor;
++	void * dlhandle;
++	const char * dlerr;
++	int err;
++
++	if (controller_ptr->verbose) {
++		jack_info ("getting driver descriptor from %s", driver_ptr->filename);
++	}
++
++	dlhandle = dlopen(driver_ptr->filename, RTLD_NOW|RTLD_GLOBAL);
++	if (dlhandle == NULL) {
++		jack_error("could not open driver .so '%s': %s", driver_ptr->filename, dlerror());
++		return FALSE;
++	}
++
++	so_get_descriptor = (JackDriverDescFunction)
++		dlsym(dlhandle, "driver_get_descriptor");
++
++	dlerr = dlerror();
++	if (dlerr != NULL) {
++		jack_error("cannot find driver_get_descriptor symbol: %s", dlerr);
++		dlclose(dlhandle);
++		return FALSE;
++	}
++
++	descriptor = so_get_descriptor();
++	if (descriptor == NULL) {
++		jack_error("driver from '%s' returned NULL descriptor", driver_ptr->filename);
++		dlclose(dlhandle);
++		return FALSE;
++	}
++
++	err = dlclose(dlhandle);
++	if (err != 0) {
++		jack_error("error closing driver .so '%s': %s", driver_ptr->filename, dlerror());
++		free(descriptor->params);
++		free(descriptor);
++		return FALSE;
++	}
++
++	/* for some mad reason we are storing filename in descriptor allocated by driver
++	   instead of reusing dlhandle when another dlsym() call is needed */
++	snprintf (descriptor->file, sizeof(descriptor->file), "%s", driver_ptr->filename);
++
++	driver_ptr->desc_ptr = descriptor;
++
++	return TRUE;
++}
++
++static
++gboolean
++jack_drivers_load(
++	struct jack_controller *controller_ptr)
++{
++	struct dirent * dir_entry;
++	DIR * dir_stream;
++	const char * ptr;
++	int err;
++	char* driver_dir;
++	struct jack_controller_driver * driver_ptr;
++	struct jack_controller_driver * other_driver_ptr;
++	JSList * node_ptr;
++
++	if ((driver_dir = getenv("JACK_DRIVER_DIR")) == 0) {
++		driver_dir = ADDON_DIR;
++	}
++
++	if (controller_ptr->verbose) {
++		jack_info ("searching for drivers in %s", driver_dir);
++	}
++
++	/* search through the driver_dir and add get descriptors
++	   from the .so files in it */
++	dir_stream = opendir (driver_dir);
++	if (!dir_stream) {
++		jack_error ("could not open driver directory %s: %s",
++			    driver_dir, strerror (errno));
++		return FALSE;
++	}
++  
++	while ( (dir_entry = readdir (dir_stream)) ) {
++		/* check the filename is of the right format */
++		if (strncmp ("jack_", dir_entry->d_name, 5) != 0) {
++			continue;
++		}
++
++#if HAVE_LIBXML2
++		/* temporary disable ffado driver until we make it work with libxml2 loaded by jackdbus */
++		if (strcmp ("jack_firewire.so", dir_entry->d_name) == 0) {
++			continue;
++		}
++#endif
++
++		ptr = strrchr (dir_entry->d_name, '.');
++		if (!ptr) {
++			continue;
++		}
++		ptr++;
++		if (strncmp ("so", ptr, 2) != 0) {
++			continue;
++		}
++
++		driver_ptr = malloc(sizeof(struct jack_controller_driver));
++		if (driver_ptr == NULL)
++		{
++			jack_error("memory allocation of jack_controller_driver structure failed.");
++			continue;
++		}
++
++		driver_ptr->filename = malloc(strlen(driver_dir) + 1 + strlen(dir_entry->d_name) + 1);
++
++		sprintf(driver_ptr->filename, "%s/%s", driver_dir, dir_entry->d_name);
++
++		if (!jack_controller_load_descriptor(controller_ptr, driver_ptr))
++		{
++			goto dealloc_driver;
++		}
++
++		/* check it doesn't exist already */
++		for (node_ptr = controller_ptr->drivers; node_ptr != NULL; node_ptr = jack_slist_next(node_ptr))
++		{
++			other_driver_ptr = (struct jack_controller_driver *)node_ptr->data;
++			
++			if (strcmp(driver_ptr->desc_ptr->name, other_driver_ptr->desc_ptr->name) == 0)
++			{
++				jack_error(
++					"the drivers in '%s' and '%s' both have the name '%s'; using the first",
++					other_driver_ptr->filename,
++					driver_ptr->filename,
++					driver_ptr->desc_ptr->name);
++				goto dealloc_descriptor;
++			}
++		}
++
++		driver_ptr->params = NULL;
++
++		controller_ptr->drivers = jack_slist_append(controller_ptr->drivers, driver_ptr);
++		controller_ptr->drivers_count++;
++
++		continue;
++
++	dealloc_descriptor:
++		free(driver_ptr->desc_ptr->params);
++		free(driver_ptr->desc_ptr);
++
++	dealloc_driver:
++		free(driver_ptr->filename);
++		free(driver_ptr);
++	}
++
++	err = closedir (dir_stream);
++	if (err) {
++		jack_error ("error closing driver directory %s: %s",
++			    driver_dir, strerror (errno));
++	}
++
++	if (controller_ptr->drivers_count == 0)
++	{
++		jack_error ("could not find any drivers in %s!", driver_dir);
++		return FALSE;
++	}
++
++	return TRUE;
++}
++
++static void
++jack_cleanup_files (const char *server_name)
++{
++	DIR *dir;
++	struct dirent *dirent;
++	char dir_name[PATH_MAX+1] = "";
++        jack_server_dir (server_name, dir_name);
++
++	/* On termination, we remove all files that jackd creates so
++	 * subsequent attempts to start jackd will not believe that an
++	 * instance is already running.  If the server crashes or is
++	 * terminated with SIGKILL, this is not possible.  So, cleanup
++	 * is also attempted when jackd starts.
++	 *
++	 * There are several tricky issues.  First, the previous JACK
++	 * server may have run for a different user ID, so its files
++	 * may be inaccessible.  This is handled by using a separate
++	 * JACK_TMP_DIR subdirectory for each user.  Second, there may
++	 * be other servers running with different names.  Each gets
++	 * its own subdirectory within the per-user directory.  The
++	 * current process has already registered as `server_name', so
++	 * we know there is no other server actively using that name.
++	 */
++
++	/* nothing to do if the server directory does not exist */
++	if ((dir = opendir (dir_name)) == NULL) {
++		return;
++	}
++
++	/* unlink all the files in this directory, they are mine */
++	while ((dirent = readdir (dir)) != NULL) {
++
++		char fullpath[PATH_MAX+1];
++
++		if ((strcmp (dirent->d_name, ".") == 0)
++		    || (strcmp (dirent->d_name, "..") == 0)) {
++			continue;
++		}
++
++		snprintf (fullpath, sizeof (fullpath), "%s/%s",
++			  dir_name, dirent->d_name);
++
++		if (unlink (fullpath)) {
++			jack_error ("cannot unlink `%s' (%s)", fullpath,
++				    strerror (errno));
++		}
++	} 
++
++	closedir (dir);
++
++	/* now, delete the per-server subdirectory, itself */
++	if (rmdir (dir_name)) {
++ 		jack_error ("cannot remove `%s' (%s)", dir_name,
++			    strerror (errno));
++	}
++
++	/* finally, delete the per-user subdirectory, if empty */
++	if (rmdir (jack_user_dir ())) {
++		if (errno != ENOTEMPTY) {
++			jack_error ("cannot remove `%s' (%s)",
++				    jack_user_dir (), strerror (errno));
++		}
++	}
++}
++
++#define JACK_CONTROLLER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), JACK_CONTROLLER_TYPE, struct jack_controller))
++
++static void
++jack_controller_dispose(GObject * obj)
++{
++  struct jack_controller * controller_ptr;
++
++  controller_ptr = JACK_CONTROLLER_GET_PRIVATE(obj);
++
++  if (controller_ptr->dispose_has_run)
++  {
++    /* If dispose did already run, return. */
++    return;
++  }
++
++  /* Make sure dispose does not run twice. */
++  controller_ptr->dispose_has_run = TRUE;
++
++  /* 
++   * In dispose, you are supposed to free all types referenced from this
++   * object which might themselves hold a reference to self. Generally,
++   * the most simple solution is to unref all members on which you own a 
++   * reference.
++   */
++
++  /* Chain up to the parent class */
++  G_OBJECT_CLASS(g_type_class_peek_parent(G_OBJECT_GET_CLASS(obj)))->dispose(obj);
++}
++
++static void
++jack_controller_finalize(GObject * obj)
++{
++//  struct jack_controller * self = JACK_CONTROLLER_GET_PRIVATE(obj);
++
++  /*
++   * Here, complete object destruction.
++   * You might not need to do much...
++   */
++  //g_free(self->private);
++
++  /* Chain up to the parent class */
++  G_OBJECT_CLASS(g_type_class_peek_parent(G_OBJECT_GET_CLASS(obj)))->finalize(obj);
++}
++
++static void
++jack_controller_class_init(
++	gpointer class_ptr,
++	gpointer class_data_ptr)
++{
++	G_OBJECT_CLASS(class_ptr)->dispose = jack_controller_dispose;
++	G_OBJECT_CLASS(class_ptr)->finalize = jack_controller_finalize;
++
++	g_type_class_add_private(G_OBJECT_CLASS(class_ptr), sizeof(struct jack_controller));
++	dbus_g_object_type_install_info (JACK_CONTROLLER_TYPE, &dbus_glib_jackcontroller_object_info);
++}
++
++static void
++jack_controller_init(
++	GTypeInstance * instance,
++	gpointer g_class)
++{
++	struct jack_controller * controller_ptr;
++
++	controller_ptr = JACK_CONTROLLER_GET_PRIVATE(instance);
++
++	controller_ptr->dispose_has_run = FALSE;
++
++	controller_ptr->loop = NULL;
++	controller_ptr->manually_started = FALSE;
++
++	controller_ptr->drivers = NULL;
++	controller_ptr->drivers_count = 0;
++
++	controller_ptr->engine = NULL;
++	controller_ptr->server_name = jack_default_server_name();
++	controller_ptr->realtime = 0;
++	controller_ptr->realtime_priority = 10;
++	controller_ptr->do_mlock = 1;
++	controller_ptr->temporary = 0;
++	controller_ptr->verbose = 0;
++	controller_ptr->client_timeout = 500;
++	controller_ptr->port_max = 256;
++	controller_ptr->do_unlock = 0;
++	controller_ptr->frame_time_offset = 0;
++	controller_ptr->nozombies = 0;
++}
++
++GType jack_controller_get_type()
++{
++	static GType type = 0;
++	if (type == 0)
++	{
++		type = g_type_register_static_simple(
++			G_TYPE_OBJECT,
++			"jack_controller_type",
++			sizeof(JackControllerClass),
++			jack_controller_class_init,
++			sizeof(JackController),
++			jack_controller_init,
++			0);
++	}
++
++	return type;
++}
++
++GQuark
++jack_controller_error_quark()
++{
++	static GQuark quark = 0;
++	if (!quark)
++		quark = g_quark_from_static_string ("jack_controller_error");
++
++	return quark;
++}
++
++gboolean
++jack_controller_test(
++	JackController * object_ptr,
++	GError ** error)
++{
++        jack_info("Test!");
++	g_set_error(error, jack_controller_error_quark(), 0, "Muhahaha!");
++	return FALSE;
++}
++
++gboolean
++jack_controller_exit(
++	JackController * object_ptr,
++	GError ** error)
++{
++	struct jack_controller * controller_ptr;
++
++	controller_ptr = JACK_CONTROLLER_GET_PRIVATE(object_ptr);
++
++        jack_info("Exit!");
++	g_main_quit(controller_ptr->loop);
++	return TRUE;
++}
++
++gboolean
++jack_controller_is_manually_activated(
++	JackController * object_ptr,
++	gboolean * manually_started_ptr,
++	GError ** error)
++{
++	struct jack_controller * controller_ptr;
++
++        jack_info("Is manually started?");
++
++	controller_ptr = JACK_CONTROLLER_GET_PRIVATE(object_ptr);
++
++	*manually_started_ptr = controller_ptr->manually_started;
++	return TRUE;
++}
++
++void
++jack_controller_error(
++	GError **error,
++	const gchar *format,
++	...)
++{
++	va_list ap;
++	char buffer[300];
++
++	va_start(ap, format);
++
++	vsnprintf(buffer, sizeof(buffer), format, ap);
++
++	jack_error_callback(buffer);
++	if (error != NULL)
++	{
++		g_set_error(error, jack_controller_error_quark(), 0, buffer);
++	}
++
++	va_end(ap);
++}
++
++jack_driver_param_desc_t *
++jack_controller_find_parameter_descriptor(
++	struct jack_controller_driver *driver_ptr,
++	jack_driver_param_t * param_ptr)
++{
++	unsigned int i;
++
++	for (i = 0; i < driver_ptr->desc_ptr->nparams ; i++)
++	{
++		if (driver_ptr->desc_ptr->params[i].character == param_ptr->character)
++		{
++			return driver_ptr->desc_ptr->params + i;
++		}
++	}
++
++	return NULL;
++}
++
++jack_driver_param_desc_t *
++jack_controller_find_parameter_descriptor_by_name(
++	struct jack_controller_driver *driver_ptr,
++	const char *param_name)
++{
++	unsigned int i;
++
++	for (i = 0; i < driver_ptr->desc_ptr->nparams ; i++)
++	{
++		if (strcmp(driver_ptr->desc_ptr->params[i].name, param_name) == 0)
++		{
++			return driver_ptr->desc_ptr->params + i;
++		}
++	}
++
++	return NULL;
++}
++
++jack_driver_param_desc_t *
++jack_controller_find_parameter_descriptor_by_name_current_driver(
++	struct jack_controller *controller_ptr,
++	const gchar *param_name)
++{
++	return jack_controller_find_parameter_descriptor_by_name(controller_ptr->driver_ptr, param_name);
++}
++
++/* search for parameter matching parameter descriptor, return NULL if not found */
++jack_driver_param_t *
++jack_controller_find_parameter(
++	struct jack_controller_driver *driver_ptr,
++	const jack_driver_param_desc_t *descr_ptr)
++{
++	JSList * node_ptr;
++	jack_driver_param_t * param_ptr;
++
++	for (node_ptr = driver_ptr->params; node_ptr != NULL; node_ptr = jack_slist_next(node_ptr))
++	{
++		param_ptr = (jack_driver_param_t *)node_ptr->data;
++			
++		if (param_ptr->character == descr_ptr->character)
++		{
++			return param_ptr;
++		}
++	}
++
++	return NULL;
++}
++
++jack_driver_param_t *
++jack_controller_find_parameter_current_driver(
++	struct jack_controller *controller_ptr,
++	const jack_driver_param_desc_t *descr_ptr)
++{
++	return jack_controller_find_parameter(controller_ptr->driver_ptr, descr_ptr);
++}
++
++/* search for parameter matching parameter descriptor, if not found, create new one */
++jack_driver_param_t *
++jack_controller_find_or_create_parameter(
++	struct jack_controller_driver *driver_ptr,
++	const jack_driver_param_desc_t *descr_ptr)
++{
++	jack_driver_param_t * param_ptr;
++
++	param_ptr = jack_controller_find_parameter(driver_ptr, descr_ptr);
++	if (param_ptr != NULL)
++	{
++		return param_ptr;
++	}
++
++	param_ptr = malloc(sizeof(jack_driver_param_t));
++	if (param_ptr == NULL)
++	{
++		jack_error("Allocation of jack_driver_param_t structure failed.");
++		return NULL;
++	}
++
++	param_ptr->character = descr_ptr->character;
++	param_ptr->value = descr_ptr->value;
++
++	driver_ptr->params = jack_slist_append(driver_ptr->params, param_ptr);
++
++	return param_ptr;
++}
++
++/* search for parameter matching parameter descriptor, if not found, create new one */
++jack_driver_param_t *
++jack_controller_find_or_create_parameter_current_driver(
++	struct jack_controller *controller_ptr,
++	const jack_driver_param_desc_t *descr_ptr)
++{
++	return jack_controller_find_or_create_parameter(controller_ptr->driver_ptr, descr_ptr);
++}
++
++#if HAVE_LIBXML2
++
++gboolean
++jack_controller_settings_write_option(
++	xmlTextWriterPtr writer,
++	const char *name,
++	const char *content,
++	GError **error)
++{
++	if (xmlTextWriterStartElement(writer, BAD_CAST "option") == -1)
++	{
++		jack_controller_error(error, "xmlTextWriterStartElement() failed.");
++		return FALSE;
++	}
++
++	if (xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST name) == -1)
++	{
++		jack_controller_error(error, "xmlTextWriterWriteAttribute() failed.");
++		return FALSE;
++	}
++
++	if (xmlTextWriterWriteString(writer, BAD_CAST content) == -1)
++	{
++		jack_controller_error(error, "xmlTextWriterWriteString() failed.");
++		return FALSE;
++	}
++
++	if (xmlTextWriterEndElement(writer) == -1)
++	{
++		jack_controller_error(error, "xmlTextWriterEndElement() failed.");
++		return FALSE;
++	}
++
++	return TRUE;
++}
++
++gboolean
++jack_controller_settings_write_engine(
++	struct jack_controller * controller_ptr,
++	xmlTextWriterPtr writer,
++	GError **error)
++{
++	gchar value_str[50];
++
++/* 	jack_info("engine settings begin"); */
++/* 	if (xmlTextWriterWriteComment(writer, BAD_CAST "engine parameters") == -1) */
++/* 	{ */
++/* 		jack_controller_error(error, "xmlTextWriterWriteComment() failed."); */
++/* 		return FALSE; */
++/* 	} */
++
++	if (xmlTextWriterStartElement(writer, BAD_CAST "engine") == -1)
++	{
++		jack_controller_error(error, "xmlTextWriterStartElement() failed.");
++		return FALSE;
++	}
++
++	if (controller_ptr->driver_ptr != NULL)
++	{
++		if (!jack_controller_settings_write_option(writer, "driver", controller_ptr->driver_ptr->desc_ptr->name, error))
++		{
++			return FALSE;
++		}
++	}
++
++	if (!jack_controller_settings_write_option(writer, "realtime", controller_ptr->realtime ? "true" : "false", error))
++	{
++		return FALSE;
++	}
++
++	sprintf(value_str, "%d", controller_ptr->realtime_priority);
++	if (!jack_controller_settings_write_option(writer, "realtime-priority", value_str, error))
++	{
++		return FALSE;
++	}
++
++	if (!jack_controller_settings_write_option(writer, "no-mem-lock", controller_ptr->do_mlock ? "false" : "true", error)) /* reverse */
++	{
++		return FALSE;
++	}
++
++	if (!jack_controller_settings_write_option(writer, "temporary", controller_ptr->temporary ? "true" : "false", error))
++	{
++		return FALSE;
++	}
++
++	if (!jack_controller_settings_write_option(writer, "verbose", controller_ptr->verbose ? "true" : "false", error))
++	{
++		return FALSE;
++	}
++
++	sprintf(value_str, "%d", controller_ptr->client_timeout);
++	if (!jack_controller_settings_write_option(writer, "client-timeout", value_str, error))
++	{
++		return FALSE;
++	}
++
++	if (!jack_controller_settings_write_option(writer, "no-zombies", controller_ptr->nozombies ? "true" : "false", error))
++	{
++		return FALSE;
++	}
++
++	sprintf(value_str, "%d", controller_ptr->port_max);
++	if (!jack_controller_settings_write_option(writer, "port-max", value_str, error))
++	{
++		return FALSE;
++	}
++
++	if (!jack_controller_settings_write_option(writer, "libs-unlock", controller_ptr->do_unlock ? "true" : "false", error))
++	{
++		return FALSE;
++	}
++
++	if (xmlTextWriterEndElement(writer) == -1)
++	{
++		jack_controller_error(error, "xmlTextWriterEndElement() failed.");
++		return FALSE;
++	}
++
++/* 	jack_info("engine settings end"); */
++	return TRUE;
++}
++
++gboolean
++jack_controller_settings_write_driver(
++	struct jack_controller * controller_ptr,
++	xmlTextWriterPtr writer,
++	struct jack_controller_driver *driver_ptr,
++	GError **error)
++{
++	JSList *node_ptr;
++	jack_driver_param_t *param_ptr;
++	jack_driver_param_desc_t *param_desc_ptr;
++	gchar value_str[50];
++
++/* 	if (xmlTextWriterWriteComment(writer, BAD_CAST "driver parameters") == -1) */
++/* 	{ */
++/* 		jack_controller_error(error, "xmlTextWriterWriteComment() failed."); */
++/* 		return FALSE; */
++/* 	} */
++
++	if (xmlTextWriterStartElement(writer, BAD_CAST "driver") == -1)
++	{
++		jack_controller_error(error, "xmlTextWriterStartElement() failed.");
++		return FALSE;
++	}
++
++	if (xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST driver_ptr->desc_ptr->name) == -1)
++	{
++		jack_controller_error(error, "xmlTextWriterWriteAttribute() failed.");
++		return FALSE;
++	}
++
++	for (node_ptr = driver_ptr->params; node_ptr != NULL; node_ptr = jack_slist_next(node_ptr))
++	{
++		param_ptr = (jack_driver_param_t *)node_ptr->data;
++		param_desc_ptr = jack_controller_find_parameter_descriptor(driver_ptr, param_ptr);
++
++/* 		if (xmlTextWriterWriteComment(writer, BAD_CAST param_desc_ptr->short_desc) == -1) */
++/* 		{ */
++/* 			jack_controller_error(error, "xmlTextWriterWriteComment() failed."); */
++/* 			return FALSE; */
++/* 		} */
++
++		switch (param_desc_ptr->type)
++		{
++		case JackDriverParamInt:
++			sprintf(value_str, "%d", param_ptr->value.i);
++			if (!jack_controller_settings_write_option(writer, param_desc_ptr->name, value_str, error))
++			{
++				return FALSE;
++			}
++			break;
++		case JackDriverParamUInt:
++			sprintf(value_str, "%u", param_ptr->value.ui);
++			if (!jack_controller_settings_write_option(writer, param_desc_ptr->name, value_str, error))
++			{
++				return FALSE;
++			}
++			break;
++		case JackDriverParamChar:
++			sprintf(value_str, "%c", param_ptr->value.c);
++			if (!jack_controller_settings_write_option(writer, param_desc_ptr->name, value_str, error))
++			{
++				return FALSE;
++			}
++			break;
++		case JackDriverParamString:
++			if (!jack_controller_settings_write_option(writer, param_desc_ptr->name, param_ptr->value.str, error))
++			{
++				return FALSE;
++			}
++			break;
++		case JackDriverParamBool:
++			if (!jack_controller_settings_write_option(writer, param_desc_ptr->name, param_ptr->value.i ? "true" : "false", error))
++			{
++				return FALSE;
++			}
++			break;
++		default:
++			jack_error("parameter of unknown type %d", param_desc_ptr->type);
++		}
++	}
++
++	if (xmlTextWriterEndElement(writer) == -1)
++	{
++		jack_controller_error(error, "xmlTextWriterEndElement() failed.");
++		return FALSE;
++	}
++
++	return TRUE;
++}
++
++gboolean
++jack_controller_settings_write_drivers(
++	struct jack_controller * controller_ptr,
++	xmlTextWriterPtr writer,
++	GError **error)
++{
++	JSList * node_ptr;
++	struct jack_controller_driver *driver_ptr;
++
++	node_ptr = controller_ptr->drivers;
++
++	if (xmlTextWriterStartElement(writer, BAD_CAST "drivers") == -1)
++	{
++		jack_controller_error(error, "xmlTextWriterStartElement() failed.");
++		return FALSE;
++	}
++
++	while (node_ptr != NULL)
++	{
++		driver_ptr = (struct jack_controller_driver *)node_ptr->data;
++
++		if (!jack_controller_settings_write_driver(
++			    controller_ptr,
++			    writer,
++			    driver_ptr,
++			    error))
++		{
++			return FALSE;
++		}
++
++		node_ptr = jack_slist_next(node_ptr);
++	}
++
++	if (xmlTextWriterEndElement(writer) == -1)
++	{
++		jack_controller_error(error, "xmlTextWriterEndElement() failed.");
++		return FALSE;
++	}
++
++	return TRUE;
++}
++
++gboolean
++jack_controller_settings_save(
++	struct jack_controller * controller_ptr,
++	GError **error)
++{
++	xmlTextWriterPtr writer;
++	gchar *filename;
++	gboolean ret;
++	time_t timestamp;
++	char timestamp_str[28];
++
++	time(&timestamp);
++	timestamp_str[0] = ' ';
++	ctime_r(&timestamp, timestamp_str + 1);
++	timestamp_str[25] = ' ';
++
++	ret = FALSE;
++
++	filename = g_strdup_printf("%s" JACKDBUS_CONF, g_jackdbus_dir);
++	if (filename == NULL)
++	{
++		jack_controller_error(error, "Out of memory.");
++		goto fail;
++	}
++
++	jack_info("saving settings to \"%s\"", filename);
++
++	writer = xmlNewTextWriterFilename(filename, 0);
++	if (writer == NULL)
++	{
++		jack_controller_error(error, "Error creating the xml writer.");
++		goto fail_free_filename;
++	}
++
++	if (xmlTextWriterSetIndent(writer, 1) == -1)
++	{
++		jack_controller_error(error, "xmlTextWriterSetIndent() failed.");
++		goto fail_free_writter;
++	}
++
++	if (xmlTextWriterStartDocument(writer, NULL, NULL, NULL) == -1)
++	{
++		jack_controller_error(error, "xmlTextWriterStartDocument() failed.");
++		goto fail_free_writter;
++	}
++
++	if (xmlTextWriterWriteComment(
++		    writer,
++		    BAD_CAST
++		    "\n"
++		    "JACK settings, as persisted by D-Bus object.\n"
++		    "You probably don't want to edit this because\n"
++		    "it will be overwritten next time jackdbus saves.\n") == -1)
++	{
++		jack_controller_error(error, "xmlTextWriterWriteComment() failed.");
++		goto fail_free_writter;
++	}
++
++	if (xmlTextWriterWriteComment(writer, BAD_CAST timestamp_str) == -1)
++	{
++		jack_controller_error(error, "xmlTextWriterWriteComment() failed.");
++		goto fail_free_writter;
++	}
++
++	if (xmlTextWriterStartElement(writer, BAD_CAST "jack") == -1)
++	{
++		jack_controller_error(error, "xmlTextWriterStartElement() failed.");
++		goto fail_free_writter;
++	}
++
++	if (!jack_controller_settings_write_engine(controller_ptr, writer, error))
++	{
++		goto fail_free_writter;
++	}
++
++	if (!jack_controller_settings_write_drivers(controller_ptr, writer, error))
++	{
++		goto fail_free_writter;
++	}
++
++	if (xmlTextWriterEndElement(writer) == -1)
++	{
++		jack_controller_error(error, "xmlTextWriterStartElement() failed.");
++		goto fail_free_writter;
++	}
++
++	if (xmlTextWriterEndDocument(writer) == -1)
++	{
++		jack_controller_error(error, "xmlTextWriterEndDocument() failed.");
++		goto fail_free_writter;
++	}
++
++	ret = TRUE;
++
++fail_free_writter:
++	xmlFreeTextWriter(writer);
++
++fail_free_filename:
++	g_free(filename);
++
++fail:
++	return ret;
++}
++
++void
++jack_controller_settings_set_bool_option(
++	const char *value_str,
++	int *value_ptr,
++	gboolean reverse)
++{
++	if (strcmp(value_str, "true") == 0)
++	{
++		*value_ptr = !reverse;
++	}
++	else if (strcmp(value_str, "false") == 0)
++	{
++		*value_ptr = reverse;
++	}
++	else
++	{
++		jack_error("ignoring unknown bool value \"%s\"", value_str);
++	}
++}
++
++void
++jack_controller_settings_set_sint_option(
++	const char *value_str,
++	int *value_ptr)
++{
++	*value_ptr = atoi(value_str);
++}
++
++void
++jack_controller_settings_set_uint_option(
++	const char *value_str,
++	unsigned int *value_ptr)
++{
++	*value_ptr = strtoul(value_str, NULL, 10);
++}
++
++void
++jack_controller_settings_set_char_option(
++	const char *value_str,
++	char *value_ptr)
++{
++	if (value_str[0] == 0 || value_str[1] != 0)
++	{
++		jack_error("invalid char option value \"%s\"", value_str);
++		return;
++	}
++
++	*value_ptr = *value_str;
++}
++
++void
++jack_controller_settings_set_string_option(
++	const char *value_str,
++	char *value_ptr,
++	size_t max_size)
++{
++	size_t size;
++
++	size = strlen(value_str);
++
++	if (size >= max_size)
++	{
++		jack_error("string option value \"%s\" is too long, max is %u chars (including terminating zero)", value_str, (unsigned int)max_size);
++		return;
++	}
++
++	strcpy(value_ptr, value_str);
++}
++
++void
++jack_controller_settings_read_engine(
++	struct jack_controller * controller_ptr,
++	xmlXPathContextPtr xpath_ctx_ptr)
++{
++	xmlXPathObjectPtr xpath_obj_ptr;
++	xmlBufferPtr content_buffer_ptr;
++	int i;
++	const char *option_name;
++	const char *option_value;
++	struct jack_controller_driver * driver_ptr;
++	JSList * node_ptr;
++
++	/* Evaluate xpath expression */
++	xpath_obj_ptr = xmlXPathEvalExpression((const xmlChar *)XPATH_ENGINE_OPTIONS_EXPRESSION, xpath_ctx_ptr);
++	if (xpath_obj_ptr == NULL)
++	{
++		jack_error("Unable to evaluate XPath expression \"%s\"", XPATH_ENGINE_OPTIONS_EXPRESSION);
++		goto exit;
++	}
++
++	if (xpath_obj_ptr->nodesetval == NULL || xpath_obj_ptr->nodesetval->nodeNr == 0)
++	{
++		jack_error("XPath \"%s\" evaluation returned no data", XPATH_ENGINE_OPTIONS_EXPRESSION);
++		goto free_xpath_obj;
++	}
++
++	content_buffer_ptr = xmlBufferCreate();
++	if (content_buffer_ptr == NULL)
++	{
++		jack_error("xmlBufferCreate() failed.");
++		goto free_xpath_obj;
++	}
++
++	for (i = 0 ; i < xpath_obj_ptr->nodesetval->nodeNr ; i++)
++	{
++		//jack_info("engine option \"%s\" at index %d", xmlGetProp(xpath_obj_ptr->nodesetval->nodeTab[i], BAD_CAST "name"), i);
++
++		if (xmlNodeBufGetContent(content_buffer_ptr, xpath_obj_ptr->nodesetval->nodeTab[i]) == -1)
++		{
++			jack_error("xmlNodeBufGetContent() failed.");
++			goto next_option;
++		}
++
++		option_name = (const char *)xmlGetProp(xpath_obj_ptr->nodesetval->nodeTab[i], BAD_CAST "name");
++		option_value = (const char *)xmlBufferContent(content_buffer_ptr);
++
++		jack_info("engine option \"%s\" with value \"%s\"", option_name, option_value);
++
++		if (strcmp(option_name, "driver") == 0)
++		{
++			for (node_ptr = controller_ptr->drivers ; node_ptr != NULL ; node_ptr = jack_slist_next(node_ptr))
++			{
++				driver_ptr = (struct jack_controller_driver *)node_ptr->data;
++
++				if (strcmp(driver_ptr->desc_ptr->name, option_value) == 0) {
++					jack_info("driver \"%s\" selected", driver_ptr->desc_ptr->name);
++					controller_ptr->driver_ptr = driver_ptr;
++					goto next_option;
++				}
++			}
++
++			jack_error("unknown driver '%s'", option_value);
++		}
++		else if (strcmp(option_name, "realtime") == 0)
++		{
++			jack_controller_settings_set_bool_option(option_value, &controller_ptr->realtime, FALSE);
++		}
++		else if (strcmp(option_name, "realtime-priority") == 0)
++		{
++			jack_controller_settings_set_sint_option(option_value, &controller_ptr->realtime_priority);
++		}
++		else if (strcmp(option_name, "no-mem-lock") == 0)
++		{
++			jack_controller_settings_set_bool_option(option_value, &controller_ptr->do_mlock, TRUE);
++		}
++		else if (strcmp(option_name, "temporary") == 0)
++		{
++			jack_controller_settings_set_bool_option(option_value, &controller_ptr->temporary, FALSE);
++		}
++		else if (strcmp(option_name, "verbose") == 0)
++		{
++			jack_controller_settings_set_bool_option(option_value, &controller_ptr->verbose, FALSE);
++		}
++		else if (strcmp(option_name, "client-timeout") == 0)
++		{
++			jack_controller_settings_set_sint_option(option_value, &controller_ptr->client_timeout);
++		}
++		else if (strcmp(option_name, "no-zombies") == 0)
++		{
++			jack_controller_settings_set_bool_option(option_value, &controller_ptr->nozombies, FALSE);
++		}
++		else if (strcmp(option_name, "port-max") == 0)
++		{
++			jack_controller_settings_set_uint_option(option_value, &controller_ptr->port_max);
++		}
++		else if (strcmp(option_name, "libs-unlock") == 0)
++		{
++			jack_controller_settings_set_bool_option(option_value, &controller_ptr->do_unlock, FALSE);
++		}
++		else
++		{
++			jack_error("ignoring unknown option \"%s\" with value \"%s\"", option_name, option_value);
++		}
++
++	next_option:
++		xmlBufferEmpty(content_buffer_ptr);
++	}
++
++//free_buffer:
++	xmlBufferFree(content_buffer_ptr);
++
++free_xpath_obj:
++	xmlXPathFreeObject(xpath_obj_ptr);
++
++exit:
++	return;
++}
++
++void
++jack_controller_settings_read_driver(
++	struct jack_controller * controller_ptr,
++	xmlXPathContextPtr xpath_ctx_ptr,
++	struct jack_controller_driver * driver_ptr)
++{
++	gchar *xpath;
++	xmlXPathObjectPtr xpath_obj_ptr;
++	xmlBufferPtr content_buffer_ptr;
++	int i;
++	const char *option_name;
++	const char *option_value;
++	jack_driver_param_desc_t * param_desc_ptr;
++	jack_driver_param_t * param_ptr;
++	int value_int;
++	unsigned int value_uint;
++
++	jack_info("reading options for driver \"%s\"", driver_ptr->desc_ptr->name);
++
++	xpath = g_strdup_printf(XPATH_DRIVER_OPTIONS_EXPRESSION, driver_ptr->desc_ptr->name);
++	if (xpath == NULL)
++	{
++		jack_error("Out of memory.");
++		goto exit;
++	}
++
++	//jack_info("xpath = \"%s\"", xpath);
++
++	/* Evaluate xpath expression */
++	xpath_obj_ptr = xmlXPathEvalExpression((const xmlChar *)xpath, xpath_ctx_ptr);
++	if (xpath_obj_ptr == NULL)
++	{
++		jack_error("Unable to evaluate XPath expression \"%s\"", xpath);
++		goto free_xpath;
++	}
++
++	if (xpath_obj_ptr->nodesetval == NULL || xpath_obj_ptr->nodesetval->nodeNr == 0)
++	{
++		//jack_info("XPath \"%s\" evaluation returned no data", xpath);
++		goto free_xpath_obj;
++	}
++
++	content_buffer_ptr = xmlBufferCreate();
++	if (content_buffer_ptr == NULL)
++	{
++		jack_error("xmlBufferCreate() failed.");
++		goto free_xpath_obj;
++	}
++
++	for (i = 0 ; i < xpath_obj_ptr->nodesetval->nodeNr ; i++)
++	{
++		//jack_info("driver option \"%s\" at index %d", xmlGetProp(xpath_obj_ptr->nodesetval->nodeTab[i], BAD_CAST "name"), i);
++
++		if (xmlNodeBufGetContent(content_buffer_ptr, xpath_obj_ptr->nodesetval->nodeTab[i]) == -1)
++		{
++			jack_error("xmlNodeBufGetContent() failed.");
++			goto next_option;
++		}
++
++		option_name = (const char *)xmlGetProp(xpath_obj_ptr->nodesetval->nodeTab[i], BAD_CAST "name");
++		option_value = (const char *)xmlBufferContent(content_buffer_ptr);
++
++		jack_info("driver option \"%s\" with value \"%s\"", option_name, option_value);
++
++		param_desc_ptr = jack_controller_find_parameter_descriptor_by_name(driver_ptr, option_name);
++		if (param_desc_ptr == NULL)
++		{
++			jack_error("Unknown parameter \"%s\" of driver \"%s\"", option_name, driver_ptr->desc_ptr->name);
++			goto next_option;
++		}
++
++		param_ptr = jack_controller_find_or_create_parameter(driver_ptr, param_desc_ptr);
++		if (param_ptr == NULL)
++		{
++			jack_error("driver parameter creation failed");
++			goto next_option;
++		}
++
++		switch (param_desc_ptr->type)
++		{
++		case JackDriverParamInt:
++			jack_controller_settings_set_sint_option(option_value, &value_int);
++			param_ptr->value.i = value_int;
++			break;
++		case JackDriverParamUInt:
++			jack_controller_settings_set_uint_option(option_value, &value_uint);
++			param_ptr->value.ui = value_uint;
++			break;
++		case JackDriverParamChar:
++			jack_controller_settings_set_char_option(option_value, &param_ptr->value.c);
++			break;
++		case JackDriverParamString:
++			jack_controller_settings_set_string_option(option_value, param_ptr->value.str, sizeof(param_ptr->value.str));
++			break;
++		case JackDriverParamBool:
++			jack_controller_settings_set_bool_option(option_value, &value_int, FALSE);
++			param_ptr->value.i = value_int;
++			break;
++		default:
++			jack_error("Parameter \"%s\" of driver \"%s\" is of unknown type %d",
++				   param_desc_ptr->name,
++				   driver_ptr->desc_ptr->name,
++				   param_desc_ptr->type);
++		}
++
++	next_option:
++		xmlBufferEmpty(content_buffer_ptr);
++	}
++
++//free_buffer:
++	xmlBufferFree(content_buffer_ptr);
++
++free_xpath_obj:
++	xmlXPathFreeObject(xpath_obj_ptr);
++
++free_xpath:
++	g_free(xpath);
++
++exit:
++	return;
++}
++
++void
++jack_controller_settings_read_drivers(
++	struct jack_controller * controller_ptr,
++	xmlXPathContextPtr xpath_ctx_ptr)
++{
++	xmlXPathObjectPtr xpath_obj_ptr;
++	int i;
++	const char *driver_name;
++	struct jack_controller_driver * driver_ptr;
++	JSList * node_ptr;
++
++	/* Evaluate xpath expression */
++	xpath_obj_ptr = xmlXPathEvalExpression((const xmlChar *)XPATH_DRIVERS_EXPRESSION, xpath_ctx_ptr);
++	if (xpath_obj_ptr == NULL)
++	{
++		jack_error("Unable to evaluate XPath expression \"%s\"", XPATH_DRIVERS_EXPRESSION);
++		goto exit;
++	}
++
++	if (xpath_obj_ptr->nodesetval == NULL || xpath_obj_ptr->nodesetval->nodeNr == 0)
++	{
++		jack_error("XPath \"%s\" evaluation returned no data", XPATH_DRIVERS_EXPRESSION);
++		goto free_xpath_obj;
++	}
++
++	for (i = 0 ; i < xpath_obj_ptr->nodesetval->nodeNr ; i++)
++	{
++		driver_name = (const char *)xmlGetProp(xpath_obj_ptr->nodesetval->nodeTab[i], BAD_CAST "name");
++		//jack_info("setting for driver \"%s\" found", driver_name);
++		for (node_ptr = controller_ptr->drivers ; node_ptr != NULL ; node_ptr = jack_slist_next(node_ptr))
++		{
++			driver_ptr = (struct jack_controller_driver *)node_ptr->data;
++
++			if (strcmp(driver_ptr->desc_ptr->name, driver_name) == 0) {
++				jack_controller_settings_read_driver(controller_ptr, xpath_ctx_ptr, driver_ptr);
++				goto next_driver;
++			}
++		}
++
++		jack_error("ignoring settings for unknown driver \"%s\"", driver_name);
++
++	next_driver:
++		;
++	}
++
++free_xpath_obj:
++	xmlXPathFreeObject(xpath_obj_ptr);
++
++exit:
++	return;
++}
++
++void
++jack_controller_settings_load(
++	struct jack_controller * controller_ptr)
++{
++	gchar *filename;
++	xmlDocPtr doc_ptr;
++	xmlXPathContextPtr xpath_ctx_ptr;
++
++	filename = g_strdup_printf("%s" JACKDBUS_CONF, g_jackdbus_dir);
++	if (filename == NULL)
++	{
++		jack_error("Out of memory.");
++		goto exit;
++	}
++
++	jack_info("loading settings from \"%s\"", filename);
++
++	doc_ptr = xmlParseFile(filename);
++	if (doc_ptr == NULL)
++	{
++		jack_error("Failed to parse playlist \"%s\"", filename);
++		goto free_filename;
++	}
++
++	/* Create xpath evaluation context */
++	xpath_ctx_ptr = xmlXPathNewContext(doc_ptr);
++	if (xpath_ctx_ptr == NULL)
++	{
++		jack_error("Unable to create new XPath context");
++		goto free_doc;
++	}
++
++	jack_controller_settings_read_engine(controller_ptr, xpath_ctx_ptr);
++	jack_controller_settings_read_drivers(controller_ptr, xpath_ctx_ptr);
++
++	xmlXPathFreeContext(xpath_ctx_ptr);
++
++free_doc:
++	xmlFreeDoc(doc_ptr);
++
++free_filename:
++	g_free(filename);
++
++exit:
++	return;
++}
++
++void
++jack_controller_settings_save_auto(
++	struct jack_controller * controller_ptr)
++{
++	jack_controller_settings_save(controller_ptr, NULL);
++}
++
++#else  /* HAVE_LIBXML2 */
++
++gboolean
++jack_controller_settings_save(
++	struct jack_controller * controller_ptr,
++	GError **error)
++{
++	jack_error("jackdbus compiled without settings persistence");
++	return TRUE;
++}
++
++void
++jack_controller_settings_load(
++	struct jack_controller * controller_ptr)
++{
++}
++
++void
++jack_controller_settings_save_auto(
++	struct jack_controller * controller_ptr)
++{
++}
++
++#endif
++
++
++void
++jack_controller_run(
++	JackController * object_ptr)
++{
++	struct jack_controller * controller_ptr;
++
++	controller_ptr = JACK_CONTROLLER_GET_PRIVATE(object_ptr);
++
++	controller_ptr->loop = g_main_loop_new(NULL, FALSE);
++	controller_ptr->manually_started = FALSE;
++
++	if (!jack_drivers_load(controller_ptr))
++	{
++		return;
++	}
++
++	jack_controller_settings_load(controller_ptr);
++
++	jack_info("Starting loop...");
++	g_main_loop_run(controller_ptr->loop);
++
++	if (controller_ptr->engine != NULL)
++	{
++		jack_controller_stop_server(object_ptr, NULL);
++		
++	}
++}
++
++gboolean
++jack_controller_start_server(
++	JackController * object_ptr,
++	GError ** error)
++{
++	struct jack_controller * controller_ptr;
++	int rc;
++
++	controller_ptr = JACK_CONTROLLER_GET_PRIVATE(object_ptr);
++
++	jack_info("Starting jack server...");
++
++	if (controller_ptr->engine != NULL)
++	{
++		jack_info("Already started.");
++		return TRUE;
++	}
++
++	if (controller_ptr->driver_ptr == NULL)
++	{
++		jack_controller_error(error, "Select driver first!");
++		goto fail;
++	}
++
++	rc = jack_register_server(controller_ptr->server_name);
++	switch (rc)
++	{
++	case EEXIST:
++		jack_controller_error(error, "`%s' server already active", controller_ptr->server_name);
++		goto fail;
++	case ENOSPC:
++		jack_controller_error(error, "too many servers already active");
++		goto fail;
++	case ENOMEM:
++		jack_controller_error(error, "no access to shm registry");
++		goto fail;
++	}
++
++	if (controller_ptr->verbose)
++	{
++		jack_info ("server `%s' registered", controller_ptr->server_name);
++	}
++
++	/* clean up shared memory and files from any previous
++	 * instance of this server name */
++	jack_cleanup_shm();
++	jack_cleanup_files(controller_ptr->server_name);
++
++	if (!controller_ptr->realtime && controller_ptr->client_timeout == 0)
++		controller_ptr->client_timeout = 500; /* 0.5 sec; usable when non realtime. */
++
++	/* get the engine/driver started */
++
++	controller_ptr->engine = jack_engine_new(
++		controller_ptr->realtime,
++		controller_ptr->realtime_priority, 
++		controller_ptr->do_mlock,
++		controller_ptr->do_unlock,
++		controller_ptr->server_name,
++		controller_ptr->temporary,
++		controller_ptr->verbose,
++		controller_ptr->client_timeout,
++		controller_ptr->port_max,
++		getpid(),
++		controller_ptr->frame_time_offset, 
++		controller_ptr->nozombies,
++		NULL);
++	if (controller_ptr->engine == NULL)
++	{
++		jack_controller_error(error, "Cannot create engine!");
++		goto fail_unregister_server;
++	}
++
++	jack_info("loading driver \"%s\" ...", controller_ptr->driver_ptr->desc_ptr->name);
++	
++	if (jack_engine_load_driver(controller_ptr->engine, controller_ptr->driver_ptr->desc_ptr, controller_ptr->driver_ptr->params)) {
++		jack_controller_error(error, "cannot load driver module %s", controller_ptr->driver_ptr->desc_ptr->name);
++		goto fail_delete_engine;
++	}
++
++	if (controller_ptr->engine->driver->start(controller_ptr->engine->driver) != 0) {
++		jack_controller_error(error, "cannot start \"%s\" driver", controller_ptr->driver_ptr->desc_ptr->name);
++		goto fail_delete_engine;
++	}
++
++	return TRUE;
++
++fail_unregister_server:
++	if (controller_ptr->verbose)
++	{
++		jack_info("cleaning up shared memory");
++	}
++
++	jack_cleanup_shm();
++
++	if (controller_ptr->verbose)
++	{
++		jack_info("cleaning up files");
++	}
++
++	jack_cleanup_files(controller_ptr->server_name);
++
++	if (controller_ptr->verbose)
++	{
++		jack_info("unregistering server `%s'", controller_ptr->server_name);
++	}
++
++	jack_unregister_server(controller_ptr->server_name);
++
++fail_delete_engine:
++	jack_engine_delete(controller_ptr->engine);
++	controller_ptr->engine = NULL;
++
++fail:
++	return FALSE;
++}
++
++gboolean
++jack_controller_stop_server(
++	JackController * object_ptr,
++	GError ** error)
++{
++	struct jack_controller * controller_ptr;
++
++	controller_ptr = JACK_CONTROLLER_GET_PRIVATE(object_ptr);
++
++	if (controller_ptr->engine == NULL)
++	{
++		return TRUE;
++	}
++
++	jack_info("Stop jack server...");
++
++	jack_engine_delete(controller_ptr->engine);
++
++	/* clean up shared memory and files from this server instance */
++	if (controller_ptr->verbose)
++	{
++		jack_info("cleaning up shared memory");
++	}
++
++	jack_cleanup_shm();
++
++	if (controller_ptr->verbose)
++	{
++		jack_info("cleaning up files");
++	}
++
++	jack_cleanup_files(controller_ptr->server_name);
++
++	if (controller_ptr->verbose)
++	{
++		jack_info("unregistering server `%s'", controller_ptr->server_name);
++	}
++
++	jack_unregister_server(controller_ptr->server_name);
++
++	controller_ptr->engine = NULL;
++
++	return TRUE;
++}
++
++gboolean
++jack_controller_get_available_drivers(
++	JackController * object_ptr,
++	gchar *** drivers_list,
++	GError ** error)
++{
++	struct jack_controller * controller_ptr;
++	gchar ** array;
++	unsigned int i;
++	struct jack_controller_driver * driver_ptr;
++	JSList * node_ptr;
++
++	controller_ptr = JACK_CONTROLLER_GET_PRIVATE(object_ptr);
++
++	array = g_malloc((controller_ptr->drivers_count + 1) * sizeof(gchar *));
++
++	node_ptr = controller_ptr->drivers;
++	i = 0;
++
++	while (node_ptr != NULL)
++	{
++		assert(i < controller_ptr->drivers_count);
++
++		driver_ptr = (struct jack_controller_driver *)node_ptr->data;
++
++		array[i] = g_strdup(driver_ptr->desc_ptr->name);
++
++		node_ptr = jack_slist_next(node_ptr);
++		i++;
++	}
++
++	assert(i == controller_ptr->drivers_count);
++	array[i] = NULL;
++
++	*drivers_list = array;
++
++	return TRUE;
++}
++
++gboolean
++jack_controller_get_selected_driver(
++	JackController * object_ptr,
++	gchar ** driver_name,
++	GError ** error)
++{
++	struct jack_controller * controller_ptr;
++
++	controller_ptr = JACK_CONTROLLER_GET_PRIVATE(object_ptr);
++
++	if (controller_ptr->driver_ptr == NULL)
++	{
++		*driver_name = NULL;
++	}
++	else
++	{
++		*driver_name = g_strdup(controller_ptr->driver_ptr->desc_ptr->name);
++	}
++
++	return TRUE;
++}
++
++gboolean
++jack_controller_select_driver(
++	JackController * object_ptr,
++	const gchar * driver_name,
++	GError ** error)
++{
++	struct jack_controller * controller_ptr;
++	struct jack_controller_driver * driver_ptr;
++	JSList * node_ptr;
++
++	controller_ptr = JACK_CONTROLLER_GET_PRIVATE(object_ptr);
++
++	for (node_ptr = controller_ptr->drivers ; node_ptr != NULL ; node_ptr = jack_slist_next(node_ptr))
++	{
++		driver_ptr = (struct jack_controller_driver *)node_ptr->data;
++
++		if (strcmp(driver_ptr->desc_ptr->name, driver_name) == 0) {
++			goto found;
++		}
++	}
++
++	jack_controller_error(error, "unknown driver '%s'", driver_name);
++	return FALSE;
++
++found:
++	jack_info("driver \"%s\" selected", driver_ptr->desc_ptr->name);
++
++	controller_ptr->driver_ptr = driver_ptr;
++
++	jack_controller_settings_save_auto(controller_ptr);
++
++	return TRUE;
++}
++
++gboolean
++jack_controller_get_driver_parameter_names(
++	JackController * object_ptr,
++	gchar *** params_list,
++	GError ** error)
++{
++	struct jack_controller * controller_ptr;
++	gchar ** array;
++	unsigned int i;
++
++	controller_ptr = JACK_CONTROLLER_GET_PRIVATE(object_ptr);
++
++	if (controller_ptr->driver_ptr == NULL)
++	{
++		jack_controller_error(error, "Select driver before operating on its parameters!");
++		return FALSE;
++	}
++
++	if (controller_ptr->verbose)
++	{
++		jack_info("Getting parameters for driver \"%s\"", controller_ptr->driver_ptr->desc_ptr->name);
++	}
++
++	array = g_malloc((controller_ptr->driver_ptr->desc_ptr->nparams + 1) * sizeof(gchar *));
++
++	for (i = 0; i < controller_ptr->driver_ptr->desc_ptr->nparams ; i++)
++	{
++		array[i] = g_strdup(controller_ptr->driver_ptr->desc_ptr->params[i].name);
++	}
++
++	array[i] = NULL;
++
++	*params_list = array;
++
++	return TRUE;
++}
++
++gboolean
++jack_controller_get_driver_parameter_short_description(
++	JackController * object_ptr,
++	const gchar * parameter,
++	gchar ** description,
++	GError ** error)
++{
++	struct jack_controller * controller_ptr;
++	unsigned int i;
++
++	controller_ptr = JACK_CONTROLLER_GET_PRIVATE(object_ptr);
++
++	if (controller_ptr->driver_ptr == NULL)
++	{
++		jack_controller_error(error, "Select driver before operating on its parameters!");
++		return FALSE;
++	}
++
++	for (i = 0; i < controller_ptr->driver_ptr->desc_ptr->nparams ; i++)
++	{
++		if (strcmp(controller_ptr->driver_ptr->desc_ptr->params[i].name, parameter) == 0)
++		{
++			*description = g_strdup(controller_ptr->driver_ptr->desc_ptr->params[i].short_desc);
++			return TRUE;
++		}
++	}
++
++	jack_controller_error(error, "Unknown parameter \"%s\" of driver \"%s\"", parameter, controller_ptr->driver_ptr->desc_ptr->name);
++	return FALSE;
++}
++
++gboolean
++jack_controller_get_driver_parameter_long_description(
++	JackController * object_ptr,
++	const gchar * parameter,
++	gchar ** description,
++	GError ** error)
++{
++	struct jack_controller * controller_ptr;
++	unsigned int i;
++
++	controller_ptr = JACK_CONTROLLER_GET_PRIVATE(object_ptr);
++
++	if (controller_ptr->driver_ptr == NULL)
++	{
++		jack_controller_error(error, "Select driver before operating on its parameters!");
++		return FALSE;
++	}
++
++	for (i = 0; i < controller_ptr->driver_ptr->desc_ptr->nparams ; i++)
++	{
++		if (strcmp(controller_ptr->driver_ptr->desc_ptr->params[i].name, parameter) == 0)
++		{
++			*description = g_strdup(controller_ptr->driver_ptr->desc_ptr->params[i].long_desc);
++			return TRUE;
++		}
++	}
++
++	jack_controller_error(error, "Unknown parameter \"%s\" of driver \"%s\"", parameter, controller_ptr->driver_ptr->desc_ptr->name);
++	return FALSE;
++}
++
++gboolean
++jack_controller_get_driver_parameter_type(
++	JackController * object_ptr,
++	const gchar * parameter,
++	guchar * type,
++	GError ** error)
++{
++	struct jack_controller * controller_ptr;
++	unsigned int i;
++
++	controller_ptr = JACK_CONTROLLER_GET_PRIVATE(object_ptr);
++
++	if (controller_ptr->driver_ptr == NULL)
++	{
++		jack_controller_error(error, "Select driver before operating on its parameters!");
++		return FALSE;
++	}
++
++	for (i = 0; i < controller_ptr->driver_ptr->desc_ptr->nparams ; i++)
++	{
++		if (strcmp(controller_ptr->driver_ptr->desc_ptr->params[i].name, parameter) == 0)
++		{
++			*type = controller_ptr->driver_ptr->desc_ptr->params[i].type;
++			return TRUE;
++		}
++	}
++
++	jack_controller_error(error, "Unknown parameter \"%s\" of driver \"%s\"", parameter, controller_ptr->driver_ptr->desc_ptr->name);
++	return FALSE;
++}
++
++gboolean
++jack_controller_get_driver_parameter_type_string(
++	JackController * object_ptr,
++	const gchar * parameter,
++	gchar ** type,
++	GError ** error)
++{
++	struct jack_controller * controller_ptr;
++	unsigned int i;
++
++	controller_ptr = JACK_CONTROLLER_GET_PRIVATE(object_ptr);
++
++	if (controller_ptr->driver_ptr == NULL)
++	{
++		jack_controller_error(error, "Select driver before operating on its parameters!");
++		return FALSE;
++	}
++
++	for (i = 0; i < controller_ptr->driver_ptr->desc_ptr->nparams ; i++)
++	{
++		if (strcmp(controller_ptr->driver_ptr->desc_ptr->params[i].name, parameter) == 0)
++		{
++			switch (controller_ptr->driver_ptr->desc_ptr->params[i].type)
++			{
++			case JackDriverParamInt:
++				*type = g_strdup("sint");
++				return TRUE;
++			case JackDriverParamUInt:
++				*type = g_strdup("uint");
++				return TRUE;
++			case JackDriverParamChar:
++				*type = g_strdup("char");
++				return TRUE;
++			case JackDriverParamString:
++				*type = g_strdup("str");
++				return TRUE;
++			case JackDriverParamBool:
++				*type = g_strdup("bool");
++				return TRUE;
++			}
++
++			jack_controller_error(
++				error,
++				"Parameter \"%s\" of driver \"%s\" is of unknown type %d",
++				parameter,
++				controller_ptr->driver_ptr->desc_ptr->name,
++				controller_ptr->driver_ptr->desc_ptr->params[i].type);
++			return FALSE;
++		}
++	}
++
++	jack_controller_error(error, "Unknown parameter \"%s\" of driver \"%s\"", parameter, controller_ptr->driver_ptr->desc_ptr->name);
++	return FALSE;
++}
++
++gboolean
++jack_controller_get_driver_parameter_value_string(
++	JackController * object_ptr,
++	const gchar * parameter,
++	gboolean * isset,
++	gchar ** default_value,
++	gchar ** value,
++	GError ** error)
++{
++	struct jack_controller * controller_ptr;
++	jack_driver_param_desc_t * param_desc_ptr;
++	jack_driver_param_t * param_ptr;
++
++	controller_ptr = JACK_CONTROLLER_GET_PRIVATE(object_ptr);
++
++	if (controller_ptr->driver_ptr == NULL)
++	{
++		jack_controller_error(error, "Select driver before operating on its parameters!");
++		return FALSE;
++	}
++
++	param_desc_ptr = jack_controller_find_parameter_descriptor_by_name_current_driver(controller_ptr, parameter);
++	if (param_desc_ptr == NULL)
++	{
++		jack_controller_error(error, "Unknown parameter \"%s\" of driver \"%s\"", parameter, controller_ptr->driver_ptr->desc_ptr->name);
++		return FALSE;
++	}
++
++	if (param_desc_ptr->type != JackDriverParamString)
++	{
++		jack_controller_error(error, "Parameter \"%s\" of driver \"%s\" is not string", parameter, controller_ptr->driver_ptr->desc_ptr->name);
++		return FALSE;
++	}
++
++	*default_value = g_strdup(param_desc_ptr->value.str);
++
++	param_ptr = jack_controller_find_parameter_current_driver(controller_ptr, param_desc_ptr);
++	if (param_ptr == NULL)
++	{
++		*isset = FALSE;
++		*value = g_strdup(*default_value);
++	}
++	else
++	{
++		*isset = TRUE;
++		*value = g_strdup(param_ptr->value.str);
++	}
++
++	return TRUE;
++}
++
++gboolean
++jack_controller_get_driver_parameter_value_bool(
++	JackController * object_ptr,
++	const gchar * parameter,
++	gboolean * isset,
++	gboolean * default_value,
++	gboolean * value,
++	GError ** error)
++{
++	struct jack_controller * controller_ptr;
++	jack_driver_param_desc_t * param_desc_ptr;
++	jack_driver_param_t * param_ptr;
++
++	controller_ptr = JACK_CONTROLLER_GET_PRIVATE(object_ptr);
++
++	if (controller_ptr->driver_ptr == NULL)
++	{
++		jack_controller_error(error, "Select driver before operating on its parameters!");
++		return FALSE;
++	}
++
++	param_desc_ptr = jack_controller_find_parameter_descriptor_by_name_current_driver(controller_ptr, parameter);
++	if (param_desc_ptr == NULL)
++	{
++		jack_controller_error(error, "Unknown parameter \"%s\" of driver \"%s\"", parameter, controller_ptr->driver_ptr->desc_ptr->name);
++		return FALSE;
++	}
++
++	if (param_desc_ptr->type != JackDriverParamBool)
++	{
++		jack_controller_error(error, "Parameter \"%s\" of driver \"%s\" is not boolean", parameter, controller_ptr->driver_ptr->desc_ptr->name);
++		return FALSE;
++	}
++
++	*default_value = param_desc_ptr->value.i ? TRUE : FALSE;
++
++	param_ptr = jack_controller_find_parameter_current_driver(controller_ptr, param_desc_ptr);
++	if (param_ptr == NULL)
++	{
++		*isset = FALSE;
++		*value = *default_value;
++	}
++	else
++	{
++		*isset = TRUE;
++		*value = param_ptr->value.i ? TRUE : FALSE;
++	}
++
++	return TRUE;
++}
++
++gboolean
++jack_controller_get_driver_parameter_value_char(
++	JackController * object_ptr,
++	const gchar * parameter,
++	gboolean * isset,
++	guchar * default_value,
++	guchar * value,
++	GError ** error)
++{
++	struct jack_controller * controller_ptr;
++	jack_driver_param_desc_t * param_desc_ptr;
++	jack_driver_param_t * param_ptr;
++
++	controller_ptr = JACK_CONTROLLER_GET_PRIVATE(object_ptr);
++
++	if (controller_ptr->driver_ptr == NULL)
++	{
++		jack_controller_error(error, "Select driver before operating on its parameters!");
++		return FALSE;
++	}
++
++	param_desc_ptr = jack_controller_find_parameter_descriptor_by_name_current_driver(controller_ptr, parameter);
++	if (param_desc_ptr == NULL)
++	{
++		jack_controller_error(error, "Unknown parameter \"%s\" of driver \"%s\"", parameter, controller_ptr->driver_ptr->desc_ptr->name);
++		return FALSE;
++	}
++
++	if (param_desc_ptr->type != JackDriverParamChar)
++	{
++		jack_controller_error(error, "Parameter \"%s\" of driver \"%s\" is not char", parameter, controller_ptr->driver_ptr->desc_ptr->name);
++		return FALSE;
++	}
++
++	*default_value = param_desc_ptr->value.c;
++
++	param_ptr = jack_controller_find_parameter_current_driver(controller_ptr, param_desc_ptr);
++	if (param_ptr == NULL)
++	{
++		*isset = FALSE;
++		*value = *default_value;
++	}
++	else
++	{
++		*isset = TRUE;
++		*value = param_ptr->value.c;
++	}
++
++	return TRUE;
++}
++
++gboolean
++jack_controller_get_driver_parameter_value_int(
++	JackController * object_ptr,
++	const gchar * parameter,
++	gboolean * isset,
++	gint * default_value,
++	gint * value,
++	GError ** error)
++{
++	struct jack_controller * controller_ptr;
++	jack_driver_param_desc_t * param_desc_ptr;
++	jack_driver_param_t * param_ptr;
++
++	controller_ptr = JACK_CONTROLLER_GET_PRIVATE(object_ptr);
++
++	if (controller_ptr->driver_ptr == NULL)
++	{
++		jack_controller_error(error, "Select driver before operating on its parameters!");
++		return FALSE;
++	}
++
++	param_desc_ptr = jack_controller_find_parameter_descriptor_by_name_current_driver(controller_ptr, parameter);
++	if (param_desc_ptr == NULL)
++	{
++		jack_controller_error(error, "Unknown parameter \"%s\" of driver \"%s\"", parameter, controller_ptr->driver_ptr->desc_ptr->name);
++		return FALSE;
++	}
++
++	if (param_desc_ptr->type != JackDriverParamInt)
++	{
++		jack_controller_error(error, "Parameter \"%s\" of driver \"%s\" is not int", parameter, controller_ptr->driver_ptr->desc_ptr->name);
++		return FALSE;
++	}
++
++	*default_value = param_desc_ptr->value.i;
++
++	param_ptr = jack_controller_find_parameter_current_driver(controller_ptr, param_desc_ptr);
++	if (param_ptr == NULL)
++	{
++		*isset = FALSE;
++		*value = *default_value;
++	}
++	else
++	{
++		*isset = TRUE;
++		*value = param_ptr->value.i;
++	}
++
++	return TRUE;
++}
++
++gboolean
++jack_controller_get_driver_parameter_value_uint(
++	JackController * object_ptr,
++	const gchar * parameter,
++	gboolean * isset,
++	guint * default_value,
++	guint * value,
++	GError ** error)
++{
++	struct jack_controller * controller_ptr;
++	jack_driver_param_desc_t * param_desc_ptr;
++	jack_driver_param_t * param_ptr;
++
++	controller_ptr = JACK_CONTROLLER_GET_PRIVATE(object_ptr);
++
++	if (controller_ptr->driver_ptr == NULL)
++	{
++		jack_controller_error(error, "Select driver before operating on its parameters!");
++		return FALSE;
++	}
++
++	param_desc_ptr = jack_controller_find_parameter_descriptor_by_name_current_driver(controller_ptr, parameter);
++	if (param_desc_ptr == NULL)
++	{
++		jack_controller_error(error, "Unknown parameter \"%s\" of driver \"%s\"", parameter, controller_ptr->driver_ptr->desc_ptr->name);
++		return FALSE;
++	}
++
++	if (param_desc_ptr->type != JackDriverParamUInt)
++	{
++		jack_controller_error(error, "Parameter \"%s\" of driver \"%s\" is not uint", parameter, controller_ptr->driver_ptr->desc_ptr->name);
++		return FALSE;
++	}
++
++	*default_value = param_desc_ptr->value.ui;
++
++	param_ptr = jack_controller_find_parameter_current_driver(controller_ptr, param_desc_ptr);
++	if (param_ptr == NULL)
++	{
++		*isset = FALSE;
++		*value = *default_value;
++	}
++	else
++	{
++		*isset = TRUE;
++		*value = param_ptr->value.ui;
++	}
++
++	return TRUE;
++}
++
++gboolean
++jack_controller_set_driver_parameter_value_string(
++	JackController * object_ptr,
++	const gchar * parameter,
++	gchar * value,
++	GError ** error)
++{
++	struct jack_controller * controller_ptr;
++	jack_driver_param_desc_t * param_desc_ptr;
++	jack_driver_param_t * param_ptr;
++	size_t value_len;
++
++	controller_ptr = JACK_CONTROLLER_GET_PRIVATE(object_ptr);
++
++	if (controller_ptr->driver_ptr == NULL)
++	{
++		jack_controller_error(error, "Select driver before operating on its parameters!");
++		return FALSE;
++	}
++
++	param_desc_ptr = jack_controller_find_parameter_descriptor_by_name_current_driver(controller_ptr, parameter);
++	if (param_desc_ptr == NULL)
++	{
++		jack_controller_error(error, "Unknown parameter \"%s\" of driver \"%s\"", parameter, controller_ptr->driver_ptr->desc_ptr->name);
++		return FALSE;
++	}
++
++	if (param_desc_ptr->type != JackDriverParamString)
++	{
++		jack_controller_error(error, "Parameter \"%s\" of driver \"%s\" is not string", parameter, controller_ptr->driver_ptr->desc_ptr->name);
++		return FALSE;
++	}
++
++	value_len = strlen(value);
++
++	if (value_len > JACK_DRIVER_PARAM_STRING_MAX)
++	{
++		jack_controller_error(
++			error,
++			"Max size of string parameter values is %u chars but value supplied is %u chars",
++			JACK_DRIVER_PARAM_STRING_MAX,
++			value_len);
++		return FALSE;
++	}
++
++	jack_info("Setting parameter \"%s\" of driver \"%s\" to \"%s\"", parameter, controller_ptr->driver_ptr->desc_ptr->name, value);
++
++	param_ptr = jack_controller_find_or_create_parameter_current_driver(controller_ptr, param_desc_ptr);
++	if (param_ptr == NULL)
++	{
++		jack_controller_error(error, "driver parameter creation failed");
++		return FALSE;
++	}
++
++	memcpy(param_ptr->value.str, value, value_len + 1);
++
++	jack_controller_settings_save_auto(controller_ptr);
++
++	return TRUE;
++}
++
++gboolean
++jack_controller_set_driver_parameter_value_bool(
++	JackController * object_ptr,
++	const gchar * parameter,
++	gboolean value,
++	GError ** error)
++{
++	struct jack_controller * controller_ptr;
++	jack_driver_param_desc_t * param_desc_ptr;
++	jack_driver_param_t * param_ptr;
++
++	controller_ptr = JACK_CONTROLLER_GET_PRIVATE(object_ptr);
++
++	if (controller_ptr->driver_ptr == NULL)
++	{
++		jack_controller_error(error, "Select driver before operating on its parameters!");
++		return FALSE;
++	}
++
++	param_desc_ptr = jack_controller_find_parameter_descriptor_by_name_current_driver(controller_ptr, parameter);
++	if (param_desc_ptr == NULL)
++	{
++		jack_controller_error(error, "Unknown parameter \"%s\" of driver \"%s\"", parameter, controller_ptr->driver_ptr->desc_ptr->name);
++		return FALSE;
++	}
++
++	if (param_desc_ptr->type != JackDriverParamBool)
++	{
++		jack_controller_error(error, "Parameter \"%s\" of driver \"%s\" is not boolean", parameter, controller_ptr->driver_ptr->desc_ptr->name);
++		return FALSE;
++	}
++
++	jack_info("Setting parameter \"%s\" of driver \"%s\" to %s", parameter, controller_ptr->driver_ptr->desc_ptr->name, value ? "true" : "false");
++
++	param_ptr = jack_controller_find_or_create_parameter_current_driver(controller_ptr, param_desc_ptr);
++	if (param_ptr == NULL)
++	{
++		jack_controller_error(error, "driver parameter creation failed");
++		return FALSE;
++	}
++
++	param_ptr->value.i = value ? TRUE : FALSE;
++
++	jack_controller_settings_save_auto(controller_ptr);
++
++	return TRUE;
++}
++
++gboolean
++jack_controller_set_driver_parameter_value_char(
++	JackController * object_ptr,
++	const gchar * parameter,
++	guchar value,
++	GError ** error)
++{
++	struct jack_controller * controller_ptr;
++	jack_driver_param_desc_t * param_desc_ptr;
++	jack_driver_param_t * param_ptr;
++
++	controller_ptr = JACK_CONTROLLER_GET_PRIVATE(object_ptr);
++
++	if (controller_ptr->driver_ptr == NULL)
++	{
++		jack_controller_error(error, "Select driver before operating on its parameters!");
++		return FALSE;
++	}
++
++	param_desc_ptr = jack_controller_find_parameter_descriptor_by_name_current_driver(controller_ptr, parameter);
++	if (param_desc_ptr == NULL)
++	{
++		jack_controller_error(error, "Unknown parameter \"%s\" of driver \"%s\"", parameter, controller_ptr->driver_ptr->desc_ptr->name);
++		return FALSE;
++	}
++
++	if (param_desc_ptr->type != JackDriverParamChar)
++	{
++		jack_controller_error(error, "Parameter \"%s\" of driver \"%s\" is not char", parameter, controller_ptr->driver_ptr->desc_ptr->name);
++		return FALSE;
++	}
++
++	jack_info("Setting parameter \"%s\" of driver \"%s\" to %c", parameter, controller_ptr->driver_ptr->desc_ptr->name, value);
++
++	param_ptr = jack_controller_find_or_create_parameter_current_driver(controller_ptr, param_desc_ptr);
++	if (param_ptr == NULL)
++	{
++		jack_controller_error(error, "driver parameter creation failed");
++		return FALSE;
++	}
++
++	param_ptr->value.c = value;
++
++	jack_controller_settings_save_auto(controller_ptr);
++
++	return TRUE;
++}
++
++gboolean
++jack_controller_set_driver_parameter_value_int(
++	JackController * object_ptr,
++	const gchar * parameter,
++	gint value,
++	GError ** error)
++{
++	struct jack_controller * controller_ptr;
++	jack_driver_param_desc_t * param_desc_ptr;
++	jack_driver_param_t * param_ptr;
++
++	controller_ptr = JACK_CONTROLLER_GET_PRIVATE(object_ptr);
++
++	if (controller_ptr->driver_ptr == NULL)
++	{
++		jack_controller_error(error, "Select driver before operating on its parameters!");
++		return FALSE;
++	}
++
++	param_desc_ptr = jack_controller_find_parameter_descriptor_by_name_current_driver(controller_ptr, parameter);
++	if (param_desc_ptr == NULL)
++	{
++		jack_controller_error(error, "Unknown parameter \"%s\" of driver \"%s\"", parameter, controller_ptr->driver_ptr->desc_ptr->name);
++		return FALSE;
++	}
++
++	if (param_desc_ptr->type != JackDriverParamInt)
++	{
++		jack_controller_error(error, "Parameter \"%s\" of driver \"%s\" is not sint", parameter, controller_ptr->driver_ptr->desc_ptr->name);
++		return FALSE;
++	}
++
++	jack_info("Setting parameter \"%s\" of driver \"%s\" to %d", parameter, controller_ptr->driver_ptr->desc_ptr->name, value);
++
++	param_ptr = jack_controller_find_or_create_parameter_current_driver(controller_ptr, param_desc_ptr);
++	if (param_ptr == NULL)
++	{
++		jack_controller_error(error, "driver parameter creation failed");
++		return FALSE;
++	}
++
++	param_ptr->value.i = value;
++
++	jack_controller_settings_save_auto(controller_ptr);
++
++	return TRUE;
++}
++
++gboolean
++jack_controller_set_driver_parameter_value_uint(
++	JackController * object_ptr,
++	const gchar * parameter,
++	guint value,
++	GError ** error)
++{
++	struct jack_controller * controller_ptr;
++	jack_driver_param_desc_t * param_desc_ptr;
++	jack_driver_param_t * param_ptr;
++
++	controller_ptr = JACK_CONTROLLER_GET_PRIVATE(object_ptr);
++
++	if (controller_ptr->driver_ptr == NULL)
++	{
++		jack_controller_error(error, "Select driver before operating on its parameters!");
++		return FALSE;
++	}
++
++	param_desc_ptr = jack_controller_find_parameter_descriptor_by_name_current_driver(controller_ptr, parameter);
++	if (param_desc_ptr == NULL)
++	{
++		jack_controller_error(error, "Unknown parameter \"%s\" of driver \"%s\"", parameter, controller_ptr->driver_ptr->desc_ptr->name);
++		return FALSE;
++	}
++
++	if (param_desc_ptr->type != JackDriverParamUInt)
++	{
++		jack_controller_error(error, "Parameter \"%s\" of driver \"%s\" is not uint", parameter, controller_ptr->driver_ptr->desc_ptr->name);
++		return FALSE;
++	}
++
++	jack_info("Setting parameter \"%s\" of driver \"%s\" to %u", parameter, controller_ptr->driver_ptr->desc_ptr->name, value);
++
++	param_ptr = jack_controller_find_or_create_parameter_current_driver(controller_ptr, param_desc_ptr);
++	if (param_ptr == NULL)
++	{
++		jack_controller_error(error, "driver parameter creation failed");
++		return FALSE;
++	}
++
++	param_ptr->value.ui = value;
++
++	jack_controller_settings_save_auto(controller_ptr);
++
++	return TRUE;
++}
++
++gboolean
++jack_controller_get_engine_parameter_names(
++	JackController * object_ptr,
++	gchar *** params_list,
++	GError ** error)
++{
++	struct jack_controller * controller_ptr;
++	gchar **array;
++	unsigned int i;
++
++	controller_ptr = JACK_CONTROLLER_GET_PRIVATE(object_ptr);
++
++	if (controller_ptr->verbose)
++	{
++		jack_info("Getting engine parameters");
++	}
++
++	array = g_malloc((JACK_ENGINE_PARAMS_COUNT + 1) * sizeof(gchar *));
++
++	for (i = 0; i < JACK_ENGINE_PARAMS_COUNT ; i++)
++	{
++		array[i] = g_strdup(jack_engine_parameters[i].name);
++	}
++
++	array[i] = NULL;
++
++	*params_list = array;
++
++	return TRUE;
++}
++
++gboolean
++jack_controller_get_engine_parameter_short_description(
++	JackController * object_ptr,
++	const gchar * parameter,
++	gchar ** description,
++	GError ** error)
++{
++	unsigned int i;
++
++	for (i = 0; i < JACK_ENGINE_PARAMS_COUNT ; i++)
++	{
++		if (strcmp(jack_engine_parameters[i].name, parameter) == 0)
++		{
++			*description = g_strdup(jack_engine_parameters[i].description_short);
++			return TRUE;
++		}
++	}
++
++	jack_controller_error(error, "Unknown engine parameter \"%s\"", parameter);
++	return FALSE;
++}
++
++gboolean
++jack_controller_get_engine_parameter_long_description(
++	JackController * object_ptr,
++	const gchar * parameter,
++	gchar ** description,
++	GError ** error)
++{
++	unsigned int i;
++
++	for (i = 0; i < JACK_ENGINE_PARAMS_COUNT ; i++)
++	{
++		if (strcmp(jack_engine_parameters[i].name, parameter) == 0)
++		{
++			if (jack_engine_parameters[i].description_long == NULL)
++			{
++				*description = g_strdup(jack_engine_parameters[i].description_short);
++			}
++			else
++			{
++				*description = g_strdup(jack_engine_parameters[i].description_long);
++			}
++
++			return TRUE;
++		}
++	}
++
++	jack_controller_error(error, "Unknown engine parameter \"%s\"", parameter);
++	return FALSE;
++}
++
++gboolean
++jack_controller_get_engine_parameter_type(
++	JackController * object_ptr,
++	const gchar * parameter,
++	guchar * type,
++	GError ** error)
++{
++	unsigned int i;
++
++	for (i = 0; i < JACK_ENGINE_PARAMS_COUNT ; i++)
++	{
++		if (strcmp(jack_engine_parameters[i].name, parameter) == 0)
++		{
++			*type = jack_engine_parameters[i].type;
++			return TRUE;
++		}
++	}
++
++	jack_controller_error(error, "Unknown engine parameter \"%s\"", parameter);
++	return FALSE;
++}
++
++gboolean
++jack_controller_get_engine_parameter_type_string(
++	JackController * object_ptr,
++	const gchar * parameter,
++	gchar ** type,
++	GError ** error)
++{
++	unsigned int i;
++
++	for (i = 0; i < JACK_ENGINE_PARAMS_COUNT ; i++)
++	{
++		if (strcmp(jack_engine_parameters[i].name, parameter) == 0)
++		{
++			switch (jack_engine_parameters[i].type)
++			{
++			case JackParamInt:
++				*type = g_strdup("sint");
++				return TRUE;
++			case JackParamUInt:
++				*type = g_strdup("uint");
++				return TRUE;
++			case JackParamChar:
++				*type = g_strdup("char");
++				return TRUE;
++			case JackParamString:
++				*type = g_strdup("str");
++				return TRUE;
++			case JackParamBool:
++				*type = g_strdup("bool");
++				return TRUE;
++			}
++
++			jack_controller_error(
++				error,
++				"Engine parameter \"%s\" is of unknown type %d",
++				parameter,
++				jack_engine_parameters[i].type);
++			return FALSE;
++		}
++	}
++
++	jack_controller_error(error, "Unknown engine parameter \"%s\"", parameter);
++	return FALSE;
++}
++
++gboolean
++jack_controller_get_engine_parameter_value_string(
++	JackController * object_ptr,
++	const gchar * parameter,
++	gchar ** value,
++	GError ** error)
++{
++	jack_controller_error(error, "Unknown engine string parameter \"%s\"", parameter);
++	return FALSE;
++}
++
++gboolean
++jack_controller_set_engine_parameter_value_string(
++	JackController * object_ptr,
++	const gchar * parameter,
++	gchar * value,
++	GError ** error)
++{
++	jack_controller_error(error, "Unknown engine string parameter \"%s\"", parameter);
++	return FALSE;
++}
++
++gboolean
++jack_controller_get_engine_parameter_value_bool(
++	JackController * object_ptr,
++	const gchar * parameter,
++	gboolean * value,
++	GError ** error)
++{
++	struct jack_controller * controller_ptr;
++
++	controller_ptr = JACK_CONTROLLER_GET_PRIVATE(object_ptr);
++
++	if (strcmp(parameter, "realtime") == 0)
++	{
++		*value = controller_ptr->realtime ? TRUE : FALSE;
++		return TRUE;
++	}
++
++	if (strcmp(parameter, "no-mem-lock") == 0)
++	{
++		*value = controller_ptr->do_mlock ? FALSE : TRUE; /* reverse logic */
++		return TRUE;
++	}
++
++	if (strcmp(parameter, "temporary") == 0)
++	{
++		*value = controller_ptr->temporary ? TRUE : FALSE;
++		return TRUE;
++	}
++
++	if (strcmp(parameter, "verbose") == 0)
++	{
++		*value = controller_ptr->verbose ? TRUE : FALSE;
++		return TRUE;
++	}
++
++	if (strcmp(parameter, "no-zombies") == 0)
++	{
++		*value = controller_ptr->nozombies ? TRUE : FALSE;
++		return TRUE;
++	}
++
++	if (strcmp(parameter, "libs-unlock") == 0)
++	{
++		*value = controller_ptr->do_unlock ? TRUE : FALSE;
++		return TRUE;
++	}
++
++	jack_controller_error(error, "Unknown engine boolean parameter \"%s\"", parameter);
++	return FALSE;
++}
++
++gboolean
++jack_controller_set_engine_parameter_value_bool(
++	JackController * object_ptr,
++	const gchar * parameter,
++	gboolean value,
++	GError ** error)
++{
++	struct jack_controller * controller_ptr;
++
++	controller_ptr = JACK_CONTROLLER_GET_PRIVATE(object_ptr);
++
++	if (controller_ptr->verbose)
++	{
++		jack_info("Setting boolean parameter \"%s\" to %s", parameter, value ? "true" : "false");
++	}
++
++	if (strcmp(parameter, "realtime") == 0)
++	{
++		controller_ptr->realtime = value;
++		goto save;
++	}
++
++	if (strcmp(parameter, "no-mem-lock") == 0)
++	{
++		controller_ptr->do_mlock = !value; /* reverse logic */
++		goto save;
++	}
++
++	if (strcmp(parameter, "temporary") == 0)
++	{
++		controller_ptr->temporary = value;
++		goto save;
++	}
++
++	if (strcmp(parameter, "verbose") == 0)
++	{
++		if (!controller_ptr->verbose && value)
++		{
++			jack_info("Setting boolean parameter \"%s\" to %s", parameter, value ? "true" : "false");
++		}
++
++		controller_ptr->verbose = value;
++		goto save;
++	}
++
++	if (strcmp(parameter, "no-zombies") == 0)
++	{
++		controller_ptr->nozombies = value;
++		goto save;
++	}
++
++	if (strcmp(parameter, "libs-unlock") == 0)
++	{
++		controller_ptr->do_unlock = value;
++		goto save;
++	}
++
++	jack_controller_error(error, "Unknown engine boolean parameter \"%s\"", parameter);
++	return FALSE;
++
++save:
++	jack_controller_settings_save_auto(controller_ptr);
++	return TRUE;
++}
++
++gboolean
++jack_controller_get_engine_parameter_value_char(
++	JackController * object_ptr,
++	const gchar * parameter,
++	guchar * value,
++	GError ** error)
++{
++	jack_controller_error(error, "Unknown engine char parameter \"%s\"", parameter);
++	return FALSE;
++}
++
++gboolean
++jack_controller_set_engine_parameter_value_char(
++	JackController * object_ptr,
++	const gchar * parameter,
++	guchar value,
++	GError ** error)
++{
++	jack_controller_error(error, "Unknown engine char parameter \"%s\"", parameter);
++	return FALSE;
++}
++
++gboolean
++jack_controller_get_engine_parameter_value_int(
++	JackController * object_ptr,
++	const gchar * parameter,
++	gint * value,
++	GError ** error)
++{
++	struct jack_controller * controller_ptr;
++
++	controller_ptr = JACK_CONTROLLER_GET_PRIVATE(object_ptr);
++
++	if (strcmp(parameter, "realtime-priority") == 0)
++	{
++		*value = controller_ptr->realtime_priority;
++		return TRUE;
++	}
++
++	if (strcmp(parameter, "client-timeout") == 0)
++	{
++		*value = controller_ptr->client_timeout;
++		return TRUE;
++	}
++
++	jack_controller_error(error, "Unknown engine sint parameter \"%s\"", parameter);
++	return FALSE;
++}
++
++gboolean
++jack_controller_set_engine_parameter_value_int(
++	JackController * object_ptr,
++	const gchar * parameter,
++	gint value,
++	GError ** error)
++{
++	struct jack_controller * controller_ptr;
++
++	controller_ptr = JACK_CONTROLLER_GET_PRIVATE(object_ptr);
++
++	if (strcmp(parameter, "realtime-priority") == 0)
++	{
++		controller_ptr->realtime_priority = value;
++		goto save;
++	}
++
++	if (strcmp(parameter, "client-timeout") == 0)
++	{
++		controller_ptr->client_timeout = value;
++		goto save;
++	}
++
++	jack_controller_error(error, "Unknown engine sint parameter \"%s\"", parameter);
++	return FALSE;
++
++save:
++	jack_controller_settings_save_auto(controller_ptr);
++	return TRUE;
++}
++
++gboolean
++jack_controller_get_engine_parameter_value_uint(
++	JackController * object_ptr,
++	const gchar * parameter,
++	guint * value,
++	GError ** error)
++{
++	struct jack_controller * controller_ptr;
++
++	controller_ptr = JACK_CONTROLLER_GET_PRIVATE(object_ptr);
++
++	if (strcmp(parameter, "port-max") == 0)
++	{
++		*value = controller_ptr->port_max;
++		return TRUE;
++	}
++
++	jack_controller_error(error, "Unknown engine uint parameter \"%s\"", parameter);
++	return FALSE;
++}
++
++gboolean
++jack_controller_set_engine_parameter_value_uint(
++	JackController * object_ptr,
++	const gchar * parameter,
++	guint value,
++	GError ** error)
++{
++	struct jack_controller * controller_ptr;
++
++	controller_ptr = JACK_CONTROLLER_GET_PRIVATE(object_ptr);
++
++	if (strcmp(parameter, "port-max") == 0)
++	{
++		controller_ptr->port_max = value;
++		goto save;
++	}
++
++	jack_controller_error(error, "Unknown engine uint parameter \"%s\"", parameter);
++	return FALSE;
++
++save:
++	jack_controller_settings_save_auto(controller_ptr);
++	return TRUE;
++}
+diff --git a/jackd/jackcontroller.h b/jackd/jackcontroller.h
+new file mode 100644
+--- /dev/null
++++ b/jackd/jackcontroller.h
+@@ -0,0 +1,324 @@
++/* -*- mode: c; c-file-style: "bsd"; -*- */
++/*
++    Copyright (C) 2007 Nedko Arnaudov
++    
++    This program is free software; you can redistribute it and/or modify
++    it under the terms of the GNU General Public License as published by
++    the Free Software Foundation; either version 2 of the License.
++
++    This program is distributed in the hope that it will be useful,
++    but WITHOUT ANY WARRANTY; without even the implied warranty of
++    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++    GNU General Public License for more details.
++
++    You should have received a copy of the GNU General Public License
++    along with this program; if not, write to the Free Software
++    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++
++*/
++
++#ifndef JACKCONTROLLER_H__2CC80B1E_8D5D_45E3_A9D8_9086DDF68BB5__INCLUDED
++#define JACKCONTROLLER_H__2CC80B1E_8D5D_45E3_A9D8_9086DDF68BB5__INCLUDED
++
++G_BEGIN_DECLS
++
++#define JACK_CONTROLLER_TYPE (jack_controller_get_type())
++#define JACK_CONTROLLER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), JACK_CONTROLLER_TYPE, JackController))
++#define JACK_CONTROLLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), JACK_CONTROLLER_TYPE, JackControllerClass))
++#define JACK_IS_CONTROLLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), JACK_CONTROLLER_TYPE))
++#define JACK_IS_CONTROLLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), JACK_CONTROLLER_TYPE))
++#define JACK_CONTROLLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), JACK_CONTROLLER_TYPE, JackControllerClass))
++
++#define JACK_TYPE_CONTROLLER JACK_CONTROLLER_TYPE
++
++typedef struct _JackController JackController;
++typedef struct _JackControllerClass JackControllerClass;
++
++struct _JackController {
++  GObject parent;
++  /* instance members */
++};
++
++struct _JackControllerClass {
++  GObjectClass parent;
++  /* class members */
++};
++
++/* used by JACK_CONTROLLER_TYPE */
++GType jack_controller_get_type();
++
++void
++jack_controller_run(
++	JackController * object_ptr);
++
++gboolean
++jack_controller_test(
++	JackController * object_ptr,
++	GError ** error);
++
++gboolean
++jack_controller_exit(
++	JackController * object_ptr,
++	GError ** error);
++
++gboolean
++jack_controller_is_manually_activated(
++	JackController * object_ptr,
++	gboolean * manually_started_ptr,
++	GError ** error);
++
++gboolean
++jack_controller_start_server(
++	JackController * object_ptr,
++	GError ** error);
++
++gboolean
++jack_controller_stop_server(
++	JackController * object_ptr,
++	GError ** error);
++
++gboolean
++jack_controller_is_manually_activated(
++	JackController * object_ptr,
++	gboolean * manually_started_ptr,
++	GError ** error);
++
++gboolean
++jack_controller_get_available_drivers(
++	JackController * object_ptr,
++	gchar *** drivers_list,
++	GError ** error);
++
++gboolean
++jack_controller_get_selected_driver(
++	JackController * object_ptr,
++	gchar ** driver_name,
++	GError ** error);
++
++gboolean
++jack_controller_select_driver(
++	JackController * object_ptr,
++	const gchar * driver_name,
++	GError ** error);
++
++gboolean
++jack_controller_get_driver_parameter_names(
++	JackController * object_ptr,
++	gchar *** params_list,
++	GError ** error);
++
++gboolean
++jack_controller_get_driver_parameter_short_description(
++	JackController * object_ptr,
++	const gchar * parameter,
++	gchar ** description,
++	GError ** error);
++
++gboolean
++jack_controller_get_driver_parameter_long_description(
++	JackController * object_ptr,
++	const gchar * parameter,
++	gchar ** description,
++	GError ** error);
++
++gboolean
++jack_controller_get_driver_parameter_type(
++	JackController * object_ptr,
++	const gchar * parameter,
++	guchar * type,
++	GError ** error);
++
++gboolean
++jack_controller_get_driver_parameter_type_string(
++	JackController * object_ptr,
++	const gchar * parameter,
++	gchar ** type,
++	GError ** error);
++
++gboolean
++jack_controller_get_driver_parameter_value_string(
++	JackController * object_ptr,
++	const gchar * parameter,
++	gboolean * isset,
++	gchar ** default_value,
++	gchar ** value,
++	GError ** error);
++
++gboolean
++jack_controller_get_driver_parameter_value_bool(
++	JackController * object_ptr,
++	const gchar * parameter,
++	gboolean * isset,
++	gboolean * default_value,
++	gboolean * value,
++	GError ** error);
++
++gboolean
++jack_controller_get_driver_parameter_value_char(
++	JackController * object_ptr,
++	const gchar * parameter,
++	gboolean * isset,
++	guchar * default_value,
++	guchar * value,
++	GError ** error);
++
++gboolean
++jack_controller_get_driver_parameter_value_int(
++	JackController * object_ptr,
++	const gchar * parameter,
++	gboolean * isset,
++	gint * default_value,
++	gint * value,
++	GError ** error);
++
++gboolean
++jack_controller_get_driver_parameter_value_uint(
++	JackController * object_ptr,
++	const gchar * parameter,
++	gboolean * isset,
++	guint * default_value,
++	guint * value,
++	GError ** error);
++
++gboolean
++jack_controller_set_driver_parameter_value_string(
++	JackController * object_ptr,
++	const gchar * parameter,
++	gchar * value,
++	GError ** error);
++
++gboolean
++jack_controller_set_driver_parameter_value_bool(
++	JackController * object_ptr,
++	const gchar * parameter,
++	gboolean value,
++	GError ** error);
++
++gboolean
++jack_controller_set_driver_parameter_value_char(
++	JackController * object_ptr,
++	const gchar * parameter,
++	guchar value,
++	GError ** error);
++
++gboolean
++jack_controller_set_driver_parameter_value_int(
++	JackController * object_ptr,
++	const gchar * parameter,
++	gint value,
++	GError ** error);
++
++gboolean
++jack_controller_set_driver_parameter_value_uint(
++	JackController * object_ptr,
++	const gchar * parameter,
++	guint value,
++	GError ** error);
++
++gboolean
++jack_controller_get_engine_parameter_names(
++	JackController * object_ptr,
++	gchar *** params_list,
++	GError ** error);
++
++gboolean
++jack_controller_get_engine_parameter_short_description(
++	JackController * object_ptr,
++	const gchar * parameter,
++	gchar ** description,
++	GError ** error);
++
++gboolean
++jack_controller_get_engine_parameter_long_description(
++	JackController * object_ptr,
++	const gchar * parameter,
++	gchar ** description,
++	GError ** error);
++
++gboolean
++jack_controller_get_engine_parameter_type(
++	JackController * object_ptr,
++	const gchar * parameter,
++	guchar * type,
++	GError ** error);
++
++gboolean
++jack_controller_get_engine_parameter_type_string(
++	JackController * object_ptr,
++	const gchar * parameter,
++	gchar ** type,
++	GError ** error);
++
++gboolean
++jack_controller_get_engine_parameter_value_string(
++	JackController * object_ptr,
++	const gchar * parameter,
++	gchar ** value,
++	GError ** error);
++
++gboolean
++jack_controller_get_engine_parameter_value_bool(
++	JackController * object_ptr,
++	const gchar * parameter,
++	gboolean * value,
++	GError ** error);
++
++gboolean
++jack_controller_get_engine_parameter_value_char(
++	JackController * object_ptr,
++	const gchar * parameter,
++	guchar * value,
++	GError ** error);
++
++gboolean
++jack_controller_get_engine_parameter_value_int(
++	JackController * object_ptr,
++	const gchar * parameter,
++	gint * value,
++	GError ** error);
++
++gboolean
++jack_controller_get_engine_parameter_value_uint(
++	JackController * object_ptr,
++	const gchar * parameter,
++	guint * value,
++	GError ** error);
++
++gboolean
++jack_controller_set_engine_parameter_value_string(
++	JackController * object_ptr,
++	const gchar * parameter,
++	gchar * value,
++	GError ** error);
++
++gboolean
++jack_controller_set_engine_parameter_value_bool(
++	JackController * object_ptr,
++	const gchar * parameter,
++	gboolean value,
++	GError ** error);
++
++gboolean
++jack_controller_set_engine_parameter_value_char(
++	JackController * object_ptr,
++	const gchar * parameter,
++	guchar value,
++	GError ** error);
++
++gboolean
++jack_controller_set_engine_parameter_value_int(
++	JackController * object_ptr,
++	const gchar * parameter,
++	gint value,
++	GError ** error);
++
++gboolean
++jack_controller_set_engine_parameter_value_uint(
++	JackController * object_ptr,
++	const gchar * parameter,
++	guint value,
++	GError ** error);
++
++G_END_DECLS
++
++#endif /* #ifndef JACKCONTROLLER_H__2CC80B1E_8D5D_45E3_A9D8_9086DDF68BB5__INCLUDED */
+diff --git a/jackd/jackcontroller.xml b/jackd/jackcontroller.xml
+new file mode 100644
+--- /dev/null
++++ b/jackd/jackcontroller.xml
+@@ -0,0 +1,159 @@
++<?xml version="1.0" encoding="UTF-8" ?>
++
++<node>
++  <interface name="org.jackaudio.JackController">
++    <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="jack_controller"/>
++    <method name="Test">
++    </method>
++    <method name="Exit">
++    </method>
++    <method name="IsManuallyActivated">
++        <arg type="b" name="manually_activated" direction="out" />
++    </method>
++    <method name="StartServer">
++    </method>
++    <method name="StopServer">
++    </method>
++    <method name="GetAvailableDrivers">
++        <arg type="as" name="drivers_list" direction="out" />
++    </method>
++    <method name="GetSelectedDriver">
++        <arg type="s" name="driver" direction="out" />
++    </method>
++    <method name="SelectDriver">
++        <arg type="s" name="driver" direction="in" />
++    </method>
++    <!-- driver parameters overview  -->
++    <method name="GetDriverParameterNames">
++        <arg type="as" name="parameters" direction="out" />
++    </method>
++    <method name="GetDriverParameterShortDescription">
++        <arg type="s" name="parameter" direction="in" />
++        <arg type="s" name="description" direction="out" />
++    </method>
++    <method name="GetDriverParameterLongDescription">
++        <arg type="s" name="parameter" direction="in" />
++        <arg type="s" name="description" direction="out" />
++    </method>
++    <method name="GetDriverParameterType">
++        <arg type="s" name="parameter" direction="in" />
++        <arg type="y" name="type" direction="out" />
++    </method>
++    <method name="GetDriverParameterTypeString">
++        <arg type="s" name="parameter" direction="in" />
++        <arg type="s" name="type" direction="out" />
++    </method>
++    <!-- driver parameters access  -->
++    <method name="GetDriverParameterValueString">
++        <arg type="s" name="parameter" direction="in" />
++        <arg type="b" name="isset" direction="out" />
++        <arg type="s" name="default" direction="out" />
++        <arg type="s" name="value" direction="out" />
++    </method>
++    <method name="GetDriverParameterValueBool">
++        <arg type="s" name="parameter" direction="in" />
++        <arg type="b" name="isset" direction="out" />
++        <arg type="b" name="default" direction="out" />
++        <arg type="b" name="value" direction="out" />
++    </method>
++    <method name="GetDriverParameterValueChar">
++        <arg type="s" name="parameter" direction="in" />
++        <arg type="b" name="isset" direction="out" />
++        <arg type="y" name="default" direction="out" />
++        <arg type="y" name="value" direction="out" />
++    </method>
++    <method name="GetDriverParameterValueInt">
++        <arg type="s" name="parameter" direction="in" />
++        <arg type="b" name="isset" direction="out" />
++        <arg type="i" name="default" direction="out" />
++        <arg type="i" name="value" direction="out" />
++    </method>
++    <method name="GetDriverParameterValueUint">
++        <arg type="s" name="parameter" direction="in" />
++        <arg type="b" name="isset" direction="out" />
++        <arg type="u" name="default" direction="out" />
++        <arg type="u" name="value" direction="out" />
++    </method>
++    <method name="SetDriverParameterValueString">
++        <arg type="s" name="parameter" direction="in" />
++        <arg type="s" name="value" direction="in" />
++    </method>
++    <method name="SetDriverParameterValueBool">
++        <arg type="s" name="parameter" direction="in" />
++        <arg type="b" name="value" direction="in" />
++    </method>
++    <method name="SetDriverParameterValueChar">
++        <arg type="s" name="parameter" direction="in" />
++        <arg type="y" name="value" direction="in" />
++    </method>
++    <method name="SetDriverParameterValueInt">
++        <arg type="s" name="parameter" direction="in" />
++        <arg type="i" name="value" direction="in" />
++    </method>
++    <method name="SetDriverParameterValueUint">
++        <arg type="s" name="parameter" direction="in" />
++        <arg type="u" name="value" direction="in" />
++    </method>
++    <!-- engine parameters overview  -->
++    <method name="GetEngineParameterNames">
++        <arg type="as" name="parameters" direction="out" />
++    </method>
++    <method name="GetEngineParameterShortDescription">
++        <arg type="s" name="parameter" direction="in" />
++        <arg type="s" name="description" direction="out" />
++    </method>
++    <method name="GetEngineParameterLongDescription">
++        <arg type="s" name="parameter" direction="in" />
++        <arg type="s" name="description" direction="out" />
++    </method>
++    <method name="GetEngineParameterType">
++        <arg type="s" name="parameter" direction="in" />
++        <arg type="y" name="type" direction="out" />
++    </method>
++    <method name="GetEngineParameterTypeString">
++        <arg type="s" name="parameter" direction="in" />
++        <arg type="s" name="type" direction="out" />
++    </method>
++    <!-- engine parameters access  -->
++    <method name="GetEngineParameterValueString">
++        <arg type="s" name="parameter" direction="in" />
++        <arg type="s" name="value" direction="out" />
++    </method>
++    <method name="GetEngineParameterValueBool">
++        <arg type="s" name="parameter" direction="in" />
++        <arg type="b" name="value" direction="out" />
++    </method>
++    <method name="GetEngineParameterValueChar">
++        <arg type="s" name="parameter" direction="in" />
++        <arg type="y" name="value" direction="out" />
++    </method>
++    <method name="GetEngineParameterValueInt">
++        <arg type="s" name="parameter" direction="in" />
++        <arg type="i" name="value" direction="out" />
++    </method>
++    <method name="GetEngineParameterValueUint">
++        <arg type="s" name="parameter" direction="in" />
++        <arg type="u" name="value" direction="out" />
++    </method>
++    <method name="SetEngineParameterValueString">
++        <arg type="s" name="parameter" direction="in" />
++        <arg type="s" name="value" direction="in" />
++    </method>
++    <method name="SetEngineParameterValueBool">
++        <arg type="s" name="parameter" direction="in" />
++        <arg type="b" name="value" direction="in" />
++    </method>
++    <method name="SetEngineParameterValueChar">
++        <arg type="s" name="parameter" direction="in" />
++        <arg type="y" name="value" direction="in" />
++    </method>
++    <method name="SetEngineParameterValueInt">
++        <arg type="s" name="parameter" direction="in" />
++        <arg type="i" name="value" direction="in" />
++    </method>
++    <method name="SetEngineParameterValueUint">
++        <arg type="s" name="parameter" direction="in" />
++        <arg type="u" name="value" direction="in" />
++    </method>
++  </interface>
++</node>
+diff --git a/jackd/jackdbus.c b/jackd/jackdbus.c
+new file mode 100644
+--- /dev/null
++++ b/jackd/jackdbus.c
+@@ -0,0 +1,346 @@
++/* -*- mode: c; c-file-style: "bsd"; -*- */
++/*
++    Copyright (C) 2007 Nedko Arnaudov
++    
++    This program is free software; you can redistribute it and/or modify
++    it under the terms of the GNU General Public License as published by
++    the Free Software Foundation; either version 2 of the License.
++
++    This program is distributed in the hope that it will be useful,
++    but WITHOUT ANY WARRANTY; without even the implied warranty of
++    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++    GNU General Public License for more details.
++
++    You should have received a copy of the GNU General Public License
++    along with this program; if not, write to the Free Software
++    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++
++*/
++
++#include <config.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <dbus/dbus-glib.h>
++#include <jack/jack.h>
++#include <jack/internal.h>
++#include <errno.h>
++#include <sys/stat.h>
++#include <sys/types.h>
++#include <time.h>
++#include <unistd.h>
++#include <signal.h>
++
++#if HAVE_LIBXML2
++#include <libxml/xmlwriter.h>
++#endif
++
++#include "jackdbus.h"
++#include "jackcontroller.h"
++
++FILE *g_logfile;
++gchar *g_jackdbus_dir;
++
++void 
++jack_dbus_info (const char *msg)
++{
++	time_t timestamp;
++	char timestamp_str[26];
++
++	time(&timestamp);
++	ctime_r(&timestamp, timestamp_str);
++	timestamp_str[24] = 0;
++
++	fprintf (g_logfile, "%s: %s\n", timestamp_str, msg);
++	fflush(g_logfile);
++}
++
++void 
++jack_dbus_error (const char *msg)
++{
++	time_t timestamp;
++	char timestamp_str[26];
++
++	time(&timestamp);
++	ctime_r(&timestamp, timestamp_str);
++	timestamp_str[24] = 0;
++
++	fprintf (g_logfile, "%s: ERROR: %s\n", timestamp_str, msg);
++	fflush(g_logfile);
++}
++
++gboolean
++paths_init()
++{
++	const char *home_dir;
++	struct stat st;
++	
++	home_dir = getenv("HOME");
++	if (home_dir == NULL)
++	{
++		g_printerr("Environment variable HOME not set\n");
++		goto fail;
++	}
++
++	g_jackdbus_dir = g_strdup_printf("%s" JACKDBUS_DIR, home_dir);
++	if (g_jackdbus_dir == NULL)
++	{
++		g_printerr("Out of memory\n");
++		goto fail;
++	}
++
++	if (stat(g_jackdbus_dir, &st) != 0)
++	{
++		if (errno == ENOENT)
++		{
++			g_print("Directory \"%s\" does not exist. Creating...\n", g_jackdbus_dir);
++			if (mkdir(g_jackdbus_dir, 0777) != 0)
++			{
++				g_printerr("Failed to create \"%s\" directory: %d (%s)\n", g_jackdbus_dir, errno, strerror(errno));
++				goto fail_free;
++			}
++		}
++		else
++		{
++			g_printerr("Failed to stat \"%s\": %d (%s)\n", g_jackdbus_dir, errno, strerror(errno));
++			goto fail_free;
++		}
++	}
++	else
++	{
++		if (!S_ISDIR(st.st_mode))
++		{
++			g_printerr("\"%s\" exists but is not directory.\n", g_jackdbus_dir);
++			goto fail_free;
++		}
++	}
++
++	return TRUE;
++
++fail_free:
++	g_free(g_jackdbus_dir);
++
++fail:
++	return FALSE;
++}
++
++void
++paths_uninit()
++{
++	g_free(g_jackdbus_dir);
++}
++
++gboolean
++log_init()
++{
++	gchar *log_filename;
++
++	log_filename = g_strdup_printf("%s" JACKDBUS_LOG, g_jackdbus_dir);
++	if (log_filename == NULL)
++	{
++		g_printerr("Out of memory\n");
++		return FALSE;
++	}
++
++	g_logfile = fopen(log_filename, "a");
++	if (g_logfile == NULL)
++	{
++		fprintf(stderr, "Cannot open jackdbus log file \"%s\": %d (%s)\n", log_filename, errno, strerror(errno));
++		g_free(log_filename);
++		return FALSE;
++	}
++
++	g_free(log_filename);
++
++	return TRUE;
++}
++
++void
++log_uninit()
++{
++	fclose(g_logfile);
++}
++
++static void 
++do_nothing_handler (int sig)
++{
++	/* this is used by the child (active) process, but it never
++	   gets called unless we are already shutting down after
++	   another signal.
++	*/
++	char buf[64];
++	snprintf (buf, sizeof(buf),
++		  "received signal %d during shutdown (ignored)\n", sig);
++	write (1, buf, strlen (buf));
++}
++
++int
++main (int argc, char **argv)
++{
++	DBusGConnection *connection;
++	GError *error;
++	JackController *controller_ptr;
++	DBusGProxy *bus_proxy;
++	guint request_name_result;
++	int ret;
++	sigset_t signals;
++	sigset_t allsignals;
++	struct sigaction action;
++	int i;
++
++#if HAVE_LIBXML2
++	/*
++	 * this initialize the library and check potential ABI mismatches
++	 * between the version it was compiled for and the actual shared
++	 * library used.
++	 */
++	LIBXML_TEST_VERSION;
++#endif
++
++	if (argc != 2 || strcmp(argv[1], "auto") != 0)
++	{
++		ret = 0;
++		fprintf(
++			stderr,
++			"jackdbus should be auto-executed by D-Bus message bus daemon.\n"
++			"If you want to run it manually anyway, specify \"auto\" as only parameter\n");
++		goto fail;
++	}
++
++	if (!paths_init())
++	{
++		ret = 1;
++		goto fail;
++	}
++
++	if (!log_init())
++	{
++		ret = 1;
++		goto fail_uninit_paths;
++	}
++
++	/* ensure that we are in our own process group so that
++	   kill (SIG, -pgrp) does the right thing.
++	*/
++
++	setsid();
++
++	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
++
++	/* what's this for?
++
++	   POSIX says that signals are delivered like this:
++
++	   * if a thread has blocked that signal, it is not
++	       a candidate to receive the signal.
++           * of all threads not blocking the signal, pick
++	       one at random, and deliver the signal.
++
++           this means that a simple-minded multi-threaded program can
++           expect to get POSIX signals delivered randomly to any one
++           of its threads,
++
++	   here, we block all signals that we think we might receive
++	   and want to catch. all "child" threads will inherit this
++	   setting. if we create a thread that calls sigwait() on the
++	   same set of signals, implicitly unblocking all those
++	   signals. any of those signals that are delivered to the
++	   process will be delivered to that thread, and that thread
++	   alone. this makes cleanup for a signal-driven exit much
++	   easier, since we know which thread is doing it and more
++	   importantly, we are free to call async-unsafe functions,
++	   because the code is executing in normal thread context
++	   after a return from sigwait().
++	*/
++
++	sigemptyset(&signals);
++	sigaddset(&signals, SIGHUP);
++	sigaddset(&signals, SIGINT);
++	sigaddset(&signals, SIGQUIT);
++	sigaddset(&signals, SIGPIPE);
++	sigaddset(&signals, SIGTERM);
++	sigaddset(&signals, SIGUSR1);
++	sigaddset(&signals, SIGUSR2);
++
++	/* all child threads will inherit this mask unless they
++	 * explicitly reset it 
++	 */
++
++	pthread_sigmask (SIG_BLOCK, &signals, 0);
++
++	/* install a do-nothing handler because otherwise pthreads
++	   behaviour is undefined when we enter sigwait.
++	*/
++
++	sigfillset (&allsignals);
++	action.sa_handler = do_nothing_handler;
++	action.sa_mask = allsignals;
++	action.sa_flags = SA_RESTART|SA_RESETHAND;
++
++	for (i = 1; i < NSIG; i++) {
++		if (sigismember (&signals, i)) {
++			sigaction (i, &action, 0);
++		} 
++	}
++
++	g_type_init ();
++
++	jack_set_error_function (jack_dbus_error);
++	jack_set_info_function (jack_dbus_info);
++
++	jack_info("------------------");
++	jack_info("Controller activated. Version " VERSION);
++
++	error = NULL;
++	connection = dbus_g_bus_get (DBUS_BUS_SESSION,
++				     &error);
++	if (connection == NULL)
++	{
++		g_printerr ("Failed to open connection to bus: %s\n",
++			    error->message);
++		g_error_free (error);
++		ret = 1;
++		goto fail_uninit_log;
++	}
++
++	bus_proxy = dbus_g_proxy_new_for_name (
++		connection,
++		"org.freedesktop.DBus",
++		"/org/freedesktop/DBus",
++		"org.freedesktop.DBus");
++
++	if (!dbus_g_proxy_call (bus_proxy, "RequestName", &error,
++				G_TYPE_STRING, "org.jackaudio.service",
++				G_TYPE_UINT, 0,
++				G_TYPE_INVALID,
++				G_TYPE_UINT, &request_name_result,
++				G_TYPE_INVALID))
++	{
++		g_printerr ("Failed to acquire org.jackaudio.service %s", error->message);
++		ret = 1;
++		goto fail_uninit_log;
++	}
++
++	controller_ptr = g_object_new(JACK_CONTROLLER_TYPE, NULL);
++
++	dbus_g_connection_register_g_object (connection,
++					     "/DefaultController",
++					     G_OBJECT(controller_ptr));
++
++	jack_controller_run(controller_ptr);
++
++	g_object_unref(controller_ptr);
++
++	jack_info("Controller deactivated.");
++
++	ret = 0;
++
++fail_uninit_log:
++	log_uninit();
++
++fail_uninit_paths:
++	paths_uninit();
++
++fail:
++	return ret;
++}
+diff --git a/jackd/jackdbus.h b/jackd/jackdbus.h
+new file mode 100644
+--- /dev/null
++++ b/jackd/jackdbus.h
+@@ -0,0 +1,29 @@
++/* -*- mode: c; c-file-style: "bsd"; -*- */
++/*
++    Copyright (C) 2007 Nedko Arnaudov
++    
++    This program is free software; you can redistribute it and/or modify
++    it under the terms of the GNU General Public License as published by
++    the Free Software Foundation; either version 2 of the License.
++
++    This program is distributed in the hope that it will be useful,
++    but WITHOUT ANY WARRANTY; without even the implied warranty of
++    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++    GNU General Public License for more details.
++
++    You should have received a copy of the GNU General Public License
++    along with this program; if not, write to the Free Software
++    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++
++*/
++
++#ifndef JACKDBUS_H__3DB2458F_44B2_43EA_882A_9F888DF71A88__INCLUDED
++#define JACKDBUS_H__3DB2458F_44B2_43EA_882A_9F888DF71A88__INCLUDED
++
++#define JACKDBUS_DIR "/.jackdbus"
++#define JACKDBUS_LOG "/jackdbus.log"
++#define JACKDBUS_CONF "/conf.xml"
++
++extern gchar *g_jackdbus_dir;
++
++#endif /* #ifndef JACKDBUS_H__3DB2458F_44B2_43EA_882A_9F888DF71A88__INCLUDED */
+diff --git a/jackd/org.jackaudio.service.in b/jackd/org.jackaudio.service.in
+new file mode 100644
+--- /dev/null
++++ b/jackd/org.jackaudio.service.in
+@@ -0,0 +1,3 @@
++[D-BUS Service]
++Name=org.jackaudio.service
++Exec=@bindir@/jackdbus auto

Added: trunk/overlays/proaudio/media-sound/jack-audio-connection-kit/files/jack-logs-20071209-r1070.patch
===================================================================
--- trunk/overlays/proaudio/media-sound/jack-audio-connection-kit/files/jack-logs-20071209-r1070.patch	                        (rev 0)
+++ trunk/overlays/proaudio/media-sound/jack-audio-connection-kit/files/jack-logs-20071209-r1070.patch	2007-12-10 21:09:08 UTC (rev 993)
@@ -0,0 +1,1877 @@
+diff --git a/drivers/alsa-midi/alsa_rawmidi.c b/drivers/alsa-midi/alsa_rawmidi.c
+--- a/drivers/alsa-midi/alsa_rawmidi.c
++++ b/drivers/alsa-midi/alsa_rawmidi.c
+@@ -218,7 +218,7 @@ int stream_init(midi_stream_t *s, alsa_r
+ 	s->name = name;
+ 	if (pipe(s->wake_pipe)==-1) {
+ 		s->wake_pipe[0] = -1;
+-		error_log("pipe() in stream_init(%s) failed: %s\n", name, strerror(errno));
++		error_log("pipe() in stream_init(%s) failed: %s", name, strerror(errno));
+ 		return -errno;
+ 	}
+ 	s->jack.new_ports = jack_ringbuffer_create(sizeof(midi_port_t*)*MAX_PORTS);
+@@ -256,7 +256,7 @@ alsa_midi_t* alsa_rawmidi_new(jack_clien
+ 		goto fail_0;
+ 	midi->client = jack;
+ 	if (pipe(midi->scan.wake_pipe)==-1) {
+-		error_log("pipe() in alsa_midi_new failed: %s\n", strerror(errno));
++		error_log("pipe() in alsa_midi_new failed: %s", strerror(errno));
+ 		goto fail_1;
+ 	}
+ 
+@@ -526,7 +526,7 @@ static inline
+ static inline
+ void alsa_error(const char *func, int err)
+ {
+-	error_log("%s() failed\n", snd_strerror(err));
++	error_log("%s() failed", snd_strerror(err));
+ }
+ 
+ typedef struct {
+@@ -555,14 +555,14 @@ void scan_cycle(alsa_rawmidi_t *midi)
+ 	scan_t scan;
+ 	midi_port_t **ports;
+ 
+-	//debug_log("scan: cleanup\n");
++	//debug_log("scan: cleanup");
+ 	scan_cleanup(midi);
+ 
+ 	scan.midi = midi;
+ 	scan.iterator = &midi->scan.ports;
+ 	snd_rawmidi_info_alloca(&scan.info);
+ 
+-	//debug_log("scan: rescan\n");
++	//debug_log("scan: rescan");
+ 	while ((err = snd_card_next(&card))>=0 && card>=0) {
+ 		char name[32];
+ 		snprintf(name, sizeof(name), "hw:%d", card);
+@@ -665,7 +665,7 @@ midi_port_t** scan_port_add(scan_t *scan
+ 
+ 	port->next = *list;
+ 	*list = port;
+-	error_log("scan: added port %s %s\n", port->dev, port->name);
++	error_log("scan: added port %s %s", port->dev, port->name);
+ 	return &port->next;
+ }
+ 
+@@ -689,7 +689,7 @@ midi_port_t** scan_port_open(alsa_rawmid
+ 	port->state = PORT_ADDED_TO_JACK;
+ 	jack_ringbuffer_write(str->jack.new_ports, (char*) &port, sizeof(port));
+ 
+-	error_log("scan: opened port %s %s\n", port->dev, port->name);
++	error_log("scan: opened port %s %s", port->dev, port->name);
+ 	return &port->next;
+ 
+  fail_2:
+@@ -698,7 +698,7 @@ midi_port_t** scan_port_open(alsa_rawmid
+ 	midi_port_close(midi, port);
+  fail_0:
+  	*list = port->next;
+-	error_log("scan: can't open port %s %s\n", port->dev, port->name);
++	error_log("scan: can't open port %s %s", port->dev, port->name);
+  	free(port);
+ 	return list;
+ }
+@@ -708,7 +708,7 @@ midi_port_t** scan_port_del(alsa_rawmidi
+ {
+ 	midi_port_t *port = *list;
+ 	if (port->state == PORT_REMOVED_FROM_JACK) {
+-		error_log("scan: deleted port %s %s\n", port->dev, port->name);
++		error_log("scan: deleted port %s %s", port->dev, port->name);
+ 		*list = port->next;
+ 		if (port->id.id[2] )
+ 			(midi->out.port_close)(midi, port);
+@@ -718,7 +718,7 @@ midi_port_t** scan_port_del(alsa_rawmidi
+ 		free(port);
+ 		return list;
+ 	} else {
+-		//debug_log("can't delete port %s, wrong state: %d\n", port->name, (int)port->state);
++		//debug_log("can't delete port %s, wrong state: %d", port->name, (int)port->state);
+ 		return &port->next;
+ 	}
+ }
+@@ -732,7 +732,7 @@ void* scan_thread(void *arg)
+ 	wakeup.events = POLLIN|POLLERR|POLLNVAL;
+ 	while (midi->keep_walking) {
+ 		int res;
+-		//error_log("scanning....\n");
++		//error_log("scanning....");
+ 		scan_cycle(midi);
+ 		res = poll(&wakeup, 1, 2000);
+ 		if (res>0) {
+@@ -778,7 +778,7 @@ void jack_process(midi_stream_t *str, ja
+ 	if (proc.frame_time + proc.nframes < cur_frames) {
+ 		int periods_lost = (cur_frames - proc.frame_time) / proc.nframes;
+ 		proc.frame_time += periods_lost * proc.nframes;
+-		debug_log("xrun detected: %d periods lost\n", periods_lost);
++		debug_log("xrun detected: %d periods lost", periods_lost);
+ 	}
+ 
+ 	// process existing ports
+@@ -804,7 +804,7 @@ void jack_process(midi_stream_t *str, ja
+ 		++w;
+ 	}
+ 	if (str->jack.nports != w)
+-		debug_log("jack_%s: nports %d -> %d\n", str->name, str->jack.nports, w);
++		debug_log("jack_%s: nports %d -> %d", str->name, str->jack.nports, w);
+ 	str->jack.nports = w;
+ 
+ 	jack_add_ports(str); // it makes no sense to add them earlier since they have no data yet
+@@ -830,7 +830,7 @@ void *midi_thread(void *arg)
+ 	pfds[0].events = POLLIN|POLLERR|POLLNVAL;
+ 	npfds = 1;
+ 
+-	//debug_log("midi_thread(%s): enter\n", str->name);
++	//debug_log("midi_thread(%s): enter", str->name);
+ 
+ 	while (midi->keep_walking) {
+ 		int poll_timeout;
+@@ -852,13 +852,13 @@ void *midi_thread(void *arg)
+ 			clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);
+ 		}
+ 		int res = poll((struct pollfd*)&pfds, npfds, poll_timeout);
+-		//debug_log("midi_thread(%s): poll exit: %d\n", str->name, res);
++		//debug_log("midi_thread(%s): poll exit: %d", str->name, res);
+ 		if (!midi->keep_walking)
+ 			break;
+ 		if (res < 0) {
+ 			if (errno == EINTR)
+ 				continue;
+-			error_log("midi_thread(%s) poll failed: %s\n", str->name, strerror(errno));
++			error_log("midi_thread(%s) poll failed: %s", str->name, strerror(errno));
+ 			break;
+ 		}
+ 
+@@ -875,7 +875,7 @@ void *midi_thread(void *arg)
+ 			midi_port_t *port;
+ 			jack_ringbuffer_read(str->midi.new_ports, (char*)&port, sizeof(port));
+ 			str->midi.ports[str->midi.nports++] = port;
+-			debug_log("midi_thread(%s): added port %s\n", str->name, port->name);
++			debug_log("midi_thread(%s): added port %s", str->name, port->name);
+ 		}
+ 
+ //		if (res == 0)
+@@ -903,10 +903,10 @@ void *midi_thread(void *arg)
+ 			++wp;
+ 		}
+ 		if (str->midi.nports != wp)
+-			debug_log("midi_%s: nports %d -> %d\n", str->name, str->midi.nports, wp);
++			debug_log("midi_%s: nports %d -> %d", str->name, str->midi.nports, wp);
+ 		str->midi.nports = wp;
+ 		if (npfds != w)
+-			debug_log("midi_%s: npfds %d -> %d\n", str->name, npfds, w);
++			debug_log("midi_%s: npfds %d -> %d", str->name, npfds, w);
+ 		npfds = w;
+ 
+ 		/*
+@@ -915,16 +915,16 @@ void *midi_thread(void *arg)
+ 		 * So, zero timeout will not cause busy-looping.
+ 		 */
+ 		if (proc.next_time < proc.cur_time) {
+-			debug_log("%s: late: next_time = %d, cur_time = %d\n", str->name, (int)proc.next_time, (int)proc.cur_time);
++			debug_log("%s: late: next_time = %d, cur_time = %d", str->name, (int)proc.next_time, (int)proc.cur_time);
+ 			wait_nsec = 0; // we are late
+ 		} else if (proc.next_time != NFRAMES_INF) {
+ 			jack_time_t wait_frames = proc.next_time - proc.cur_time;
+ 			jack_nframes_t rate = jack_get_sample_rate(midi->client);
+ 			wait_nsec = (wait_frames * (1000*1000*1000)) / rate;
+-			debug_log("midi_%s: timeout = %d\n", str->name, (int)wait_frames);
++			debug_log("midi_%s: timeout = %d", str->name, (int)wait_frames);
+ 		} else
+ 			wait_nsec = 1000*1000*1000;
+-		//debug_log("midi_thread(%s): wait_nsec = %lld\n", str->name, wait_nsec);
++		//debug_log("midi_thread(%s): wait_nsec = %lld", str->name, wait_nsec);
+ 	}
+ 	return NULL;
+ }
+@@ -937,17 +937,17 @@ int midi_is_ready(process_midi_t *proc)
+ 		unsigned short revents = 0;
+ 		int res = snd_rawmidi_poll_descriptors_revents(port->rawmidi, proc->rpfds, port->npfds, &revents);
+ 		if (res) {
+-			error_log("snd_rawmidi_poll_descriptors_revents failed on port %s with: %s\n", port->name, snd_strerror(res));
++			error_log("snd_rawmidi_poll_descriptors_revents failed on port %s with: %s", port->name, snd_strerror(res));
+ 			return 0;
+ 		}
+ 
+ 		if (revents & ~proc->mode) {
+-			debug_log("midi: port %s failed\n", port->name);
++			debug_log("midi: port %s failed", port->name);
+ 			return 0;
+ 		}
+ 		if (revents & proc->mode) {
+ 			port->is_ready = 1;
+-			debug_log("midi: is_ready %s\n", port->name);
++			debug_log("midi: is_ready %s", port->name);
+ 		}
+ 	}
+ 	return 1;
+@@ -960,7 +960,7 @@ int midi_update_pfds(process_midi_t *pro
+ 	if (port->npfds == 0) {
+ 		port->npfds = snd_rawmidi_poll_descriptors_count(port->rawmidi);
+ 		if (port->npfds > proc->max_pfds) {
+-			debug_log("midi: not enough pfds for port %s\n", port->name);
++			debug_log("midi: not enough pfds for port %s", port->name);
+ 			return 0;
+ 		}
+ 		snd_rawmidi_poll_descriptors(port->rawmidi, proc->wpfds, port->npfds);
+@@ -1021,7 +1021,7 @@ void do_jack_input(process_jack_t *p)
+ 			int avail = todo < vec[i].len ? todo : vec[i].len;
+ 			int done = midi_unpack_buf(&port->unpack, (unsigned char*)vec[i].buf, avail, p->buffer, time);
+ 			if (done != avail) {
+-				debug_log("jack_in: buffer overflow in port %s\n", port->base.name);
++				debug_log("jack_in: buffer overflow in port %s", port->base.name);
+ 				break;
+ 			}
+ 			todo -= done;
+@@ -1048,14 +1048,14 @@ int do_midi_input(process_midi_t *proc)
+ 		if (jack_ringbuffer_write_space(port->base.event_ring) < sizeof(event_head_t) || vec[0].len < 1) {
+ 			port->overruns++;
+ 			if (port->base.npfds)
+-				debug_log("midi_in: internal overflow on %s\n", port->base.name);
++				debug_log("midi_in: internal overflow on %s", port->base.name);
+ 			// remove from poll to prevent busy-looping
+ 			port->base.npfds = 0;
+ 			return 1;
+ 		}
+ 		res = snd_rawmidi_read(port->base.rawmidi, vec[0].buf, vec[0].len);
+ 		if (res < 0 && res != -EWOULDBLOCK) {
+-			error_log("midi_in: reading from port %s failed: %s\n", port->base.name, snd_strerror(res));
++			error_log("midi_in: reading from port %s failed: %s", port->base.name, snd_strerror(res));
+ 			return 0;
+ 		} else if (res > 0) {
+ 			event_head_t event;
+@@ -1063,7 +1063,7 @@ int do_midi_input(process_midi_t *proc)
+ 			event.size = res;
+ 			event.overruns = port->overruns;
+ 			port->overruns = 0;
+-			debug_log("midi_in: read %d bytes at %d\n", (int)event.size, (int)event.time);
++			debug_log("midi_in: read %d bytes at %d", (int)event.size, (int)event.time);
+ 			jack_ringbuffer_write_advance(port->base.data_ring, event.size);
+ 			jack_ringbuffer_write(port->base.event_ring, (char*)&event, sizeof(event));
+ 		}
+@@ -1101,7 +1101,7 @@ void do_jack_output(process_jack_t *proc
+ 	int nevents = jack_midi_get_event_count(proc->buffer);
+ 	int i;
+ 	if (nevents)
+-		debug_log("jack_out: %d events in %s\n", nevents, port->base.name);
++		debug_log("jack_out: %d events in %s", nevents, port->base.name);
+ 	for (i=0; i<nevents; ++i) {
+ 		jack_midi_event_t event;
+ 		event_head_t hdr;
+@@ -1109,7 +1109,7 @@ void do_jack_output(process_jack_t *proc
+ 		jack_midi_event_get(&event, proc->buffer, i);
+ 
+ 		if (jack_ringbuffer_write_space(port->base.data_ring) < event.size || jack_ringbuffer_write_space(port->base.event_ring) < sizeof(hdr)) {
+-			debug_log("jack_out: output buffer overflow on %s\n", port->base.name);
++			debug_log("jack_out: output buffer overflow on %s", port->base.name);
+ 			break;
+ 		}
+ 
+@@ -1120,7 +1120,7 @@ void do_jack_output(process_jack_t *proc
+ 		hdr.time = proc->frame_time + event.time + proc->nframes;
+ 		hdr.size = event.size;
+ 		jack_ringbuffer_write(port->base.event_ring, (char*)&hdr, sizeof(hdr));
+-		debug_log("jack_out: sent %d-byte event at %ld\n", (int)event.size, (long)event.time);
++		debug_log("jack_out: sent %d-byte event at %ld", (int)event.size, (long)event.time);
+ 	}
+ }
+ 
+@@ -1141,16 +1141,16 @@ int do_midi_output(process_midi_t *proc)
+ 			port->next_event.size = 0;
+ 			break;
+ 		} else
+-			debug_log("midi_out: at %ld got %d bytes for %ld\n", (long)proc->cur_time, (int)port->next_event.size, (long)port->next_event.time);
++			debug_log("midi_out: at %ld got %d bytes for %ld", (long)proc->cur_time, (int)port->next_event.size, (long)port->next_event.time);
+ 	}
+ 	
+ 	if (port->todo)
+-		debug_log("midi_out: todo = %d at %ld\n", (int)port->todo, (long)proc->cur_time);
++		debug_log("midi_out: todo = %d at %ld", (int)port->todo, (long)proc->cur_time);
+ 
+ 	// calc next wakeup time
+ 	if (!port->todo && port->next_event.time && port->next_event.time < proc->next_time) {
+ 		proc->next_time = port->next_event.time;
+-		debug_log("midi_out: next_time = %ld\n", (long)proc->next_time);
++		debug_log("midi_out: next_time = %ld", (long)proc->next_time);
+ 	}
+ 
+ 	if (port->todo && port->base.is_ready) {
+@@ -1167,15 +1167,15 @@ int do_midi_output(process_midi_t *proc)
+ 		res = snd_rawmidi_write(port->base.rawmidi, vec[0].buf, size);
+ 		if (res > 0) {
+ 			jack_ringbuffer_read_advance(port->base.data_ring, res);
+-			debug_log("midi_out: written %d bytes to %s\n", res, port->base.name);
++			debug_log("midi_out: written %d bytes to %s", res, port->base.name);
+ 			port->todo -= res;
+ 			worked = 1;
+ 		} else if (res == -EWOULDBLOCK) {
+ 			port->base.is_ready = 0;
+-			debug_log("midi_out: -EWOULDBLOCK on %s\n", port->base.name);
++			debug_log("midi_out: -EWOULDBLOCK on %s", port->base.name);
+ 			return 1;
+ 		} else {
+-			error_log("midi_out: writing to port %s failed: %s\n", port->base.name, snd_strerror(res));
++			error_log("midi_out: writing to port %s failed: %s", port->base.name, snd_strerror(res));
+ 			return 0;
+ 		}
+ 		snd_rawmidi_drain(port->base.rawmidi);
+@@ -1188,7 +1188,7 @@ int do_midi_output(process_midi_t *proc)
+ 	if (!port->todo) {
+ 		int i;
+ 		if (worked)
+-			debug_log("midi_out: relaxing on %s\n", port->base.name);
++			debug_log("midi_out: relaxing on %s", port->base.name);
+ 		for (i=0; i<port->base.npfds; ++i)
+ 			proc->wpfds[i].events &= ~POLLOUT;
+ 	} else {
+diff --git a/drivers/alsa/alsa_driver.c b/drivers/alsa/alsa_driver.c
+--- a/drivers/alsa/alsa_driver.c
++++ b/drivers/alsa/alsa_driver.c
+@@ -115,7 +115,7 @@ alsa_driver_check_card_type (alsa_driver
+ 		char tmp[5];
+ 		strncpy(tmp,strstr(driver->alsa_name_playback,"hw"),4);
+ 		tmp[4]='\0';
+-		printf("control device %s\n",tmp);
++		jack_info("control device %s",tmp);
+ 		ctl_name = strdup(tmp);
+ 	} else {
+ 		ctl_name = strdup(driver->alsa_name_playback);
+@@ -243,21 +243,21 @@ alsa_driver_setup_io_function_pointers (
+ 
+ 		switch (driver->dither) {
+ 			case Rectangular:
+-			printf("Rectangular dithering at 16 bits\n");
++			jack_info("Rectangular dithering at 16 bits");
+ 			driver->write_via_copy = driver->quirk_bswap?
+ 				sample_move_dither_rect_d16_sSs:
+ 				sample_move_dither_rect_d16_sS;
+ 			break;
+ 
+ 			case Triangular:
+-			printf("Triangular dithering at 16 bits\n");
++			jack_info("Triangular dithering at 16 bits");
+ 			driver->write_via_copy = driver->quirk_bswap?
+ 				sample_move_dither_tri_d16_sSs:
+ 				sample_move_dither_tri_d16_sS;
+ 			break;
+ 
+ 			case Shaped:
+-			printf("Noise-shaped dithering at 16 bits\n");
++			jack_info("Noise-shaped dithering at 16 bits");
+ 			driver->write_via_copy = driver->quirk_bswap?
+ 				sample_move_dither_shaped_d16_sSs:
+ 				sample_move_dither_shaped_d16_sS;
+@@ -279,21 +279,21 @@ alsa_driver_setup_io_function_pointers (
+ 
+ 		switch (driver->dither) {
+ 			case Rectangular:
+-			printf("Rectangular dithering at 16 bits\n");
++			jack_info("Rectangular dithering at 16 bits");
+ 			driver->write_via_copy = driver->quirk_bswap?
+ 				sample_move_dither_rect_d24_sSs:
+ 				sample_move_dither_rect_d24_sS;
+ 			break;
+ 
+ 			case Triangular:
+-			printf("Triangular dithering at 16 bits\n");
++			jack_info("Triangular dithering at 16 bits");
+ 			driver->write_via_copy = driver->quirk_bswap?
+ 				sample_move_dither_tri_d24_sSs:
+ 				sample_move_dither_tri_d24_sS;
+ 			break;
+ 
+ 			case Shaped:
+-			printf("Noise-shaped dithering at 16 bits\n");
++			jack_info("Noise-shaped dithering at 16 bits");
+ 			driver->write_via_copy = driver->quirk_bswap?
+ 				sample_move_dither_shaped_d24_sSs:
+ 				sample_move_dither_shaped_d24_sS;
+@@ -315,21 +315,21 @@ alsa_driver_setup_io_function_pointers (
+ 		
+ 		switch (driver->dither) {
+ 			case Rectangular:
+-			printf("Rectangular dithering at 16 bits\n");
++			jack_info("Rectangular dithering at 16 bits");
+ 			driver->write_via_copy = driver->quirk_bswap?
+ 				sample_move_dither_rect_d32u24_sSs:
+ 				sample_move_dither_rect_d32u24_sS;
+ 			break;
+ 
+ 			case Triangular:
+-			printf("Triangular dithering at 16 bits\n");
++			jack_info("Triangular dithering at 16 bits");
+ 			driver->write_via_copy = driver->quirk_bswap?
+ 				sample_move_dither_tri_d32u24_sSs:
+ 				sample_move_dither_tri_d32u24_sS;
+ 			break;
+ 
+ 			case Shaped:
+-			printf("Noise-shaped dithering at 16 bits\n");
++			jack_info("Noise-shaped dithering at 16 bits");
+ 			driver->write_via_copy = driver->quirk_bswap?
+ 				sample_move_dither_shaped_d32u24_sSs:
+ 				sample_move_dither_shaped_d32u24_sS;
+@@ -436,7 +436,7 @@ alsa_driver_configure_stream (alsa_drive
+ 			} else {
+ 				driver->quirk_bswap = 0;
+ 			}
+-			jack_error ("ALSA: final selected sample format for %s: %s", stream_name, formats[format].Name);
++			jack_info ("ALSA: final selected sample format for %s: %s", stream_name, formats[format].Name);
+ 			break;
+ 		}
+ 	} 
+@@ -514,7 +514,7 @@ alsa_driver_configure_stream (alsa_drive
+ 			    stream_name);
+ 		return -1;
+ 	}
+-	jack_error ("ALSA: use %d periods for %s", *nperiodsp, stream_name);
++	jack_info ("ALSA: use %d periods for %s", *nperiodsp, stream_name);
+ 	
+ 	if (!jack_power_of_two(driver->frames_per_cycle)) {
+ 		jack_error("JACK: frames must be a power of two "
+@@ -567,7 +567,7 @@ alsa_driver_configure_stream (alsa_drive
+ 	}
+ 
+ #if 0
+-	fprintf (stderr, "set silence size to %lu * %lu = %lu\n",
++	jack_info ("set silence size to %lu * %lu = %lu",
+ 		 driver->frames_per_cycle, *nperiodsp,
+ 		 driver->frames_per_cycle * *nperiodsp);
+ 
+@@ -621,8 +621,8 @@ alsa_driver_set_parameters (alsa_driver_
+ 	driver->frames_per_cycle = frames_per_cycle;
+ 	driver->user_nperiods = user_nperiods;
+ 
+-	fprintf (stderr, "configuring for %" PRIu32 "Hz, period = %"
+-		 PRIu32 " frames (%.1f ms), buffer = %" PRIu32 " periods\n",
++	jack_info ("configuring for %" PRIu32 "Hz, period = %"
++		 PRIu32 " frames (%.1f ms), buffer = %" PRIu32 " periods",
+ 		 rate, frames_per_cycle, (((float)frames_per_cycle / (float) rate) * 1000.0f), user_nperiods);
+ 	
+ 	if (driver->capture_handle) {
+@@ -1299,7 +1299,7 @@ alsa_driver_wait (alsa_driver_t *driver,
+ 		if (poll_result < 0) {
+ 
+ 			if (errno == EINTR) {
+-				printf ("poll interrupt\n");
++				jack_info ("poll interrupt");
+ 				// this happens mostly when run
+ 				// under gdb, or when exiting due to a signal
+ 				if (under_gdb) {
+@@ -1329,8 +1329,8 @@ alsa_driver_wait (alsa_driver_t *driver,
+ 		}
+ 
+ #ifdef DEBUG_WAKEUP
+-		fprintf (stderr, "%" PRIu64 ": checked %d fds, %" PRIu64
+-			 " usecs since poll entered\n", poll_ret, nfds,
++		jack_info ("%" PRIu64 ": checked %d fds, %" PRIu64
++			 " usecs since poll entered", poll_ret, nfds,
+ 			 poll_ret - poll_enter);
+ #endif
+ 
+@@ -1368,8 +1368,8 @@ alsa_driver_wait (alsa_driver_t *driver,
+ 			if (revents & POLLOUT) {
+ 				need_playback = 0;
+ #ifdef DEBUG_WAKEUP
+-				fprintf (stderr, "%" PRIu64
+-					 " playback stream ready\n",
++				jack_info ("%" PRIu64
++					 " playback stream ready",
+ 					 poll_ret);
+ #endif
+ 			}
+@@ -1391,8 +1391,8 @@ alsa_driver_wait (alsa_driver_t *driver,
+ 			if (revents & POLLIN) {
+ 				need_capture = 0;
+ #ifdef DEBUG_WAKEUP
+-				fprintf (stderr, "%" PRIu64
+-					 " capture stream ready\n",
++				jack_info ("%" PRIu64
++					 " capture stream ready",
+ 					 poll_ret);
+ #endif
+ 			}
+@@ -1449,8 +1449,8 @@ alsa_driver_wait (alsa_driver_t *driver,
+ 	avail = capture_avail < playback_avail ? capture_avail : playback_avail;
+ 
+ #ifdef DEBUG_WAKEUP
+-	fprintf (stderr, "wakeup complete, avail = %lu, pavail = %lu "
+-		 "cavail = %lu\n",
++	jack_info ("wakeup complete, avail = %lu, pavail = %lu "
++		 "cavail = %lu",
+ 		 avail, playback_avail, capture_avail);
+ #endif
+ 
+@@ -1600,7 +1600,7 @@ alsa_driver_read (alsa_driver_t *driver,
+ 		if ((err = snd_pcm_mmap_commit (driver->capture_handle,
+ 				offset, contiguous)) < 0) {
+ 			jack_error ("ALSA: could not complete read of %"
+-				PRIu32 " frames: error = %d\n", contiguous, err);
++				PRIu32 " frames: error = %d", contiguous, err);
+ 			return -1;
+ 		}
+ 
+@@ -2011,8 +2011,8 @@ alsa_driver_new (char *name, char *playb
+ 
+ 	alsa_driver_t *driver;
+ 
+-	printf ("creating alsa driver ... %s|%s|%" PRIu32 "|%" PRIu32
+-		"|%" PRIu32"|%" PRIu32"|%" PRIu32 "|%s|%s|%s|%s\n",
++	jack_info ("creating alsa driver ... %s|%s|%" PRIu32 "|%" PRIu32
++		"|%" PRIu32"|%" PRIu32"|%" PRIu32 "|%s|%s|%s|%s",
+ 		playing ? playback_alsa_device : "-",
+ 		capturing ? capture_alsa_device : "-", 
+ 		frames_per_cycle, user_nperiods, rate,
+@@ -2343,7 +2343,7 @@ dither_opt (char c, DitherAlgorithm* dit
+ 		break;
+ 		
+ 	default:
+-		fprintf (stderr, "ALSA driver: illegal dithering mode %c\n", c);
++		jack_error ("ALSA driver: illegal dithering mode %c", c);
+ 		return -1;
+ 	}
+ 	return 0;
+@@ -2600,7 +2600,7 @@ driver_initialize (jack_client_t *client
+ 
+ 		case 'r':
+ 		        srate = param->value.ui;
+-			fprintf (stderr, "apparent rate = %d\n", srate);
++			jack_info ("apparent rate = %d", srate);
+ 		        break;
+ 			
+ 		case 'p':
+diff --git a/drivers/alsa/hammerfall.c b/drivers/alsa/hammerfall.c
+--- a/drivers/alsa/hammerfall.c
++++ b/drivers/alsa/hammerfall.c
+@@ -109,7 +109,7 @@ hammerfall_check_sync (hammerfall_t *h, 
+ 	int val;
+ 	snd_ctl_elem_id_t *ctl_id;
+ 	
+-	printf ("check sync\n");
++	jack_info ("check sync");
+ 
+ 	snd_ctl_elem_id_alloca (&ctl_id);
+ 	snd_ctl_elem_value_get_id (ctl, ctl_id);
+diff --git a/drivers/alsa/usx2y.c b/drivers/alsa/usx2y.c
+--- a/drivers/alsa/usx2y.c
++++ b/drivers/alsa/usx2y.c
+@@ -122,7 +122,7 @@ usx2y_driver_get_channel_addresses_playb
+ 	if (dbg_offset < (sizeof(dbg_buffer) - 256))
+ 		dbg_offset += sprintf(dbg_buffer + dbg_offset, "avail %li@%p\n", *playback_avail, driver->playback_addr[0]);
+ 	else {
+-		printf(dbg_buffer);
++		jack_info_multiline(dbg_buffer);
+ 		return -1;
+ 	}
+ #endif
+@@ -196,7 +196,7 @@ usx2y_driver_get_channel_addresses_captu
+ 	if (dbg_offset < (sizeof(dbg_buffer) - 256))
+ 		dbg_offset += sprintf(dbg_buffer + dbg_offset, "avail %li@%p\n", *capture_avail, driver->capture_addr[0]);
+ 	else {
+-		printf(dbg_buffer);
++		jack_info_multiline(dbg_buffer);
+ 		return -1;
+ 	}
+ #endif
+@@ -391,7 +391,7 @@ usx2y_driver_null_cycle (alsa_driver_t* 
+ 	int chn;
+ 
+ 	VERBOSE(driver->engine,
+-		"usx2y_driver_null_cycle (%p, %i)\n", driver, nframes);
++		"usx2y_driver_null_cycle (%p, %i)", driver, nframes);
+ 
+ 	if (driver->capture_handle) {
+ 		nf = nframes;
+@@ -675,8 +675,8 @@ jack_alsa_usx2y_hw_new (alsa_driver_t *d
+ 			hw->private = h;
+ 			/* Set our own operational function pointers. */
+ 			usx2y_driver_setup(driver);
+-			printf("ALSA/USX2Y: EXPERIMENTAL hwdep pcm device %s"
+-				" (aka \"rawusb\")\n", driver->alsa_name_playback);
++			jack_info("ALSA/USX2Y: EXPERIMENTAL hwdep pcm device %s"
++				" (aka \"rawusb\")", driver->alsa_name_playback);
+ 		}
+ 	}
+ 
+diff --git a/drivers/coreaudio/coreaudio_driver.c b/drivers/coreaudio/coreaudio_driver.c
+--- a/drivers/coreaudio/coreaudio_driver.c
++++ b/drivers/coreaudio/coreaudio_driver.c
+@@ -272,8 +272,8 @@ static OSStatus display_device_names()
+ 		err = AudioDeviceGetProperty(devices[i], 0, false, kAudioDevicePropertyDeviceName, &size, device_name);
+ 		if (err != noErr) 
+ 			return err; 
+-		printf("ICI\n");
+-		printf("Device name = \'%s\', internal_name = \'%s\' (to be used as -d parameter)\n", device_name, internal_name); 
++		jack_info("ICI");
++		jack_info("Device name = \'%s\', internal_name = \'%s\' (to be used as -d parameter)", device_name, internal_name); 
+ 	}
+ 	
+ 	return noErr;
+@@ -627,7 +627,7 @@ static jack_driver_t *coreaudio_driver_n
+     jack_driver_init((jack_driver_t *) driver);
+ 
+     if (!jack_power_of_two(nframes)) {
+-		fprintf(stderr, "CA: -p must be a power of two.\n");
++		jack_error("CA: -p must be a power of two.");
+ 		goto error;
+     }
+ 
+diff --git a/drivers/dummy/dummy_driver.c b/drivers/dummy/dummy_driver.c
+--- a/drivers/dummy/dummy_driver.c
++++ b/drivers/dummy/dummy_driver.c
+@@ -50,7 +50,7 @@ FakeVideoSync( dummy_driver_t *driver )
+         jack_position_t *position = &driver->engine->control->current_time;
+ 
+         if ( period >= VIDEO_SYNC_PERIOD ) {
+-                printf("JACK driver period size too large for simple video sync emulation. Halting.\n");
++                jack_error("JACK driver period size too large for simple video sync emulation. Halting.");
+                 exit(0);
+         }
+ 
+@@ -87,7 +87,7 @@ dummy_driver_wait (dummy_driver_t *drive
+ 			    > (PRETEND_BUFFER_SIZE * 1000000LL
+ 			       / driver->sample_rate)) {
+ 			/* xrun */
+-			fprintf(stderr,"**** dummy: xrun of %ju usec\n",
++			jack_error("**** dummy: xrun of %ju usec",
+ 				(uintmax_t)now - driver->next_time);
+ 			driver->next_time = now + driver->wait_time;
+ 		} else {
+@@ -267,8 +267,8 @@ dummy_driver_new (jack_client_t * client
+ {
+ 	dummy_driver_t * driver;
+ 
+-	printf ("creating dummy driver ... %s|%" PRIu32 "|%" PRIu32
+-		"|%lu|%u|%u\n", name, sample_rate, period_size, wait_time,
++	jack_info ("creating dummy driver ... %s|%" PRIu32 "|%" PRIu32
++		"|%lu|%u|%u", name, sample_rate, period_size, wait_time,
+ 		capture_ports, playback_ports);
+ 
+ 	driver = (dummy_driver_t *) calloc (1, sizeof (dummy_driver_t));
+diff --git a/drivers/oss/oss_driver.c b/drivers/oss/oss_driver.c
+--- a/drivers/oss/oss_driver.c
++++ b/drivers/oss/oss_driver.c
+@@ -599,14 +599,14 @@ static int oss_driver_start (oss_driver_
+ 			jack_error(
+ 				"OSS: failed to set samplerate for %s: %s@%i, errno=%d", 
+ 				indev, __FILE__, __LINE__, errno);
+-		printf("oss_driver: %s : 0x%x/%i/%i (%i)\n", indev, 
++		jack_info("oss_driver: %s : 0x%x/%i/%i (%i)", indev, 
+ 			format, channels, samplerate, get_fragment(infd));
+ 		
+ 		period_size = get_fragment(infd) / samplesize / channels;
+ 		if (period_size != driver->period_size && 
+ 			!driver->ignorehwbuf)
+ 		{
+-			printf("oss_driver: period size update: %u\n",
++			jack_info("oss_driver: period size update: %u",
+ 				period_size);
+ 			driver->period_size = period_size;
+ 			driver->period_usecs = 
+@@ -634,7 +634,7 @@ static int oss_driver_start (oss_driver_
+ 			jack_error(
+ 				"OSS: failed to set samplerate for %s: %s@%i, errno=%d", 
+ 				outdev, __FILE__, __LINE__, errno);
+-		printf("oss_driver: %s : 0x%x/%i/%i (%i)\n", outdev, 
++		jack_info("oss_driver: %s : 0x%x/%i/%i (%i)", outdev, 
+ 			format, channels, samplerate, 
+ 			get_fragment(outfd));
+ 
+@@ -642,7 +642,7 @@ static int oss_driver_start (oss_driver_
+ 		if (period_size != driver->period_size &&
+ 			!driver->ignorehwbuf)
+ 		{
+-			printf("oss_driver: period size update: %u\n",
++			jack_indo("oss_driver: period size update: %u",
+ 				period_size);
+ 			driver->period_size = period_size;
+ 			driver->period_usecs = 
+@@ -691,7 +691,7 @@ static int oss_driver_start (oss_driver_
+ 		driver->outdevbuf = NULL;
+ 	}
+ 
+-	printf("oss_driver: indevbuf %zd B, outdevbuf %zd B\n",
++	jack_info("oss_driver: indevbuf %zd B, outdevbuf %zd B",
+ 		driver->indevbufsize, driver->outdevbufsize);
+ 
+ 	pthread_mutex_init(&driver->mutex_in, NULL);
+@@ -907,7 +907,7 @@ static int oss_driver_bufsize (oss_drive
+ 
+ 	set_period_size(driver, nframes);
+ 	driver->engine->set_buffer_size(driver->engine, driver->period_size);
+-	printf("oss_driver: period size update: %u\n", nframes);
++	jack_info("oss_driver: period size update: %u", nframes);
+ 
+ 	oss_driver_start(driver);
+ 
+@@ -1102,7 +1102,7 @@ jack_driver_desc_t * driver_get_descript
+ 	desc = (jack_driver_desc_t *) calloc(1, sizeof(jack_driver_desc_t));
+ 	if (desc == NULL)
+ 	{
+-		printf("oss_driver: calloc() failed: %s@%i, errno=%d\n",
++		jack_error("oss_driver: calloc() failed: %s@%i, errno=%d",
+ 			__FILE__, __LINE__, errno);
+ 		return NULL;
+ 	}
+@@ -1112,7 +1112,7 @@ jack_driver_desc_t * driver_get_descript
+ 	params = calloc(desc->nparams, sizeof(jack_driver_param_desc_t));
+ 	if (params == NULL)
+ 	{
+-		printf("oss_driver: calloc() failed: %s@%i, errno=%d\n",
++		jack_error("oss_driver: calloc() failed: %s@%i, errno=%d",
+ 			__FILE__, __LINE__, errno);
+ 		return NULL;
+ 	}
+diff --git a/drivers/portaudio/portaudio_driver.c b/drivers/portaudio/portaudio_driver.c
+--- a/drivers/portaudio/portaudio_driver.c
++++ b/drivers/portaudio/portaudio_driver.c
+@@ -332,9 +332,9 @@ portaudio_driver_set_parameters (portaud
+ 
+ 		// JOQ: this driver is dead.  How do we terminate it?
+ 		Pa_Terminate();
+-		fprintf(stderr, "Unable to set portaudio parameters\n"); 
+-		fprintf(stderr, "Error number: %d\n", err);
+-		fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(err));
++		jack_error("Unable to set portaudio parameters");
++		jack_error("Error number: %d", err);
++		jack_error("Error message: %s", Pa_GetErrorText(err));
+ 		return EIO;
+ 	}
+ }
+@@ -345,8 +345,8 @@ portaudio_driver_reset_parameters (porta
+ 				   jack_nframes_t rate)
+ {
+ 	if (!jack_power_of_two(nframes)) {
+-		fprintf (stderr, "PA: frames must be a power of two "
+-			 "(64, 512, 1024, ...)\n");
++		jack_error("PA: frames must be a power of two "
++			 "(64, 512, 1024, ...)");
+ 		return EINVAL;
+ 	}
+ 
+@@ -541,7 +541,7 @@ portaudio_driver_new (char *name,
+ 	jack_driver_init ((jack_driver_t *) driver);
+ 
+ 	if (!jack_power_of_two(frames_per_cycle)) {
+-		fprintf (stderr, "PA: -p must be a power of two.\n");
++		jack_error ("PA: -p must be a power of two.");
+ 		goto error;
+ 	}
+ 
+@@ -653,9 +653,9 @@ error:
+ error:
+ 
+ 	Pa_Terminate();
+-	fprintf(stderr, "An error occured while using the portaudio stream\n"); 
+-	fprintf(stderr, "Error number: %d\n", err);
+-	fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(err));
++	jack_error("An error occured while using the portaudio stream");
++	jack_error("Error number: %d", err);
++	jack_error("Error message: %s", Pa_GetErrorText(err));
+ 	free(driver);
+ 	return NULL;
+ }
+diff --git a/jack/internal.h b/jack/internal.h
+--- a/jack/internal.h
++++ b/jack/internal.h
+@@ -36,6 +36,8 @@
+ 
+ /* Needed by <sysdeps/time.h> */
+ extern void jack_error (const char *fmt, ...);
++
++extern void jack_info (const char *fmt, ...);
+ 
+ #include <jack/jack.h>
+ #include <jack/types.h>
+diff --git a/jack/jack.h b/jack/jack.h
+--- a/jack/jack.h
++++ b/jack/jack.h
+@@ -856,6 +856,21 @@ extern void (*jack_error_callback)(const
+  */
+ void jack_set_error_function (void (*func)(const char *));
+ 
++/**
++ * Display JACK info message.
++ *
++ * Set via jack_set_info_function(), otherwise a JACK-provided
++ * default will print @a msg (plus a newline) to stdout.
++ *
++ * @param msg info message text (no newline at end).
++ */
++extern void (*jack_info_callback)(const char *msg);
++
++/**
++ * Set the @ref jack_info_callback for info message display.
++ */
++void jack_set_info_function (void (*func)(const char *));
++
+ #ifdef __cplusplus
+ }
+ #endif
+diff --git a/jackd/clientengine.c b/jackd/clientengine.c
+--- a/jackd/clientengine.c
++++ b/jackd/clientengine.c
+@@ -87,7 +87,7 @@ static void
+ static void
+ jack_zombify_client (jack_engine_t *engine, jack_client_internal_t *client)
+ {
+-	VERBOSE (engine, "removing client \"%s\" from the processing chain\n",
++	VERBOSE (engine, "removing client \"%s\" from the processing chain",
+ 		 client->control->name);
+ 
+ 	/* caller must hold the client_lock */
+@@ -109,7 +109,7 @@ jack_remove_client (jack_engine_t *engin
+ 
+ 	/* caller must hold the client_lock */
+ 
+-	VERBOSE (engine, "removing client \"%s\"\n", client->control->name);
++	VERBOSE (engine, "removing client \"%s\"", client->control->name);
+ 
+ 	/* if its not already a zombie, make it so */
+ 
+@@ -187,7 +187,7 @@ jack_remove_clients (jack_engine_t* engi
+ 			if (client->error >= JACK_ERROR_WITH_SOCKETS) {
+ 				VERBOSE (engine, "removing failed "
+ 					 "client %s state = %s errors"
+-					 " = %d\n", 
++					 " = %d", 
+ 					 client->control->name,
+ 					 jack_client_state_name (client),
+ 					 client->error);
+@@ -197,7 +197,7 @@ jack_remove_clients (jack_engine_t* engi
+ 			} else {
+ 				VERBOSE (engine, "client failure: "
+ 					 "client %s state = %s errors"
+-					 " = %d\n", 
++					 " = %d", 
+ 					 client->control->name,
+ 					 jack_client_state_name (client),
+ 					 client->error);
+@@ -527,7 +527,7 @@ setup_client (jack_engine_t *engine, Cli
+ 	}
+ 
+ 	VERBOSE (engine, "new client: %s, id = %" PRIu32
+-		 " type %d @ %p fd = %d\n", 
++		 " type %d @ %p fd = %d", 
+ 		 client->control->name, client->control->id, 
+ 		 type, client->control, client_fd);
+ 
+@@ -568,7 +568,7 @@ setup_client (jack_engine_t *engine, Cli
+ 
+ 				/* failed: clean up client data */
+ 				VERBOSE (engine,
+-					 "%s jack_initialize() failed!\n",
++					 "%s jack_initialize() failed!",
+ 					 client->control->name);
+ 				jack_lock_graph (engine);
+ 				jack_remove_client (engine, client);
+@@ -628,7 +628,7 @@ handle_unload_client (jack_engine_t *eng
+ 	jack_lock_graph (engine);
+ 
+ 	if ((client = jack_client_internal_by_id (engine, id))) {
+-		VERBOSE (engine, "unloading client \"%s\"\n",
++		VERBOSE (engine, "unloading client \"%s\"",
+ 			 client->control->name);
+ 		jack_remove_client (engine, client);
+ 		status = 0;
+@@ -824,7 +824,7 @@ jack_client_disconnect (jack_engine_t *e
+ 
+         if (client) {
+ 		VERBOSE (engine, "removing disconnected client %s state = "
+-			 "%s errors = %d\n", client->control->name,
++			 "%s errors = %d", client->control->name,
+ 			 jack_client_state_name (client),
+ 			 client->error);
+ 		jack_remove_client(engine, client);
+@@ -906,7 +906,7 @@ jack_intclient_load_request (jack_engine
+ 	jack_status_t status = 0;
+ 
+ 	VERBOSE (engine, "load internal client %s from %s, init `%s', "
+-		 "options: 0x%x\n", req->x.intclient.name,
++		 "options: 0x%x", req->x.intclient.name,
+ 		 req->x.intclient.path, req->x.intclient.init,
+ 		 req->x.intclient.options);
+ 
+@@ -917,7 +917,7 @@ jack_intclient_load_request (jack_engine
+ 	if (client == NULL) {
+ 		status |= JackFailure;	/* just making sure */
+ 		req->x.intclient.id = 0;
+-		VERBOSE (engine, "load failed, status = 0x%x\n", status);
++		VERBOSE (engine, "load failed, status = 0x%x", status);
+ 	} else {
+ 		req->x.intclient.id = client->control->id;
+ 	}
+@@ -955,7 +955,7 @@ jack_intclient_unload_request (jack_engi
+ 			handle_unload_client (engine, req->x.intclient.id);
+ 		pthread_mutex_lock (&engine->request_lock);
+ 	} else {
+-		VERBOSE (engine, "invalid unload request\n");
++		VERBOSE (engine, "invalid unload request");
+ 		req->status = JackFailure;
+ 	}
+ }
+diff --git a/jackd/engine.c b/jackd/engine.c
+--- a/jackd/engine.c
++++ b/jackd/engine.c
+@@ -510,7 +510,7 @@ jack_driver_buffer_size (jack_engine_t *
+ 	jack_event_t event;
+ 	JSList *node;
+ 
+-	VERBOSE (engine, "new buffer size %" PRIu32 "\n", nframes);
++	VERBOSE (engine, "new buffer size %" PRIu32, nframes);
+ 
+ 	engine->control->buffer_size = nframes;
+ 	if (engine->driver)
+@@ -709,7 +709,7 @@ jack_process_external(jack_engine_t *eng
+ 			 " waiting on %d for %" PRIu64
+ 			 " usecs, status = %d sig = %" PRIu64
+ 			 " awa = %" PRIu64 " fin = %" PRIu64
+-			 " dur=%" PRIu64 "\n",
++			 " dur=%" PRIu64,
+ 			 now,
+ 			 client->subgraph_wait_fd,
+ 			 now - then,
+@@ -808,7 +808,7 @@ jack_calc_cpu_load(jack_engine_t *engine
+ 	engine->rolling_client_usecs[engine->rolling_client_usecs_index++] = 
+ 		cycle_end - engine->control->current_time.usecs;
+ 
+-	//printf ("cycle_end - engine->control->current_time.usecs %ld\n",
++	//jack_info ("cycle_end - engine->control->current_time.usecs %ld",
+ 	//	(long) (cycle_end - engine->control->current_time.usecs));
+ 
+ 	if (engine->rolling_client_usecs_index >= JACK_ENGINE_ROLLING_COUNT) {
+@@ -847,7 +847,7 @@ jack_calc_cpu_load(jack_engine_t *engine
+ 			+ (engine->control->cpu_load * 0.5f);
+ 
+ 		VERBOSE (engine, "load = %.4f max usecs: %.3f, "
+-			 "spare = %.3f\n", engine->control->cpu_load,
++			 "spare = %.3f", engine->control->cpu_load,
+ 			 max_usecs, engine->spare_usecs);
+ 	}
+ 
+@@ -880,7 +880,7 @@ jack_engine_post_process (jack_engine_t 
+ 			    ctl->timed_out++) {
+ 				VERBOSE(engine, "client %s error: awake_at = %"
+ 					 PRIu64
+-					 " state = %d timed_out = %d\n",
++					 " state = %d timed_out = %d",
+ 					 ctl->name,
+ 					 ctl->awake_at,
+ 					 ctl->state,
+@@ -1077,14 +1077,14 @@ static int check_capabilities (jack_engi
+ 
+ 	if (caps == NULL) {
+ 		VERBOSE (engine, "check: could not allocate capability"
+-			 " working storage\n");
++			 " working storage");
+ 		return 0;
+ 	}
+ 	pid = getpid ();
+ 	cap_clear (caps);
+ 	if (capgetp (pid, caps)) {
+ 		VERBOSE (engine, "check: could not get capabilities "
+-			 "for process %d\n", pid);
++			 "for process %d", pid);
+ 		return 0;
+ 	}
+ 	/* check that we are able to give capabilites to other processes */
+@@ -1123,13 +1123,13 @@ static int give_capabilities (jack_engin
+ 
+ 	if (caps == NULL) {
+ 		VERBOSE (engine, "give: could not allocate capability"
+-			 " working storage\n");
++			 " working storage");
+ 		return -1;
+ 	}
+ 	cap_clear(caps);
+ 	if (capgetp (pid, caps)) {
+ 		VERBOSE (engine, "give: could not get current "
+-			 "capabilities for process %d\n", pid);
++			 "capabilities for process %d", pid);
+ 		cap_clear(caps);
+ 	}
+ 	cap_set_flag(caps, CAP_EFFECTIVE, caps_size, cap_list , CAP_SET);
+@@ -1156,11 +1156,11 @@ jack_set_client_capabilities (jack_engin
+ 
+ 	if ((ret = give_capabilities (engine, cap_pid)) != 0) {
+ 		jack_error ("could not give capabilities to "
+-			    "process %d\n",
++			    "process %d",
+ 			    cap_pid);
+ 	} else {
+ 		VERBOSE (engine, "gave capabilities to"
+-			 " process %d\n",
++			 " process %d",
+ 			 cap_pid);
+ 	}
+ 
+@@ -1667,7 +1667,7 @@ jack_engine_new (int realtime, int rtpri
+ 			&jack_builtin_port_types[i],
+ 			sizeof (jack_port_type_info_t));
+ 
+-		VERBOSE (engine, "registered builtin port type %s\n",
++		VERBOSE (engine, "registered builtin port type %s",
+ 			 engine->control->port_types[i].type_name);
+ 
+ 		/* the port type id is index into port_types array */
+@@ -1725,7 +1725,7 @@ jack_engine_new (int realtime, int rtpri
+ 	jack_set_clock_source (clock_source);
+ 	engine->control->clock_source = clock_source;
+ 
+-	VERBOSE (engine, "clock source = %s\n", jack_clock_source_name (clock_source));
++	VERBOSE (engine, "clock source = %s", jack_clock_source_name (clock_source));
+ 
+ 	engine->control->frame_timer.frames = frame_time_offset;
+ 	engine->control->frame_timer.reset_pending = 0;
+@@ -1759,20 +1759,20 @@ jack_engine_new (int realtime, int rtpri
+ #ifdef USE_CAPABILITIES
+ 	if (uid == 0 || euid == 0) {
+ 		VERBOSE (engine, "running with uid=%d and euid=%d, "
+-			 "will not try to use capabilites\n",
++			 "will not try to use capabilites",
+ 			 uid, euid);
+ 	} else {
+ 		/* only try to use capabilities if not running as root */
+ 		engine->control->has_capabilities = check_capabilities (engine);
+ 		if (engine->control->has_capabilities == 0) {
+ 			VERBOSE (engine, "required capabilities not "
+-				 "available\n");
++				 "available");
+ 		}
+ 		if (engine->verbose) {
+ 			size_t size;
+ 			cap_t cap = cap_init();
+ 			capgetp(0, cap);
+-			VERBOSE (engine, "capabilities: %s\n",
++			VERBOSE (engine, "capabilities: %s",
+ 				 cap_to_text(cap, &size));
+ 		}
+ 	}
+@@ -1847,7 +1847,7 @@ jack_engine_freewheel (void *arg)
+ {
+ 	jack_engine_t* engine = (jack_engine_t *) arg;
+ 
+-	VERBOSE (engine, "freewheel thread starting ...\n");
++	VERBOSE (engine, "freewheel thread starting ...");
+ 
+ 	/* we should not be running SCHED_FIFO, so we don't 
+ 	   have to do anything about scheduling.
+@@ -1867,7 +1867,7 @@ jack_engine_freewheel (void *arg)
+ 		jack_unlock_graph (engine);
+ 	}
+ 
+-	VERBOSE (engine, "freewheel came to an end, naturally\n");
++	VERBOSE (engine, "freewheel came to an end, naturally");
+ 	return 0;
+ }
+ 
+@@ -1924,7 +1924,7 @@ jack_stop_freewheeling (jack_engine_t* e
+ 	}
+ 
+ 	if (!engine->freewheeling) {
+-		VERBOSE (engine, "stop freewheel when not freewheeling\n");
++		VERBOSE (engine, "stop freewheel when not freewheeling");
+ 		return 0;
+ 	}
+ 
+@@ -1933,9 +1933,9 @@ jack_stop_freewheeling (jack_engine_t* e
+ 	*/
+ 
+ 	engine->freewheeling = 0;
+-	VERBOSE (engine, "freewheeling stopped, waiting for thread\n");
++	VERBOSE (engine, "freewheeling stopped, waiting for thread");
+ 	pthread_join (engine->freewheel_thread, &ftstatus);
+-	VERBOSE (engine, "freewheel thread has returned\n");
++	VERBOSE (engine, "freewheel thread has returned");
+ 
+ 	/* tell everyone we've stopped */
+ 
+@@ -2023,7 +2023,7 @@ jack_run_one_cycle (jack_engine_t *engin
+ 			if (client->control->type == ClientExternal) {
+ 				if (kill (client->control->pid, 0)) {
+ 					VERBOSE(engine,
+-						"client %s has died/exited\n",
++						"client %s has died/exited",
+ 						client->control->name);
+ 					client->error++;
+ 				}
+@@ -2109,7 +2109,7 @@ jack_run_cycle (jack_engine_t *engine, j
+ 		if (nframes != b_size) { 
+ 			VERBOSE (engine, 
+ 				"late driver wakeup: nframes to process = %"
+-				PRIu32 ".\n", nframes);
++				PRIu32 ".", nframes);
+ 		}
+ 	}
+ 
+@@ -2132,7 +2132,7 @@ jack_engine_delete (jack_engine_t *engin
+ 	if (engine == NULL)
+ 		return;
+ 
+-	VERBOSE (engine, "starting server engine shutdown\n");
++	VERBOSE (engine, "starting server engine shutdown");
+ 
+ 	engine->control->engine_ok = 0;	/* tell clients we're going away */
+ 
+@@ -2149,23 +2149,23 @@ jack_engine_delete (jack_engine_t *engin
+ 	if (engine->driver) {
+ 		jack_driver_t* driver = engine->driver;
+ 
+-		VERBOSE (engine, "stopping driver\n");
++		VERBOSE (engine, "stopping driver");
+ 		driver->stop (driver);
+-		// VERBOSE (engine, "detaching driver\n");
++		// VERBOSE (engine, "detaching driver");
+ 		// driver->detach (driver, engine);
+-		VERBOSE (engine, "unloading driver\n");
++		VERBOSE (engine, "unloading driver");
+ 		jack_driver_unload (driver);
+ 		engine->driver = NULL;
+ 	}
+ 
+-	VERBOSE (engine, "freeing shared port segments\n");
++	VERBOSE (engine, "freeing shared port segments");
+ 	for (i = 0; i < engine->control->n_port_types; ++i) {
+ 		jack_release_shm (&engine->port_segment[i]);
+ 		jack_destroy_shm (&engine->port_segment[i]);
+ 	}
+ 
+ 	/* stop the other engine threads */
+-	VERBOSE (engine, "stopping server thread\n");
++	VERBOSE (engine, "stopping server thread");
+ 
+ #if JACK_USE_MACH_THREADS 
+ 	// MacOSX pthread_cancel still not implemented correctly in Darwin
+@@ -2183,26 +2183,25 @@ jack_engine_delete (jack_engine_t *engin
+ 	 * drivers already contain a similar mechanism.
+ 	 */	
+ 	if (engine->control->real_time && engine->watchdog_thread) {
+-		VERBOSE (engine, "stopping watchdog thread\n");
++		VERBOSE (engine, "stopping watchdog thread");
+ 		pthread_cancel (engine->watchdog_thread);
+ 		pthread_join (engine->watchdog_thread, NULL);
+ 	}
+ #endif
+ 
+-	VERBOSE (engine, "last xrun delay: %.3f usecs\n",
++	VERBOSE (engine, "last xrun delay: %.3f usecs",
+ 		engine->control->xrun_delayed_usecs);
+-	VERBOSE (engine, "max delay reported by backend: %.3f usecs\n",
++	VERBOSE (engine, "max delay reported by backend: %.3f usecs",
+ 		engine->control->max_delayed_usecs);
+ 
+ 	/* free engine control shm segment */
+ 	engine->control = NULL;
+-	VERBOSE (engine, "freeing engine shared memory\n");
++	VERBOSE (engine, "freeing engine shared memory");
+ 	jack_release_shm (&engine->control_shm);
+ 	jack_destroy_shm (&engine->control_shm);
+ 
+-	VERBOSE (engine, "max usecs: %.3f, ", engine->max_usecs);
++	VERBOSE (engine, "max usecs: %.3f, engine deleted", engine->max_usecs);
+ 
+-	VERBOSE (engine, "engine deleted\n");
+ 	free (engine);
+ 
+ 	jack_messagebuffer_exit();
+@@ -2398,7 +2397,7 @@ jack_rechain_graph (jack_engine_t *engin
+ 
+ 	subgraph_client = 0;
+ 
+-	VERBOSE(engine, "++ jack_rechain_graph():\n");
++	VERBOSE(engine, "++ jack_rechain_graph():");
+ 
+ 	event.type = GraphReordered;
+ 
+@@ -2444,7 +2443,7 @@ jack_rechain_graph (jack_engine_t *engin
+ 						jack_get_fifo_fd (engine, n);
+ 					VERBOSE (engine, "client %s: wait_fd="
+ 						 "%d, execution_order="
+-						 "%lu.\n", 
++						 "%lu.", 
+ 						 subgraph_client->
+ 						 control->name,
+ 						 subgraph_client->
+@@ -2454,7 +2453,7 @@ jack_rechain_graph (jack_engine_t *engin
+ 
+ 				VERBOSE (engine, "client %s: internal "
+ 					 "client, execution_order="
+-					 "%lu.\n", 
++					 "%lu.", 
+ 					 client->control->name, n);
+ 
+ 				/* this does the right thing for
+@@ -2480,7 +2479,7 @@ jack_rechain_graph (jack_engine_t *engin
+ 						jack_get_fifo_fd (engine, n);
+ 					VERBOSE (engine, "client %s: "
+ 						 "start_fd=%d, execution"
+-						 "_order=%lu.\n",
++						 "_order=%lu.",
+ 						 subgraph_client->
+ 						 control->name,
+ 						 subgraph_client->
+@@ -2498,7 +2497,7 @@ jack_rechain_graph (jack_engine_t *engin
+ 					VERBOSE (engine, "client %s: in"
+ 						 " subgraph after %s, "
+ 						 "execution_order="
+-						 "%lu.\n",
++						 "%lu.",
+ 						 client->control->name,
+ 						 subgraph_client->
+ 						 control->name, n);
+@@ -2530,12 +2529,12 @@ jack_rechain_graph (jack_engine_t *engin
+ 		subgraph_client->subgraph_wait_fd =
+ 			jack_get_fifo_fd (engine, n);
+ 		VERBOSE (engine, "client %s: wait_fd=%d, "
+-			 "execution_order=%lu (last client).\n", 
++			 "execution_order=%lu (last client).", 
+ 			 subgraph_client->control->name,
+ 			 subgraph_client->subgraph_wait_fd, n);
+ 	}
+ 
+-	VERBOSE (engine, "-- jack_rechain_graph()\n");
++	VERBOSE (engine, "-- jack_rechain_graph()");
+ 
+ 	return err;
+ }
+@@ -2573,7 +2572,7 @@ jack_get_port_total_latency (jack_engine
+ 	}
+ 
+ #ifdef DEBUG_TOTAL_LATENCY_COMPUTATION
+-	fprintf (stderr, "\n%sFor port %s (%s)\n", prefix, port->shared->name, (toward_port ? "toward" : "away"));
++	jack_info ("%sFor port %s (%s)", prefix, port->shared->name, (toward_port ? "toward" : "away"));
+ #endif
+ 	
+ 	for (node = port->connections; node; node = jack_slist_next (node)) {
+@@ -2590,7 +2589,7 @@ jack_get_port_total_latency (jack_engine
+ 		     (connection->destination->shared == port->shared))) {
+ 
+ #ifdef DEBUG_TOTAL_LATENCY_COMPUTATION
+-			fprintf (stderr, "%s\tskip connection %s->%s\n",
++			jack_info ("%s\tskip connection %s->%s",
+ 				 prefix,
+ 				 connection->source->shared->name,
+ 				 connection->destination->shared->name);
+@@ -2600,7 +2599,7 @@ jack_get_port_total_latency (jack_engine
+ 		}
+ 
+ #ifdef DEBUG_TOTAL_LATENCY_COMPUTATION
+-		fprintf (stderr, "%s\tconnection %s->%s ... ", 
++		jack_info ("%s\tconnection %s->%s ... ", 
+ 			 prefix,
+ 			 connection->source->shared->name,
+ 			 connection->destination->shared->name);
+@@ -2647,7 +2646,7 @@ jack_get_port_total_latency (jack_engine
+ 	}
+ 
+ #ifdef DEBUG_TOTAL_LATENCY_COMPUTATION
+-	fprintf (stderr, "%s\treturn %lu + %lu = %lu\n", prefix, latency, max_latency, latency + max_latency);
++	jack_info ("%s\treturn %lu + %lu = %lu", prefix, latency, max_latency, latency + max_latency);
+ #endif	
+ 
+ 	return latency + max_latency;
+@@ -2782,7 +2781,7 @@ jack_check_acyclic (jack_engine_t *engin
+ 	int stuck;
+ 	int unsortedclients = 0;
+ 
+-	VERBOSE (engine, "checking for graph become acyclic\n");
++	VERBOSE (engine, "checking for graph become acyclic");
+ 
+ 	for (srcnode = engine->clients; srcnode;
+ 	     srcnode = jack_slist_next (srcnode)) {
+@@ -2823,10 +2822,10 @@ jack_check_acyclic (jack_engine_t *engin
+ 	
+ 	if (stuck) {
+ 
+-		VERBOSE (engine, "graph is still cyclic\n" );
++		VERBOSE (engine, "graph is still cyclic" );
+ 	} else {
+ 
+-		VERBOSE (engine, "graph has become acyclic\n");
++		VERBOSE (engine, "graph has become acyclic");
+ 
+ 		/* turn feedback connections around in sortfeeds */
+ 		for (srcnode = engine->clients; srcnode;
+@@ -2852,7 +2851,7 @@ jack_check_acyclic (jack_engine_t *engin
+ 				
+ 						VERBOSE (engine,
+ 						"reversing connection from "
+-						"%s to %s\n",
++						"%s to %s",
+ 						conn->srcclient->control->name,
+ 						conn->dstclient->control->name);
+ 						conn->dir = 1;
+@@ -2874,7 +2873,7 @@ jack_check_acyclic (jack_engine_t *engin
+ }
+ 
+ /**
+- * Dumps current engine configuration to stderr.
++ * Dumps current engine configuration.
+  */
+ void jack_dump_configuration(jack_engine_t *engine, int take_lock)
+ {
+@@ -2885,7 +2884,7 @@ void jack_dump_configuration(jack_engine
+ 	jack_connection_internal_t* connection;
+ 	int n, m, o;
+ 	
+-	fprintf(stderr, "engine.c: <-- dump begins -->\n");
++	jack_info ("engine.c: <-- dump begins -->");
+ 
+ 	if (take_lock) {
+ 		jack_lock_graph (engine);
+@@ -2896,8 +2895,8 @@ void jack_dump_configuration(jack_engine
+ 	        client = (jack_client_internal_t *) clientnode->data;
+ 		ctl = client->control;
+ 
+-		fprintf (stderr, "client #%d: %s (type: %d, process? %s,"
+-			 " start=%d wait=%d\n",
++		jack_info ("client #%d: %s (type: %d, process? %s,"
++			 " start=%d wait=%d",
+ 			 ++n,
+ 			 ctl->name,
+ 			 ctl->type,
+@@ -2909,7 +2908,7 @@ void jack_dump_configuration(jack_engine
+ 		    portnode = jack_slist_next (portnode)) {
+ 		        port = (jack_port_internal_t *) portnode->data;
+ 
+-			fprintf(stderr, "\t port #%d: %s\n", ++m,
++			jack_info("\t port #%d: %s", ++m,
+ 				port->shared->name);
+ 
+ 			for(o = 0, connectionnode = port->connections; 
+@@ -2919,7 +2918,7 @@ void jack_dump_configuration(jack_engine
+ 			        connection = (jack_connection_internal_t *)
+ 					connectionnode->data;
+ 	
+-				fprintf(stderr, "\t\t connection #%d: %s %s\n",
++				jack_info("\t\t connection #%d: %s %s",
+ 					++o,
+ 					(port->shared->flags
+ 					 & JackPortIsInput)? "<-": "->",
+@@ -2935,7 +2934,7 @@ void jack_dump_configuration(jack_engine
+ 	}
+ 
+ 	
+-	fprintf(stderr, "engine.c: <-- dump ends -->\n");
++	jack_info("engine.c: <-- dump ends -->");
+ }
+ 
+ static int 
+@@ -3049,7 +3048,7 @@ jack_port_do_connect (jack_engine_t *eng
+ 			   feedback */
+ 			
+ 			VERBOSE (engine,
+-				 "connect %s and %s (output)\n",
++				 "connect %s and %s (output)",
+ 				 srcport->shared->name,
+ 				 dstport->shared->name);
+ 
+@@ -3072,7 +3071,7 @@ jack_port_do_connect (jack_engine_t *eng
+ 				   this is a feedback connection */
+ 				
+ 				VERBOSE (engine,
+-					 "connect %s and %s (feedback)\n",
++					 "connect %s and %s (feedback)",
+ 					 srcport->shared->name,
+ 					 dstport->shared->name);
+ 				 
+@@ -3082,7 +3081,7 @@ jack_port_do_connect (jack_engine_t *eng
+ 				connection->dir = -1;
+ 				engine->feedbackcount++;
+ 				VERBOSE (engine,
+-					 "feedback count up to %d\n",
++					 "feedback count up to %d",
+ 					 engine->feedbackcount);
+ 
+ 			} else {
+@@ -3090,7 +3089,7 @@ jack_port_do_connect (jack_engine_t *eng
+ 				/* this is not a feedback connection */
+ 
+ 				VERBOSE (engine,
+-					 "connect %s and %s (forward)\n",
++					 "connect %s and %s (forward)",
+ 					 srcport->shared->name,
+ 					 dstport->shared->name);
+ 
+@@ -3105,7 +3104,7 @@ jack_port_do_connect (jack_engine_t *eng
+ 			/* this is a connection to self */
+ 
+ 			VERBOSE (engine,
+-				 "connect %s and %s (self)\n",
++				 "connect %s and %s (self)",
+ 				 srcport->shared->name,
+ 				 dstport->shared->name);
+ 			
+@@ -3160,7 +3159,7 @@ jack_port_disconnect_internal (jack_engi
+ 		if (connect->source == srcport &&
+ 		    connect->destination == dstport) {
+ 
+-			VERBOSE (engine, "DIS-connect %s and %s\n",
++			VERBOSE (engine, "DIS-connect %s and %s",
+ 				 srcport->shared->name,
+ 				 dstport->shared->name);
+ 			
+@@ -3225,7 +3224,7 @@ jack_port_disconnect_internal (jack_engi
+ 						(dst->sortfeeds, src);
+ 					engine->feedbackcount--;
+ 					VERBOSE (engine,
+-						 "feedback count down to %d\n",
++						 "feedback count down to %d",
+ 						 engine->feedbackcount);
+ 					
+ 				}
+@@ -3256,7 +3255,7 @@ jack_port_do_disconnect_all (jack_engine
+ 		return -1;
+ 	}
+ 
+-	VERBOSE (engine, "clear connections for %s\n",
++	VERBOSE (engine, "clear connections for %s",
+ 		 engine->internal_ports[port_id].shared->name);
+ 
+ 	jack_lock_graph (engine);
+@@ -3588,7 +3587,7 @@ next:
+ 	jack_port_registration_notify (engine, port_id, TRUE);
+ 	jack_unlock_graph (engine);
+ 
+-	VERBOSE (engine, "registered port %s, offset = %u\n",
++	VERBOSE (engine, "registered port %s, offset = %u",
+ 		 shared->name, (unsigned int)shared->offset);
+ 
+ 	req->x.port_info.port_id = port_id;
+diff --git a/jackd/jackd.c b/jackd/jackd.c
+--- a/jackd/jackd.c
++++ b/jackd/jackd.c
+@@ -148,14 +148,14 @@ jack_main (jack_driver_desc_t * driver_d
+ 				       temporary, verbose, client_timeout,
+ 				       port_max, getpid(), frame_time_offset, 
+ 				       nozombies, drivers)) == 0) {
+-		fprintf (stderr, "cannot create engine\n");
++		jack_error ("cannot create engine");
+ 		return -1;
+ 	}
+ 
+-	fprintf (stderr, "loading driver ..\n");
++	jack_info ("loading driver ..");
+ 	
+ 	if (jack_engine_load_driver (engine, driver_desc, driver_params)) {
+-		fprintf (stderr, "cannot load driver module %s\n",
++		jack_error ("cannot load driver module %s",
+ 			 driver_desc->name);
+ 		goto error;
+ 	}
+@@ -181,7 +181,7 @@ jack_main (jack_driver_desc_t * driver_d
+ 	}
+ 	
+ 	if (verbose) {
+-		fprintf (stderr, "%d waiting for signals\n", getpid());
++		jack_info ("%d waiting for signals", getpid());
+ 	}
+ 
+ 	waiting = TRUE;
+@@ -189,7 +189,7 @@ jack_main (jack_driver_desc_t * driver_d
+ 	while (waiting) {
+ 		sigwait (&signals, &sig);
+ 
+-		fprintf (stderr, "jack main caught signal %d\n", sig);
++		jack_info ("jack main caught signal %d", sig);
+ 		
+ 		switch (sig) {
+ 		case SIGUSR1:
+@@ -241,7 +241,7 @@ jack_drivers_get_descriptor (JSList * dr
+ 	sprintf (filename, "%s/%s", driver_dir, sofile);
+ 
+ 	if (verbose) {
+-		fprintf (stderr, "getting driver descriptor from %s\n", filename);
++		jack_info ("getting driver descriptor from %s", filename);
+ 	}
+ 
+ 	if ((dlhandle = dlopen (filename, RTLD_NOW|RTLD_GLOBAL)) == NULL) {
+@@ -254,7 +254,7 @@ jack_drivers_get_descriptor (JSList * dr
+ 		dlsym (dlhandle, "driver_get_descriptor");
+ 
+ 	if ((dlerr = dlerror ()) != NULL) {
+-		fprintf(stderr, "%s\n", dlerr);
++		jack_error("%s", dlerr);
+ 		dlclose (dlhandle);
+ 		free (filename);
+ 		return NULL;
+@@ -479,24 +479,23 @@ maybe_use_capabilities ()
+   	        char c = 1;
+ 
+ 	        if (write (PIPE_WRITE_FD, &c, 1) != 1) {
+-		        fprintf (stderr, "cannot write to jackstart sync "
+-				 "pipe %d (%s)\n", PIPE_WRITE_FD,
++		        jack_error ("cannot write to jackstart sync "
++				 "pipe %d (%s)", PIPE_WRITE_FD,
+ 				 strerror (errno));
+ 	        }
+ 
+ 		if (close(PIPE_WRITE_FD) != 0) {
+-			fprintf(stderr,
+-				"jackd: error on startup pipe close: %s\n",
+-				strerror (errno));
++			jack_error("jackd: error on startup pipe close: %s",
++				   strerror (errno));
+ 		} else {
+ 			/* wait for jackstart process to set our capabilities */
+ 			if (wait (&status) == -1) {
+-				fprintf (stderr, "jackd: wait for startup "
+-					 "process exit failed\n");
++				jack_error ("jackd: wait for startup "
++					    "process exit failed");
+ 			}
+ 			if (!WIFEXITED (status) || WEXITSTATUS (status)) {
+-				fprintf(stderr, "jackd: jackstart did not "
+-					"exit cleanly\n");
++				jack_error ("jackd: jackstart did not "
++					    "exit cleanly");
+ 				exit (1);
+ 			}
+ 		}
+@@ -627,8 +626,8 @@ main (int argc, char *argv[])
+ 			break;
+ 
+ 		default:
+-			fprintf (stderr, "Unknown option character %c\n",
+-				 optopt);
++			jack_error ("Unknown option character %c",
++				    optopt);
+ 			/*fallthru*/
+ 		case 'h':
+ 			usage (stdout);
+diff --git a/jackd/transengine.c b/jackd/transengine.c
+--- a/jackd/transengine.c
++++ b/jackd/transengine.c
+@@ -48,10 +48,10 @@ jack_sync_poll_new (jack_engine_t *engin
+ 	// JOQ: I don't like doing this here...
+ 	if (engine->control->transport_state == JackTransportRolling) {
+ 		engine->control->transport_state = JackTransportStarting;
+-		VERBOSE (engine, "force transport state to Starting\n");
++		VERBOSE (engine, "force transport state to Starting");
+ 	}
+ 
+-	VERBOSE (engine, "polling sync client %" PRIu32 "\n",
++	VERBOSE (engine, "polling sync client %" PRIu32,
+ 		 client->control->id);
+ }
+ 
+@@ -67,7 +67,7 @@ jack_sync_poll_deactivate (jack_engine_t
+ 		client->control->sync_new = 0;
+ 		engine->control->sync_remain--;
+ 		VERBOSE (engine, "sync poll interrupted for client %"
+-			 PRIu32 "\n", client->control->id);
++			 PRIu32, client->control->id);
+ 	}
+ 	client->control->active_slowsync = 0;
+ 	engine->control->sync_clients--;
+@@ -97,7 +97,7 @@ jack_sync_poll_stop (jack_engine_t *engi
+ 	assert (poll_count == engine->control->sync_remain);
+ 	VERBOSE (engine,
+ 		 "sync poll halted with %" PRIu32
+-		 " clients and %8.6f secs remaining\n",
++		 " clients and %8.6f secs remaining",
+ 		 engine->control->sync_remain,
+ 		 (double) (engine->control->sync_time_left / 1000000.0));
+ 	engine->control->sync_remain = 0;
+@@ -127,7 +127,7 @@ jack_sync_poll_start (jack_engine_t *eng
+ 	engine->control->sync_remain = sync_count;
+ 	engine->control->sync_time_left = engine->control->sync_timeout;
+ 	VERBOSE (engine, "transport Starting, sync poll of %" PRIu32
+-		 " clients for %8.6f secs\n", engine->control->sync_remain,
++		 " clients for %8.6f secs", engine->control->sync_remain,
+ 		 (double) (engine->control->sync_time_left / 1000000.0));
+ }
+ 
+@@ -147,7 +147,7 @@ jack_sync_timeout (jack_engine_t *engine
+ 	}
+ 
+ 	/* timed out */
+-	VERBOSE (engine, "transport sync timeout\n");
++	VERBOSE (engine, "transport sync timeout");
+ 	ectl->sync_time_left = 0;
+ 	return TRUE;
+ }
+@@ -182,7 +182,7 @@ jack_timebase_reset (jack_engine_t *engi
+ 		client->control->timebase_new = 0;
+ 		engine->timebase_client = NULL;
+ 		ectl->pending_time.valid = 0;
+-		VERBOSE (engine, "%s resigned as timebase master\n",
++		VERBOSE (engine, "%s resigned as timebase master",
+ 			 client->control->name);
+ 		ret = 0;
+ 	}  else
+@@ -206,7 +206,7 @@ jack_timebase_set (jack_engine_t *engine
+ 	client = jack_client_internal_by_id (engine, client_id);
+ 
+ 	if (client == NULL) {
+- 		VERBOSE (engine, " %" PRIu32 " no longer exists\n", client_id);
++ 		VERBOSE (engine, " %" PRIu32 " no longer exists", client_id);
+ 		jack_unlock_graph (engine);
+ 		return EINVAL;
+ 	}
+@@ -215,13 +215,13 @@ jack_timebase_set (jack_engine_t *engine
+ 
+ 		/* see if timebase master is someone else */
+ 		if (client != engine->timebase_client) {
+-			VERBOSE (engine, "conditional timebase for %s failed\n"
+-				 " %s is already the master\n",
+-				 client->control->name,
++			VERBOSE (engine, "conditional timebase for %s failed",
++				 client->control->name);
++			VERBOSE (engine, " %s is already the master",
+ 				 engine->timebase_client->control->name);
+ 			ret = EBUSY;
+ 		} else
+-			VERBOSE (engine, " %s was already timebase master:\n",
++			VERBOSE (engine, " %s was already timebase master:",
+ 				 client->control->name);
+ 
+ 	} else {
+@@ -234,7 +234,7 @@ jack_timebase_set (jack_engine_t *engine
+ 		client->control->is_timebase = 1;
+ 		if (client->control->active)
+ 			client->control->timebase_new = 1;
+-		VERBOSE (engine, "new timebase master: %s\n",
++		VERBOSE (engine, "new timebase master: %s",
+ 			 client->control->name);
+ 	}
+ 
+@@ -297,7 +297,7 @@ jack_transport_client_exit (jack_engine_
+ 			engine->timebase_client->control->is_timebase = 0;
+ 			engine->timebase_client->control->timebase_new = 0;
+ 			engine->timebase_client = NULL;
+-			VERBOSE (engine, "timebase master exit\n");
++			VERBOSE (engine, "timebase master exit");
+ 		}
+ 		engine->control->current_time.valid = 0;
+ 		engine->control->pending_time.valid = 0;
+@@ -410,7 +410,7 @@ jack_transport_cycle_end (jack_engine_t 
+ 		    (jack_sync_timeout(engine))) {
+ 			ectl->transport_state = JackTransportRolling;
+ 			VERBOSE (engine, "transport Rolling, %8.6f sec"
+-				 " left for poll\n",
++				 " left for poll",
+ 				 (double) (ectl->sync_time_left / 1000000.0));
+ 		}
+ 	}
+@@ -419,7 +419,7 @@ jack_transport_cycle_end (jack_engine_t 
+ 	cmd = ectl->transport_cmd;
+ 	if (cmd != ectl->previous_cmd) {
+ 		ectl->previous_cmd = cmd;
+-		VERBOSE (engine, "transport command: %s\n",
++		VERBOSE (engine, "transport command: %s",
+ 		       (cmd == TransportCommandStart? "START": "STOP"));
+ 	} else
+ 		cmd = TransportCommandNone;
+@@ -435,7 +435,7 @@ jack_transport_cycle_end (jack_engine_t 
+ 				jack_sync_poll_start(engine);
+ 			} else {
+ 				ectl->transport_state = JackTransportRolling;
+-				VERBOSE (engine, "transport Rolling\n");
++				VERBOSE (engine, "transport Rolling");
+ 			}
+ 		}
+ 		break;
+@@ -443,7 +443,7 @@ jack_transport_cycle_end (jack_engine_t 
+ 	case JackTransportStarting:
+ 		if (cmd == TransportCommandStop) {
+ 			ectl->transport_state = JackTransportStopped;
+-			VERBOSE (engine, "transport Stopped\n");
++			VERBOSE (engine, "transport Stopped");
+ 			if (ectl->sync_remain)
+ 				jack_sync_poll_stop(engine);
+ 		} else if (ectl->new_pos) {
+@@ -452,7 +452,7 @@ jack_transport_cycle_end (jack_engine_t 
+ 				jack_sync_poll_start(engine);
+ 			} else {
+ 				ectl->transport_state = JackTransportRolling;
+-				VERBOSE (engine, "transport Rolling\n");
++				VERBOSE (engine, "transport Rolling");
+ 			}
+ 		}
+ 		break;
+@@ -460,7 +460,7 @@ jack_transport_cycle_end (jack_engine_t 
+ 	case JackTransportRolling:
+ 		if (cmd == TransportCommandStop) {
+ 			ectl->transport_state = JackTransportStopped;
+-			VERBOSE (engine, "transport Stopped\n");
++			VERBOSE (engine, "transport Stopped");
+ 			if (ectl->sync_remain)
+ 				jack_sync_poll_stop(engine);
+ 		} else if (ectl->new_pos) {
+@@ -490,7 +490,7 @@ jack_transport_cycle_end (jack_engine_t 
+ 		jack_transport_copy_position(&ectl->request_time,
+ 					     &ectl->pending_time);
+ 		VERBOSE (engine, "new transport position: %" PRIu32
+-			 ", id=0x%" PRIx64 "\n", ectl->pending_time.frame,
++			 ", id=0x%" PRIx64, ectl->pending_time.frame,
+ 			 ectl->pending_time.unique_1);
+ 		ectl->prev_request = ectl->pending_time.unique_1;
+ 		ectl->pending_pos = 1;
+@@ -513,7 +513,7 @@ jack_transport_set_sync_timeout (jack_en
+ 				 jack_time_t usecs)
+ {
+ 	engine->control->sync_timeout = usecs;
+-	VERBOSE (engine, "new sync timeout: %8.6f secs\n",
++	VERBOSE (engine, "new sync timeout: %8.6f secs",
+ 		 (double) (usecs / 1000000.0));
+ 	return 0;
+ }
+diff --git a/libjack/client.c b/libjack/client.c
+--- a/libjack/client.c
++++ b/libjack/client.c
+@@ -86,12 +86,11 @@ init_cpu ()
+ {
+ 	cpu_type = ((have_3dnow() << 8) | have_sse());
+ 	if (ARCH_X86_HAVE_3DNOW(cpu_type))
+-		fprintf(stderr, "Enhanced3DNow! detected\n");
++		jack_info("Enhanced3DNow! detected");
+ 	if (ARCH_X86_HAVE_SSE2(cpu_type))
+-		fprintf(stderr, "SSE2 detected\n");
++		jack_info("SSE2 detected");
+ 	if ((!ARCH_X86_HAVE_3DNOW(cpu_type)) && (!ARCH_X86_HAVE_SSE2(cpu_type)))
+-		fprintf(stderr,
+-			"No supported SIMD instruction sets detected\n");
++		jack_info("No supported SIMD instruction sets detected");
+ 	jack_port_set_funcs();
+ }
+ 
+@@ -157,6 +156,14 @@ default_jack_error_callback (const char 
+ default_jack_error_callback (const char *desc)
+ {
+ 	fprintf(stderr, "%s\n", desc);
++	fflush(stderr);
++}
++
++void 
++default_jack_info_callback (const char *desc)
++{
++	fprintf(stdout, "%s\n", desc);
++	fflush(stdout);
+ }
+ 
+ void 
+@@ -165,6 +172,19 @@ silent_jack_error_callback (const char *
+ }
+ 
+ void (*jack_error_callback)(const char *desc) = &default_jack_error_callback;
++void (*jack_info_callback)(const char *desc) = &default_jack_info_callback;
++
++void 
++jack_info (const char *fmt, ...)
++{
++	va_list ap;
++	char buffer[300];
++
++	va_start (ap, fmt);
++	vsnprintf (buffer, sizeof(buffer), fmt, ap);
++	jack_info_callback (buffer);
++	va_end (ap);
++}
+ 
+ static int
+ oop_client_deliver_request (void *ptr, jack_request_t *req)
+@@ -487,7 +507,7 @@ server_connect (const char *server_name)
+ 	}
+ 
+ 	//JOQ: temporary debug message
+-	//fprintf (stderr, "DEBUG: connecting to `%s' server\n", server_name);
++	//jack_info ("DEBUG: connecting to `%s' server", server_name);
+ 
+ 	addr.sun_family = AF_UNIX;
+ 	snprintf (addr.sun_path, sizeof (addr.sun_path) - 1, "%s/jack_%d",
+@@ -2004,6 +2024,12 @@ jack_set_error_function (void (*func) (c
+ 	jack_error_callback = func;
+ }
+ 
++void
++jack_set_info_function (void (*func) (const char *))
++{
++	jack_info_callback = func;
++}
++
+ int 
+ jack_set_graph_order_callback (jack_client_t *client,
+ 			       JackGraphOrderCallback callback, void *arg)
+diff --git a/libjack/messagebuffer.c b/libjack/messagebuffer.c
+--- a/libjack/messagebuffer.c
++++ b/libjack/messagebuffer.c
+@@ -53,7 +53,7 @@ mb_flush()
+ {
+ 	/* called WITHOUT the mb_write_lock */
+ 	while (mb_outbuffer != mb_inbuffer) {
+-		fputs(mb_buffers[mb_outbuffer], stderr);
++		jack_info(mb_buffers[mb_outbuffer]);
+ 		mb_outbuffer = MB_NEXT(mb_outbuffer);
+ 	}
+ }
+@@ -110,10 +110,10 @@ jack_messagebuffer_exit ()
+ 	mb_flush();
+ 
+ 	if (mb_overruns)
+-		fprintf(stderr, "WARNING: %d message buffer overruns!\n",
++		jack_error("WARNING: %d message buffer overruns!",
+ 			mb_overruns);
+ 	else
+-		fprintf(stderr, "no message buffer overruns\n");
++		jack_info("no message buffer overruns");
+ 
+ 	pthread_mutex_destroy(&mb_write_lock);
+ 	pthread_cond_destroy(&mb_ready_cond);
+diff --git a/libjack/shm.c b/libjack/shm.c
+--- a/libjack/shm.c
++++ b/libjack/shm.c
+@@ -380,7 +380,7 @@ jack_register_server (const char *server
+ 
+ 	jack_set_server_prefix (server_name);
+ 
+-	fprintf (stderr, "JACK compiled with %s SHM support.\n", JACK_SHM_TYPE);
++	jack_info ("JACK compiled with %s SHM support.", JACK_SHM_TYPE);
+ 
+ 	if (jack_server_initialize_shm ())
+ 		return ENOMEM;
+diff --git a/libjack/simd.c b/libjack/simd.c
+--- a/libjack/simd.c
++++ b/libjack/simd.c
+@@ -298,7 +298,7 @@ x86_sse_add2f (float *dest, const float 
+ 
+ 	if (__builtin_expect(((long) src & 0xf) || ((long) dest & 0xf), 0))
+ 	{
+-		/*fprintf(stderr, "x86_sse_add2f(): non aligned pointers!\n");*/
++		/*jack_error("x86_sse_add2f(): non aligned pointers!");*/
+ 		si2 = 0;
+ 		goto sse_nonalign;
+ 	}
+diff --git a/libjack/transclient.c b/libjack/transclient.c
+--- a/libjack/transclient.c
++++ b/libjack/transclient.c
+@@ -247,7 +247,7 @@ jack_time_to_frames(const jack_client_t 
+ 
+ 	if (time.initialized) {
+ #if 0
+-		fprintf (stderr, "now = %Lu current wakeup = %Lu next = %Lu frames = %lu + %f => %lu\n", 
++		jack_info ("now = %Lu current wakeup = %Lu next = %Lu frames = %lu + %f => %lu", 
+ 			 now, time.current_wakeup, time.next_wakeup, time.frames,
+ 			 (double) (now - time.current_wakeup)/ 
+ 			 (time.next_wakeup - time.current_wakeup),
+diff --git a/libjack/unlock.c b/libjack/unlock.c
+--- a/libjack/unlock.c
++++ b/libjack/unlock.c
+@@ -65,7 +65,7 @@ cleanup_mlock ()
+ 	snprintf (path, sizeof(path), "/proc/%d/maps", getpid());
+ 
+ 	if ((map = fopen (path, "r")) == NULL) {
+-		fprintf (stderr, "can't open map file\n");
++		jack_error ("can't open map file");
+ 		return;
+ 	}
+ 
+@@ -117,7 +117,7 @@ cleanup_mlock ()
+ 		}
+ 		
+ 		if (unlock) {
+-			fprintf (stderr, "unlocking %s\n", path);
++			jack_info ("unlocking %s", path);
+ 			munlock ((char *) start, end - start);
+ 		}
+ 	}

Added: trunk/overlays/proaudio/media-sound/jack-audio-connection-kit/files/jackd-midi-alsa-munge-r1051.patch
===================================================================
--- trunk/overlays/proaudio/media-sound/jack-audio-connection-kit/files/jackd-midi-alsa-munge-r1051.patch	                        (rev 0)
+++ trunk/overlays/proaudio/media-sound/jack-audio-connection-kit/files/jackd-midi-alsa-munge-r1051.patch	2007-12-10 21:09:08 UTC (rev 993)
@@ -0,0 +1,204 @@
+Index: jack/engine.h
+===================================================================
+--- jack/engine.h	(revision 1051)
++++ jack/engine.h	(working copy)
+@@ -205,6 +205,5 @@
+ void	jack_port_registration_notify (jack_engine_t *, jack_port_id_t, int);
+ void	jack_port_release (jack_engine_t *engine, jack_port_internal_t *);
+ void	jack_sort_graph (jack_engine_t *engine);
+-void    jack_engine_munge_backend_port_names (jack_engine_t* engine);
+ 
+ #endif /* __jack_engine_h__ */
+Index: jack/port.h
+===================================================================
+--- jack/port.h	(revision 1051)
++++ jack/port.h	(working copy)
+@@ -53,6 +53,8 @@
+ #define JACK_SHM_MAX (MAX_INT32)
+ typedef int32_t jack_port_type_id_t;
+ 
++#define JACK_BACKEND_ALIAS "system"
++
+ /* Port type structure.  
+  *
+  *  (1) One for each port type is part of the engine's jack_control_t
+Index: jackd/engine.c
+===================================================================
+--- jackd/engine.c	(revision 1051)
++++ jackd/engine.c	(working copy)
+@@ -94,7 +94,7 @@
+ static int  jack_port_do_disconnect_all (jack_engine_t *engine,
+ 					 jack_port_id_t);
+ static int  jack_port_do_unregister (jack_engine_t *engine, jack_request_t *);
+-static int  jack_port_do_register (jack_engine_t *engine, jack_request_t *);
++static int  jack_port_do_register (jack_engine_t *engine, jack_request_t *, int);
+ static int  jack_do_get_port_connections (jack_engine_t *engine,
+ 					  jack_request_t *req, int reply_fd);
+ static int  jack_port_disconnect_internal (jack_engine_t *engine,
+@@ -950,44 +950,6 @@
+ }
+ #endif /* !JACK_USE_MACH_THREADS */
+ 
+-void
+-jack_engine_munge_backend_port_names (jack_engine_t* engine)
+-{
+-	int out_cnt = 1;
+-	int in_cnt = 1;
+-	int i;
+-	char* backend_client_name = (char*) engine->driver->internal_client->control->name;
+-	size_t len = strlen (backend_client_name);
+-
+-	for (i = 0; i < engine->port_max; i++) {
+-		jack_port_shared_t* port = &engine->control->ports[i];
+-
+-		if (strncmp (port->name, backend_client_name, len) == 0) {
+-
+-			/* save the backend's own name */
+-
+-			char name[JACK_CLIENT_NAME_SIZE+JACK_PORT_NAME_SIZE];
+-			snprintf (name, sizeof (name), "%s", engine->control->ports[i].name);
+-
+-			/* replace input port names, and use backend's original as an alias */
+-
+-			if ((port->flags & (JackPortIsPhysical|JackPortIsInput)) == (JackPortIsPhysical|JackPortIsInput)) {
+-				snprintf (port->name, sizeof (port->name), "system:playback_%d", out_cnt++);
+-				strcpy (port->alias1, name);
+-				continue;
+-			} 
+-
+-			/* replace output port names, and use backend's original as an alias */
+-
+-			if ((port->flags & (JackPortIsPhysical|JackPortIsOutput)) == (JackPortIsPhysical|JackPortIsOutput)) {
+-				snprintf (port->name, sizeof (port->name), "system:capture_%d", in_cnt++);
+-				strcpy (port->alias1, name);
+-				continue;
+-			} 
+-		}
+-	}
+-}
+-
+ static jack_driver_info_t *
+ jack_load_driver (jack_engine_t *engine, jack_driver_desc_t * driver_desc)
+ {
+@@ -1223,7 +1185,7 @@
+ 
+ 	switch (req->type) {
+ 	case RegisterPort:
+-		req->status = jack_port_do_register (engine, req);
++		req->status = jack_port_do_register (engine, req, reply_fd ? FALSE : TRUE);
+ 		break;
+ 
+ 	case UnRegisterPort:
+@@ -3427,6 +3389,8 @@
+ 		engine->driver = 0;
+ 	}
+ 
++	engine->driver = driver;
++
+ 	if (driver) {
+ 		if (driver->attach (driver, engine))
+ 			return -1;
+@@ -3435,7 +3399,6 @@
+ 			jack_rolling_interval (driver->period_usecs);
+ 	}
+ 
+-	engine->driver = driver;
+ 	return 0;
+ }
+ 
+@@ -3511,14 +3474,19 @@
+ }
+ 
+ int
+-jack_port_do_register (jack_engine_t *engine, jack_request_t *req)
+-	
++jack_port_do_register (jack_engine_t *engine, jack_request_t *req, int internal)
+ {
+ 	jack_port_id_t port_id;
+ 	jack_port_shared_t *shared;
+ 	jack_port_internal_t *port;
+ 	jack_client_internal_t *client;
+ 	unsigned long i;
++	char *backend_client_name;
++	size_t len;
++	static int audio_out_cnt = 1;
++	static int audio_in_cnt = 1;
++	static int midi_out_cnt = 1;
++	static int midi_in_cnt = 1;
+ 
+ 	for (i = 0; i < engine->control->n_port_types; ++i) {
+ 		if (strcmp (req->x.port_info.type,
+@@ -3556,7 +3524,47 @@
+ 
+ 	shared = &engine->control->ports[port_id];
+ 
++	if (!internal || !engine->driver)
++		goto fallback;
++
++	backend_client_name = (char *) engine->driver->internal_client->control->name;
++	len = strlen (backend_client_name);
++
++	if (strncmp (req->x.port_info.name, backend_client_name, len) != 0)
++		goto fallback;
++
++	/* use backend's original as an alias, use predefined names */
++
++	if (strcmp(req->x.port_info.type, JACK_DEFAULT_AUDIO_TYPE) == 0) {
++		if ((req->x.port_info.flags & (JackPortIsPhysical|JackPortIsInput)) == (JackPortIsPhysical|JackPortIsInput)) {
++			snprintf (shared->name, sizeof (shared->name), JACK_BACKEND_ALIAS ":playback_%d", audio_out_cnt++);
++			strcpy (shared->alias1, req->x.port_info.name);
++			goto next;
++		} 
++		else if ((req->x.port_info.flags & (JackPortIsPhysical|JackPortIsOutput)) == (JackPortIsPhysical|JackPortIsOutput)) {
++			snprintf (shared->name, sizeof (shared->name), JACK_BACKEND_ALIAS ":capture_%d", audio_in_cnt++);
++			strcpy (shared->alias1, req->x.port_info.name);
++			goto next;
++		}
++	}
++	else if (strcmp(req->x.port_info.type, JACK_DEFAULT_MIDI_TYPE) == 0) {
++		if ((req->x.port_info.flags & (JackPortIsPhysical|JackPortIsInput)) == (JackPortIsPhysical|JackPortIsInput)) {
++			snprintf (shared->name, sizeof (shared->name), JACK_BACKEND_ALIAS ":midi_playback_%d", midi_out_cnt++);
++			strcpy (shared->alias1, req->x.port_info.name);
++			goto next;
++		} 
++		else if ((req->x.port_info.flags & (JackPortIsPhysical|JackPortIsOutput)) == (JackPortIsPhysical|JackPortIsOutput)) {
++			snprintf (shared->name, sizeof (shared->name), JACK_BACKEND_ALIAS ":midi_capture_%d", midi_in_cnt++);
++			strcpy (shared->alias1, req->x.port_info.name);
++			goto next;
++		}
++	}
++
++fallback:
+ 	strcpy (shared->name, req->x.port_info.name);
++
++next:
++
+ 	shared->ptype_id = engine->control->port_types[i].ptype_id;
+ 	shared->client_id = req->x.port_info.client_id;
+ 	shared->flags = req->x.port_info.flags;
+Index: jackd/jackd.c
+===================================================================
+--- jackd/jackd.c	(revision 1051)
++++ jackd/jackd.c	(working copy)
+@@ -160,8 +160,6 @@
+ 		goto error;
+ 	}
+ 
+-	jack_engine_munge_backend_port_names (engine);
+-
+ 	if (engine->driver->start (engine->driver) != 0) {
+ 		jack_error ("cannot start driver");
+ 		goto error;
+Index: drivers/alsa/alsa_driver.c
+===================================================================
+--- drivers/alsa/alsa_driver.c	(revision 1051)
++++ drivers/alsa/alsa_driver.c	(working copy)
+@@ -2347,7 +2347,7 @@
+ 
+ /* DRIVER "PLUGIN" INTERFACE */
+ 
+-const char driver_client_name[] = "alsa_pcm";
++const char driver_client_name[] = "ALSA";
+ 
+ const jack_driver_desc_t *
+ driver_get_descriptor ()

Modified: trunk/overlays/proaudio/media-sound/jack-audio-connection-kit/jack-audio-connection-kit-9999.ebuild
===================================================================
--- trunk/overlays/proaudio/media-sound/jack-audio-connection-kit/jack-audio-connection-kit-9999.ebuild	2007-12-09 21:31:09 UTC (rev 992)
+++ trunk/overlays/proaudio/media-sound/jack-audio-connection-kit/jack-audio-connection-kit-9999.ebuild	2007-12-10 21:09:08 UTC (rev 993)
@@ -16,7 +16,7 @@
 LICENSE="GPL-2 LGPL-2.1"
 SLOT="0"
 KEYWORDS=""
-IUSE="altivec alsa caps coreaudio doc debug jack-tmpfs mmx oss sndfile netjack
+IUSE="altivec alsa caps coreaudio dbus doc debug jack-tmpfs mmx oss sndfile netjack
 sse jackmidi freebob"
 
 RDEPEND="dev-util/pkgconfig
@@ -28,6 +28,7 @@
 	netjack? ( dev-util/scons )
 	jackmidi? ( media-libs/alsa-lib )
 	freebob? ( sys-libs/libfreebob )
+	dbus? ( sys-apps/dbus )
 	!media-sound/jack-audio-connection-kit-svn"
 DEPEND="${RDEPEND}
 	doc? ( app-doc/doxygen )"
@@ -56,6 +57,13 @@
 
 	# jack transport patch from Torben Hohn
 	epatch "${FILESDIR}/jack-transport-start-at-zero-fix.diff"
+
+	# dbus patches from Nedko Arnaudov
+	if use dbus; then
+		epatch "${FILESDIR}/jackd-midi-alsa-munge-r1051.patch"
+		epatch "${FILESDIR}/jack-logs-20071209-r1070.patch"
+		epatch "${FILESDIR}/jack-dbus-20071209-r1070.patch"
+	fi
 }
 
 src_compile() {
@@ -74,6 +82,10 @@
 		myconf="${myconf} --with-default-tmpdir=/var/run/jack"
 	fi
 
+	if use dbus; then
+		myconf="${myconf} --enable-dbus --enable-pkg-config-dbus-service-dir"
+	fi
+
 	if use userland_Darwin ; then
 		append-flags -fno-common
 		use altivec && append-flags -force_cpusubtype_ALL \
@@ -147,7 +159,13 @@
 		dobin alsa_in
 		dobin alsa_out
 		dobin jacknet_client
-		insinto /usr/$(get_libdir)/jack
+
+		# why on earth doesn't get_libdir work here
+		if use amd64; then
+			insinto /usr/lib64/jack
+		else
+			insinto /usr/lib/jack
+		fi
 		doins jack_net.so
 	fi
 }


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/