git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@2339 0c269be4-1314-0410-8aa9-9f06e86f4224tags/1.90
@@ -20,6 +20,10 @@ Fernando Lopez-Lezcano | |||
Jackdmp changes log | |||
--------------------------- | |||
2008-05-26 Stephane Letz <letz@grame.fr> | |||
* Merge control branch. | |||
2008-05-24 Stephane Letz <letz@grame.fr> | |||
* Tim Blechmann RAII idiom patch for JackServer ressource initialization. | |||
@@ -143,6 +147,10 @@ Fernando Lopez-Lezcano | |||
* Synchronise transport.h with latest jackd version (Video handling). | |||
2008-03-19 Stephane Letz <letz@grame.fr> | |||
* Add jack_port_type_id in jack API. | |||
2008-03-17 Stephane Letz <letz@grame.fr> | |||
* New jack_server_control client to test notifications when linked to the server library. | |||
@@ -81,6 +81,7 @@ opts.AddOptions( | |||
BoolOption('BUILD_EXAMPLES', 'Build the example clients in their directory', True), | |||
BoolOption('INSTALL_EXAMPLES', 'Install the example clients in the BINDIR directory', True), | |||
BoolOption('BUILD_DOXYGEN_DOCS', 'Build doxygen documentation', False), | |||
BoolOption('ENABLE_DBUS', 'Whether to use D-Bus API', False), | |||
('cc', 'cc', False), | |||
('cxx', 'cxx', False), | |||
('ccflags', 'ccflags', False), | |||
@@ -195,6 +196,7 @@ if env['DEBUG']: | |||
print '--> Doing a DEBUG build' | |||
# TODO: -Werror could be added to, which would force the devs to really remove all the warnings :-) | |||
env.AppendUnique(CCFLAGS = ['-DDEBUG', '-Wall', '-g']) | |||
env.AppendUnique(LINKFLAGS = ['-g']) | |||
else: | |||
env.AppendUnique(CCFLAGS = ['-O3','-DNDEBUG']) | |||
@@ -234,6 +236,8 @@ pkg_config_dir = env['INSTALL_LIBDIR']+"/pkgconfig/" | |||
env.Install(pkg_config_dir, 'jack.pc') | |||
env.Alias('install', pkg_config_dir) | |||
env['BINDIR']=env.subst(env['BINDIR']) | |||
# To have the top_srcdir as the doxygen-script is used from auto* | |||
env['top_srcdir'] = env.Dir('.').abspath | |||
@@ -259,6 +263,10 @@ subdirs=['common'] | |||
if env['PLATFORM'] == 'posix': | |||
subdirs.append('linux') | |||
if env['ENABLE_DBUS']: | |||
subdirs.append('linux/dbus') | |||
env.AppendUnique(CCFLAGS = ['-DJACK_DBUS']) | |||
# TODO FOR Marc: make macosx/SConscript work right | |||
if env['PLATFORM'] == 'macosx': | |||
subdirs.append('macosx') | |||
@@ -26,6 +26,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
#include "JackGlobals.h" | |||
#include "JackTime.h" | |||
#include "JackExports.h" | |||
#include "JackPortType.h" | |||
#ifdef __APPLE__ | |||
#include "JackMachThread.h" | |||
@@ -47,6 +48,18 @@ extern "C" | |||
{ | |||
#endif | |||
EXPORT | |||
void | |||
jack_get_version( | |||
int *major_ptr, | |||
int *minor_ptr, | |||
int *micro_ptr, | |||
int *proto_ptr); | |||
EXPORT | |||
const char * | |||
jack_get_version_string(); | |||
EXPORT jack_client_t * jack_client_open_aux (const char *client_name, | |||
jack_options_t options, | |||
jack_status_t *status, va_list ap); | |||
@@ -114,6 +127,7 @@ extern "C" | |||
EXPORT const char * jack_port_short_name (const jack_port_t *port); | |||
EXPORT int jack_port_flags (const jack_port_t *port); | |||
EXPORT const char * jack_port_type (const jack_port_t *port); | |||
EXPORT jack_port_type_id_t jack_port_type_id (const jack_port_t *port); | |||
EXPORT int jack_port_is_mine (const jack_client_t *, const jack_port_t *port); | |||
EXPORT int jack_port_connected (const jack_port_t *port); | |||
EXPORT int jack_port_connected_to (const jack_port_t *port, | |||
@@ -359,6 +373,21 @@ EXPORT const char* jack_port_type(const jack_port_t* port) | |||
} | |||
} | |||
EXPORT jack_port_type_id_t jack_port_type_id (const jack_port_t *port) | |||
{ | |||
#ifdef __CLIENTDEBUG__ | |||
JackLibGlobals::CheckContext(); | |||
#endif | |||
jack_port_id_t myport = (jack_port_id_t)port; | |||
if (!CheckPort(myport)) { | |||
jack_error("jack_port_type_id called an incorrect port %ld", myport); | |||
return 0; | |||
} else { | |||
JackGraphManager* manager = GetGraphManager(); | |||
return (manager ? GetPortTypeId(manager->GetPort(myport)->GetType()) : 0); | |||
} | |||
} | |||
EXPORT int jack_port_connected(const jack_port_t* port) | |||
{ | |||
#ifdef __CLIENTDEBUG__ | |||
@@ -1686,3 +1715,25 @@ EXPORT jack_status_t jack_internal_client_unload(jack_client_t* ext_client, jack | |||
return my_status; | |||
} | |||
} | |||
EXPORT | |||
void | |||
jack_get_version( | |||
int *major_ptr, | |||
int *minor_ptr, | |||
int *micro_ptr, | |||
int *proto_ptr) | |||
{ | |||
// FIXME: We need these comming from build system | |||
*major_ptr = 0; | |||
*minor_ptr = 0; | |||
*micro_ptr = 0; | |||
*proto_ptr = 0; | |||
} | |||
EXPORT | |||
const char * | |||
jack_get_version_string() | |||
{ | |||
return VERSION; | |||
} |
@@ -21,7 +21,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
#define __JackAtomicArrayState__ | |||
#include "JackAtomic.h" | |||
#include "JackError.h" | |||
#include <string.h> // for memcpy | |||
namespace Jack | |||
@@ -136,7 +135,6 @@ class JackAtomicArrayState | |||
JackAtomicArrayState() | |||
{ | |||
jack_log("JackAtomicArrayState constructor"); | |||
Counter1(fCounter) = 0; | |||
} | |||
@@ -21,7 +21,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
#define __JackChannel__ | |||
#include "types.h" | |||
#include "JackError.h" | |||
namespace Jack | |||
{ | |||
@@ -354,7 +354,7 @@ void JackConnectionManager::DirectDisconnect(int ref1, int ref2) | |||
bool JackConnectionManager::IsDirectConnection(int ref1, int ref2) const | |||
{ | |||
assert(ref1 >= 0 && ref2 >= 0); | |||
return fConnectionRef.GetItemCount(ref1, ref2); | |||
return (fConnectionRef.GetItemCount(ref1, ref2) > 0); | |||
} | |||
/*! | |||
@@ -22,6 +22,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
#include "JackConstants.h" | |||
#include "JackActivationCount.h" | |||
#include "JackError.h" | |||
#include <assert.h> | |||
namespace Jack | |||
@@ -48,6 +48,8 @@ namespace Jack | |||
#define LOOPBACK_DRIVER_REFNUM 2 // Loopback driver is initialized third, it will get the refnum 2 | |||
#define REAL_REFNUM LOOPBACK_DRIVER_REFNUM + 1 // Real clients start at LOOPBACK_DRIVER_REFNUM + 1 | |||
#define JACK_DEFAULT_SERVER_NAME "default" | |||
#ifdef WIN32 | |||
#define jack_server_dir "server" | |||
#define jack_client_dir "client" | |||
@@ -36,6 +36,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
#include <dirent.h> | |||
#endif | |||
#include <errno.h> | |||
jack_driver_desc_t * jackctl_driver_get_desc(jackctl_driver_t * driver); | |||
static void | |||
jack_print_driver_options (jack_driver_desc_t * desc, FILE *file) | |||
{ | |||
@@ -222,6 +226,147 @@ jack_parse_driver_params (jack_driver_desc_t * desc, int argc, char* argv[], JSL | |||
return 0; | |||
} | |||
EXPORT int | |||
jackctl_parse_driver_params (jackctl_driver *driver_ptr, int argc, char* argv[]) | |||
{ | |||
struct option * long_options; | |||
char * options, * options_ptr; | |||
unsigned long i; | |||
int opt; | |||
JSList * node_ptr; | |||
jackctl_parameter_t * param; | |||
union jackctl_parameter_value value; | |||
if (argc <= 1) | |||
return 0; | |||
const JSList * driver_params = jackctl_driver_get_parameters(driver_ptr); | |||
if (driver_params == NULL) | |||
return 1; | |||
jack_driver_desc_t * desc = jackctl_driver_get_desc(driver_ptr); | |||
/* check for help */ | |||
if (strcmp (argv[1], "-h") == 0 || strcmp (argv[1], "--help") == 0) { | |||
if (argc > 2) { | |||
for (i = 0; i < desc->nparams; i++) { | |||
if (strcmp (desc->params[i].name, argv[2]) == 0) { | |||
jack_print_driver_param_usage (desc, i, stdout); | |||
return 1; | |||
} | |||
} | |||
fprintf (stderr, "jackd: unknown option '%s' " | |||
"for driver '%s'\n", argv[2], | |||
desc->name); | |||
} | |||
printf ("Parameters for driver '%s' (all parameters are optional):\n", desc->name); | |||
jack_print_driver_options (desc, stdout); | |||
return 1; | |||
} | |||
/* set up the stuff for getopt */ | |||
options = (char*)calloc (desc->nparams * 3 + 1, sizeof (char)); | |||
long_options = (option*)calloc (desc->nparams + 1, sizeof (struct option)); | |||
options_ptr = options; | |||
for (i = 0; i < desc->nparams; i++) { | |||
sprintf (options_ptr, "%c::", desc->params[i].character); | |||
options_ptr += 3; | |||
long_options[i].name = desc->params[i].name; | |||
long_options[i].flag = NULL; | |||
long_options[i].val = desc->params[i].character; | |||
long_options[i].has_arg = optional_argument; | |||
} | |||
/* create the params */ | |||
optind = 0; | |||
opterr = 0; | |||
while ((opt = getopt_long(argc, argv, options, long_options, NULL)) != -1) { | |||
if (opt == ':' || opt == '?') { | |||
if (opt == ':') { | |||
fprintf (stderr, "Missing option to argument '%c'\n", optopt); | |||
} else { | |||
fprintf (stderr, "Unknownage with option '%c'\n", optopt); | |||
} | |||
fprintf (stderr, "Options for driver '%s':\n", desc->name); | |||
jack_print_driver_options (desc, stderr); | |||
exit (1); | |||
} | |||
node_ptr = (JSList *)driver_params; | |||
while (node_ptr) { | |||
param = (jackctl_parameter_t*)node_ptr->data; | |||
if (opt == jackctl_parameter_get_id(param)) { | |||
break; | |||
} | |||
node_ptr = node_ptr->next; | |||
} | |||
if (!optarg && optind < argc && | |||
strlen(argv[optind]) && | |||
argv[optind][0] != '-') { | |||
optarg = argv[optind]; | |||
} | |||
if (optarg) { | |||
switch (jackctl_parameter_get_type(param)) { | |||
case JackDriverParamInt: | |||
value.i = atoi (optarg); | |||
jackctl_parameter_set_value(param, &value); | |||
break; | |||
case JackDriverParamUInt: | |||
value.ui = strtoul (optarg, NULL, 10); | |||
jackctl_parameter_set_value(param, &value); | |||
break; | |||
case JackDriverParamChar: | |||
value.c = optarg[0]; | |||
jackctl_parameter_set_value(param, &value); | |||
break; | |||
case JackDriverParamString: | |||
strncpy (value.str, optarg, JACK_DRIVER_PARAM_STRING_MAX); | |||
jackctl_parameter_set_value(param, &value); | |||
break; | |||
case JackDriverParamBool: | |||
/* | |||
if (strcasecmp ("false", optarg) == 0 || | |||
strcasecmp ("off", optarg) == 0 || | |||
strcasecmp ("no", optarg) == 0 || | |||
strcasecmp ("0", optarg) == 0 || | |||
strcasecmp ("(null)", optarg) == 0 ) { | |||
*/ | |||
// steph | |||
if (strcmp ("false", optarg) == 0 || | |||
strcmp ("off", optarg) == 0 || | |||
strcmp ("no", optarg) == 0 || | |||
strcmp ("0", optarg) == 0 || | |||
strcmp ("(null)", optarg) == 0 ) { | |||
value.i = false; | |||
} else { | |||
value.i = true; | |||
} | |||
jackctl_parameter_set_value(param, &value); | |||
break; | |||
} | |||
} else { | |||
if (jackctl_parameter_get_type(param) == JackParamBool) { | |||
value.i = true; | |||
} else { | |||
value = jackctl_parameter_get_default_value(param); | |||
jackctl_parameter_set_value(param, &value); | |||
} | |||
} | |||
} | |||
free (options); | |||
free (long_options); | |||
return 0; | |||
} | |||
EXPORT jack_driver_desc_t * | |||
jack_find_driver_descriptor (JSList * drivers, const char * name) | |||
{ | |||
@@ -21,9 +21,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
#ifndef __JackDriverLoader__ | |||
#define __JackDriverLoader__ | |||
#include "jslist.h" | |||
#include "driver_interface.h" | |||
#include "JackDriver.h" | |||
#include "control_types.h" | |||
#include "jslist.h" | |||
#ifdef WIN32 | |||
@@ -54,14 +55,13 @@ typedef struct _jack_driver_info | |||
jack_driver_info_t; | |||
EXPORT jack_driver_desc_t * jack_find_driver_descriptor (JSList * drivers, const char * name); | |||
jack_driver_desc_t * jack_drivers_get_descriptor (JSList * drivers, const char * sofile); | |||
EXPORT JSList * jack_drivers_load (JSList * drivers); | |||
jack_driver_info_t * jack_load_driver (jack_driver_desc_t * driver_desc); | |||
EXPORT int jack_parse_driver_params (jack_driver_desc_t * desc, int argc, char* argv[], JSList ** param_ptr); | |||
EXPORT int jackctl_parse_driver_params (jackctl_driver *driver_ptr, int argc, char* argv[]); | |||
#endif | |||
@@ -34,6 +34,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
#include "JackGlobals.h" | |||
#include "JackChannel.h" | |||
#include "JackSyncInterface.h" | |||
#include "JackError.h" | |||
namespace Jack | |||
{ | |||
@@ -76,6 +77,7 @@ int JackEngine::Close() | |||
jack_log("JackEngine::Close"); | |||
fChannel->Close(); | |||
// Close (possibly) remaining clients (RT is stopped) | |||
for (int i = 0; i < CLIENT_NUM; i++) { | |||
/* | |||
Can only delete clients that where loaded using "jack_internal_client_load" (and not properly unloaded using "jack_internal_client_unload"...) | |||
@@ -112,6 +114,7 @@ void JackEngine::ReleaseRefnum(int ref) | |||
fClientTable[ref] = NULL; | |||
if (fEngineControl->fTemporary) { | |||
jack_log("JackEngine::ReleaseRefnum fTemporary"); | |||
int i; | |||
for (i = REAL_REFNUM; i < CLIENT_NUM; i++) { | |||
if (fClientTable[i]) | |||
@@ -217,7 +220,7 @@ void JackEngine::NotifyClient(int refnum, int event, int sync, int value1, int v | |||
jack_log("JackEngine::NotifyClient: client not available anymore"); | |||
} else if (client->GetClientControl()->fCallback[event]) { | |||
if (client->ClientNotify(refnum, client->GetClientControl()->fName, event, sync, value1, value2) < 0) | |||
jack_error("NotifyClient fails name = %s event = %ld val1 = %ld val2 = %ld", client->GetClientControl()->fName, event, value1, value2); | |||
jack_error("NotifyClient fails name = %s event = %ld = val1 = %ld val2 = %ld", client->GetClientControl()->fName, event, value1, value2); | |||
} else { | |||
jack_log("JackEngine::NotifyClient: no callback for event = %ld", event); | |||
} | |||
@@ -680,7 +683,7 @@ int JackEngine::PortRegister(int refnum, const char* name, const char *type, uns | |||
assert(fClientTable[refnum]); | |||
// Check if port name already exists | |||
if (fGraphManager->GetPort(name) != NO_PORT) { | |||
if (GetGraphManager()->GetPort(name) != NO_PORT) { | |||
jack_error("port_name \"%s\" already exists", name); | |||
return -1; | |||
} | |||
@@ -25,6 +25,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
#include "JackFrameTimer.h" | |||
#include "JackTransportEngine.h" | |||
#include "types.h" | |||
#include <stdio.h> | |||
namespace Jack | |||
{ | |||
@@ -1,92 +0,0 @@ | |||
/* | |||
Copyright (C) 2001 Paul Davis | |||
Copyright (C) 2004-2008 Grame | |||
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, or | |||
(at your option) any later version. | |||
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 <stdarg.h> | |||
#include <stdio.h> | |||
#include "JackError.h" | |||
int jack_verbose = 0; | |||
static | |||
void | |||
jack_format_and_log(const char *prefix, const char *fmt, va_list ap, void (* log_callback)(const char *)) | |||
{ | |||
char buffer[300]; | |||
size_t len; | |||
if (prefix != NULL) { | |||
len = strlen(prefix); | |||
memcpy(buffer, prefix, len); | |||
} else { | |||
len = 0; | |||
} | |||
vsnprintf(buffer + len, sizeof(buffer) - len, fmt, ap); | |||
log_callback(buffer); | |||
} | |||
EXPORT void jack_error(const char *fmt, ...) | |||
{ | |||
va_list ap; | |||
va_start(ap, fmt); | |||
jack_format_and_log(NULL, fmt, ap, jack_error_callback); | |||
va_end(ap); | |||
} | |||
EXPORT void jack_info(const char *fmt, ...) | |||
{ | |||
va_list ap; | |||
va_start(ap, fmt); | |||
jack_format_and_log(NULL, fmt, ap, jack_info_callback); | |||
va_end(ap); | |||
} | |||
EXPORT void jack_info_multiline(const char *fmt, ...) | |||
{ | |||
va_list ap; | |||
va_start(ap, fmt); | |||
jack_format_and_log(NULL, fmt, ap, jack_info_callback); | |||
va_end(ap); | |||
} | |||
EXPORT void jack_log(const char *fmt,...) | |||
{ | |||
if (jack_verbose) { | |||
va_list ap; | |||
va_start(ap, fmt); | |||
jack_format_and_log("Jack: ", fmt, ap, jack_info_callback); | |||
va_end(ap); | |||
} | |||
} | |||
static void default_jack_error_callback(const char *desc) | |||
{ | |||
fprintf(stderr, "%s\n", desc); | |||
fflush(stderr); | |||
} | |||
static void default_jack_info_callback (const char *desc) | |||
{ | |||
fprintf(stdout, "%s\n", desc); | |||
fflush(stdout); | |||
} | |||
void (*jack_error_callback)(const char *desc) = &default_jack_error_callback; | |||
void (*jack_info_callback)(const char *desc) = &default_jack_info_callback; |
@@ -1,6 +1,7 @@ | |||
/* | |||
Copyright (C) 2001 Paul Davis | |||
Copyright (C) 2004-2008 Grame | |||
Copyright (C) 2008 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 | |||
@@ -19,20 +20,22 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
*/ | |||
#ifndef __JackError__ | |||
#define __JackError__ | |||
#include <string.h> | |||
#include <errno.h> | |||
#include <stdio.h> | |||
#include "JackExports.h" | |||
#include "types.h" | |||
#ifdef __cplusplus | |||
extern "C" | |||
{ | |||
#endif | |||
#ifdef WIN32 | |||
#define vsnprintf _vsnprintf | |||
#define snprintf _snprintf | |||
#endif | |||
#define LOG_LEVEL_INFO 1 | |||
#define LOG_LEVEL_ERROR 2 | |||
EXPORT void jack_error(const char *fmt, ...); | |||
@@ -41,11 +44,20 @@ extern "C" | |||
// like jack_info() but only if verbose mode is enabled | |||
EXPORT void jack_log(const char *fmt, ...); | |||
extern int jack_verbose; | |||
extern void (*jack_error_callback)(const char *desc); | |||
extern void (*jack_info_callback)(const char *desc); | |||
typedef void (* jack_log_function_t)(int level, const char *message); | |||
void change_thread_log_function(jack_log_function_t log_function); | |||
void jack_log_function(int level, const char *message); | |||
EXPORT void set_threaded_log_function(); | |||
extern int jack_verbose; | |||
#ifdef __cplusplus | |||
} | |||
#endif | |||
#endif |
@@ -58,6 +58,71 @@ namespace Jack | |||
JackDriverException(const char* msg) : JackException(msg) | |||
{} | |||
}; | |||
} | |||
#endif | |||
/* | |||
Copyright (C) 2008 Grame | |||
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, or | |||
(at your option) any later version. | |||
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 __JackException__ | |||
#define __JackException__ | |||
#include <stdexcept> | |||
#include <iostream> | |||
#include <string> | |||
#include "JackError.h" | |||
namespace Jack | |||
{ | |||
class JackException : public std::runtime_error { | |||
public: | |||
JackException(const std::string& msg) : runtime_error(msg) | |||
{} | |||
JackException(const char* msg) : runtime_error(msg) | |||
{} | |||
std::string Message() | |||
{ | |||
return what(); | |||
} | |||
void PrintMessage() | |||
{ | |||
std::string str = what(); | |||
jack_error(str.c_str()); | |||
} | |||
}; | |||
class JackDriverException : public JackException { | |||
public: | |||
JackDriverException(const std::string& msg) : JackException(msg) | |||
{} | |||
JackDriverException(const char* msg) : JackException(msg) | |||
{} | |||
}; | |||
} | |||
#endif |
@@ -22,6 +22,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
#include "JackClientControl.h" | |||
#include "JackGlobals.h" | |||
#include "JackChannel.h" | |||
#include "JackError.h" | |||
namespace Jack | |||
{ | |||
@@ -18,22 +18,78 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
*/ | |||
#include "JackGlobals.h" | |||
#include "JackError.h" | |||
namespace Jack | |||
{ | |||
JackFactoryImpl* JackGlobals::fInstance; | |||
JackFactoryImpl* JackGlobals::fInstance; | |||
void JackGlobals::InitServer() | |||
{ | |||
jack_log("JackGlobals InitServer"); | |||
if (!fInstance) { | |||
#ifdef __APPLE__ | |||
fInstance = new JackFactoryOSXServer(); | |||
#endif | |||
#ifdef WIN32 | |||
fInstance = new JackFactoryWindowsServer(); | |||
#endif | |||
#ifdef __linux__ | |||
fInstance = new JackFactoryLinuxServer(); | |||
#endif | |||
} | |||
} | |||
void JackGlobals::InitClient() | |||
{ | |||
jack_log("JackGlobals InitClient"); | |||
if (!fInstance) { | |||
#ifdef __APPLE__ | |||
fInstance = new JackFactoryOSXClient(); | |||
#endif | |||
#ifdef WIN32 | |||
fInstance = new JackFactoryWindowsClient(); | |||
#endif | |||
#ifdef __linux__ | |||
fInstance = new JackFactoryLinuxClient(); | |||
#endif | |||
} | |||
} | |||
void JackGlobals::Destroy() | |||
{ | |||
jack_log("JackGlobals Destroy"); | |||
if (fInstance) { | |||
delete fInstance; | |||
fInstance = NULL; | |||
} | |||
} | |||
} // end of namespace | |||
static bool gKeyRealtimeInitialized = false; | |||
static bool g_key_log_function_initialized = false; | |||
jack_tls_key gRealTime; | |||
jack_tls_key g_key_log_function; | |||
void jack_init() | |||
{ | |||
if (!gKeyRealtimeInitialized) { | |||
gKeyRealtimeInitialized = jack_tls_allocate_key(&gRealTime); | |||
} | |||
if (!g_key_log_function_initialized) | |||
g_key_log_function_initialized = jack_tls_allocate_key(&g_key_log_function); | |||
} | |||
void jack_uninit() | |||
@@ -42,6 +98,11 @@ void jack_uninit() | |||
jack_tls_free_key(gRealTime); | |||
gKeyRealtimeInitialized = false; | |||
} | |||
if (g_key_log_function_initialized) { | |||
jack_tls_free_key(g_key_log_function); | |||
g_key_log_function_initialized = false; | |||
} | |||
} | |||
// Initialisation at library load time | |||
@@ -229,55 +229,12 @@ class JackGlobals | |||
return fInstance->MakeThread(runnable); | |||
} | |||
static void InitServer() | |||
{ | |||
jack_log("JackGlobals InitServer"); | |||
if (!fInstance) { | |||
#ifdef __APPLE__ | |||
fInstance = new JackFactoryOSXServer(); | |||
#endif | |||
#ifdef WIN32 | |||
fInstance = new JackFactoryWindowsServer(); | |||
#endif | |||
#ifdef __linux__ | |||
fInstance = new JackFactoryLinuxServer(); | |||
#endif | |||
} | |||
} | |||
static void InitClient() | |||
{ | |||
jack_log("JackGlobals InitClient"); | |||
if (!fInstance) { | |||
#ifdef __APPLE__ | |||
fInstance = new JackFactoryOSXClient(); | |||
#endif | |||
#ifdef WIN32 | |||
fInstance = new JackFactoryWindowsClient(); | |||
#endif | |||
#ifdef __linux__ | |||
fInstance = new JackFactoryLinuxClient(); | |||
#endif | |||
} | |||
} | |||
static void Destroy() | |||
{ | |||
jack_log("JackGlobals Destroy"); | |||
if (fInstance) { | |||
delete fInstance; | |||
fInstance = NULL; | |||
} | |||
} | |||
static void InitServer(); | |||
static void InitClient(); | |||
static void Destroy(); | |||
}; | |||
namespace detail | |||
@@ -304,6 +261,7 @@ extern "C" | |||
#endif | |||
extern jack_tls_key gRealTime; | |||
extern jack_tls_key g_key_log_function; | |||
#ifdef WIN32 | |||
@@ -67,6 +67,13 @@ namespace Jack | |||
{ | |||
#ifdef WIN32 | |||
JackSynchro* JackFactoryWindowsServer::MakeSynchro() {return NULL;} | |||
JackServerNotifyChannelInterface* JackFactoryWindowsServer::MakeServerNotifyChannel() {return NULL;} | |||
JackClientChannelInterface* JackFactoryWindowsServer::MakeClientChannel() {return NULL;} | |||
JackNotifyChannelInterface* JackFactoryWindowsServer::MakeNotifyChannel() {return NULL;} | |||
JackServerChannelInterface* JackFactoryWindowsServer::MakeServerChannel() {return NULL;} | |||
JackSyncInterface* JackFactoryWindowsServer::MakeInterProcessSync() {return NULL;} | |||
JackThread* JackFactoryWindowsServer::MakeThread(JackRunnableInterface* runnable) {return NULL;} | |||
JackSynchro* JackFactoryWindowsClient::MakeSynchro() | |||
{ | |||
@@ -144,6 +151,14 @@ JackThread* JackFactoryLinuxClient::MakeThread(JackRunnableInterface* runnable) | |||
#endif | |||
#if defined(SOCKET_RPC_FIFO_SEMA) | |||
JackSynchro* JackFactoryLinuxServer::MakeSynchro() {return NULL;} | |||
JackServerNotifyChannelInterface* JackFactoryLinuxServer::MakeServerNotifyChannel() {return NULL;} | |||
JackClientChannelInterface* JackFactoryLinuxServer::MakeClientChannel() {return NULL;} | |||
JackNotifyChannelInterface* JackFactoryLinuxServer::MakeNotifyChannel() {return NULL;} | |||
JackServerChannelInterface* JackFactoryLinuxServer::MakeServerChannel() {return NULL;} | |||
JackSyncInterface* JackFactoryLinuxServer::MakeInterProcessSync() {return NULL;} | |||
JackThread* JackFactoryLinuxServer::MakeThread(JackRunnableInterface* runnable) {return NULL;} | |||
JackSynchro* JackFactoryLinuxClient::MakeSynchro() | |||
{ | |||
return new JackFifo(); | |||
@@ -223,6 +238,14 @@ JackThread* JackFactoryLinuxClient::MakeThread(JackRunnableInterface* runnable) | |||
#if defined(MACH_RPC_MACH_SEMA) | |||
// Mach RPC + Mach Semaphore | |||
JackSynchro* JackFactoryOSXServer::MakeSynchro() {return NULL;} | |||
JackServerNotifyChannelInterface* JackFactoryOSXServer::MakeServerNotifyChannel() {return NULL;} | |||
JackClientChannelInterface* JackFactoryOSXServer::MakeClientChannel() {return NULL;} | |||
JackNotifyChannelInterface* JackFactoryOSXServer::MakeNotifyChannel() {return NULL;} | |||
JackServerChannelInterface* JackFactoryOSXServer::MakeServerChannel() {return NULL;} | |||
JackSyncInterface* JackFactoryOSXServer::MakeInterProcessSync() {return NULL;} | |||
JackThread* JackFactoryOSXServer::MakeThread(JackRunnableInterface* runnable) {return NULL;} | |||
JackSynchro* JackFactoryOSXClient::MakeSynchro() | |||
{ | |||
return new JackMachSemaphore(); | |||
@@ -338,6 +361,7 @@ JackThread* JackFactoryOSXClient::MakeThread(JackRunnableInterface* runnable) | |||
#if defined(MACH_RPC_FIFO_SEMA) | |||
// Mach RPC + Fifo Semaphore | |||
JackSynchro* JackFactoryOSXClient::MakeSynchro() | |||
{ | |||
return new JackFifo(); | |||
@@ -78,6 +78,14 @@ namespace Jack | |||
{ | |||
#ifdef WIN32 | |||
JackSynchro* JackFactoryWindowsClient::MakeSynchro() {return NULL;} | |||
JackServerNotifyChannelInterface* JackFactoryWindowsClient::MakeServerNotifyChannel() {return NULL;} | |||
JackClientChannelInterface* JackFactoryWindowsClient::MakeClientChannel() {return NULL;} | |||
JackNotifyChannelInterface* JackFactoryWindowsClient::MakeNotifyChannel() {return NULL;} | |||
JackServerChannelInterface* JackFactoryWindowsClient::MakeServerChannel() {return NULL;} | |||
JackSyncInterface* JackFactoryWindowsClient::MakeInterProcessSync() {return NULL;} | |||
JackThread* JackFactoryWindowsClient::MakeThread(JackRunnableInterface* runnable) {return NULL;} | |||
JackSynchro* JackFactoryWindowsServer::MakeSynchro() | |||
{ | |||
return new JackWinSemaphore(); | |||
@@ -154,6 +162,14 @@ JackThread* JackFactoryLinuxServer::MakeThread(JackRunnableInterface* runnable) | |||
#endif | |||
#if defined(SOCKET_RPC_FIFO_SEMA) | |||
JackSynchro* JackFactoryLinuxClient::MakeSynchro() {return NULL;} | |||
JackServerNotifyChannelInterface* JackFactoryLinuxClient::MakeServerNotifyChannel() {return NULL;} | |||
JackClientChannelInterface* JackFactoryLinuxClient::MakeClientChannel() {return NULL;} | |||
JackNotifyChannelInterface* JackFactoryLinuxClient::MakeNotifyChannel() {return NULL;} | |||
JackServerChannelInterface* JackFactoryLinuxClient::MakeServerChannel() {return NULL;} | |||
JackSyncInterface* JackFactoryLinuxClient::MakeInterProcessSync() {return NULL;} | |||
JackThread* JackFactoryLinuxClient::MakeThread(JackRunnableInterface* runnable) {return NULL;} | |||
JackSynchro* JackFactoryLinuxServer::MakeSynchro() | |||
{ | |||
return new JackFifo(); | |||
@@ -233,6 +249,14 @@ JackThread* JackFactoryLinuxServer::MakeThread(JackRunnableInterface* runnable) | |||
#if defined(MACH_RPC_MACH_SEMA) | |||
// Mach RPC + Mach Semaphore | |||
JackSynchro* JackFactoryOSXClient::MakeSynchro() {return NULL;} | |||
JackServerNotifyChannelInterface* JackFactoryOSXClient::MakeServerNotifyChannel() {return NULL;} | |||
JackClientChannelInterface* JackFactoryOSXClient::MakeClientChannel() {return NULL;} | |||
JackNotifyChannelInterface* JackFactoryOSXClient::MakeNotifyChannel() {return NULL;} | |||
JackServerChannelInterface* JackFactoryOSXClient::MakeServerChannel() {return NULL;} | |||
JackSyncInterface* JackFactoryOSXClient::MakeInterProcessSync() {return NULL;} | |||
JackThread* JackFactoryOSXClient::MakeThread(JackRunnableInterface* runnable) {return NULL;} | |||
JackSynchro* JackFactoryOSXServer::MakeSynchro() | |||
{ | |||
return new JackMachSemaphore(); | |||
@@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
#include "JackGraphManager.h" | |||
#include "JackConstants.h" | |||
#include "JackError.h" | |||
#include <assert.h> | |||
#include <stdlib.h> | |||
#include <algorithm> | |||
@@ -27,22 +27,23 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
namespace Jack | |||
{ | |||
// Used for external C API (JackAPI.cpp) | |||
JackGraphManager* GetGraphManager() | |||
{ | |||
if (JackLibGlobals::fGlobals) { | |||
return JackLibGlobals::fGlobals->fGraphManager; | |||
} else { | |||
return NULL; | |||
if (JackLibGlobals::fGlobals) { | |||
return JackLibGlobals::fGlobals->fGraphManager; | |||
} else { | |||
return NULL; | |||
} | |||
} | |||
JackEngineControl* GetEngineControl() | |||
{ | |||
if (JackLibGlobals::fGlobals) { | |||
return JackLibGlobals::fGlobals->fEngineControl; | |||
} else { | |||
return NULL; | |||
if (JackLibGlobals::fGlobals) { | |||
return JackLibGlobals::fGlobals->fEngineControl; | |||
} else { | |||
return NULL; | |||
} | |||
} | |||
@@ -28,7 +28,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
#endif | |||
#include "JackGlobals.h" | |||
#include "JackGraphManager.h" | |||
#include "JackMessageBuffer.h" | |||
#include "JackTime.h" | |||
#include "JackError.h" | |||
#include <assert.h> | |||
namespace Jack | |||
@@ -55,6 +57,7 @@ struct JackLibGlobals | |||
JackLibGlobals() | |||
{ | |||
jack_log("JackLibGlobals"); | |||
JackMessageBuffer::Create(); | |||
for (int i = 0; i < CLIENT_NUM; i++) | |||
fSynchroTable[i] = JackGlobals::MakeSynchro(); | |||
fGraphManager = -1; | |||
@@ -68,6 +71,7 @@ struct JackLibGlobals | |||
fSynchroTable[i]->Disconnect(); | |||
delete fSynchroTable[i]; | |||
} | |||
JackMessageBuffer::Destroy(); | |||
} | |||
static void Init() | |||
@@ -25,6 +25,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
#include "JackLoopbackDriver.h" | |||
#include "JackEngineControl.h" | |||
#include "JackGraphManager.h" | |||
#include "JackError.h" | |||
#include <iostream> | |||
#include <assert.h> | |||
@@ -35,7 +35,7 @@ enum | |||
PORT_TYPES_MAX = sizeof(port_types) / sizeof(port_types[0]) | |||
}; | |||
int GetPortTypeId(const char* port_type) | |||
jack_port_type_id_t GetPortTypeId(const char* port_type) | |||
{ | |||
for (int i = 0; i < PORT_TYPES_MAX; ++i) { | |||
const JackPortType* type = port_types[i]; | |||
@@ -46,7 +46,7 @@ int GetPortTypeId(const char* port_type) | |||
return -1; | |||
} | |||
const JackPortType* GetPortType(int type_id) | |||
const JackPortType* GetPortType(jack_port_type_id_t type_id) | |||
{ | |||
assert(type_id >= 0 && type_id <= PORT_TYPES_MAX); | |||
const JackPortType* type = port_types[type_id]; | |||
@@ -34,11 +34,11 @@ struct JackPortType | |||
void (*mixdown)(void *mixbuffer, void** src_buffers, int src_count, jack_nframes_t nframes); | |||
}; | |||
extern int GetPortTypeId(const char* port_type); | |||
extern const JackPortType* GetPortType(int port_type_id); | |||
extern jack_port_type_id_t GetPortTypeId(const char* port_type); | |||
extern const struct JackPortType* GetPortType(jack_port_type_id_t port_type_id); | |||
extern const JackPortType gAudioPortType; | |||
extern const JackPortType gMidiPortType; | |||
extern const struct JackPortType gAudioPortType; | |||
extern const struct JackPortType gMidiPortType; | |||
} // namespace Jack | |||
@@ -67,45 +67,10 @@ class JackProcessSync : public JackSyncInterface | |||
void Destroy() | |||
{} | |||
bool TimedWait(long usec) | |||
{ | |||
struct timeval T0, T1; | |||
timespec time; | |||
struct timeval now; | |||
int res; | |||
pthread_mutex_lock(&fLock); | |||
jack_log("JackProcessSync::Wait time out = %ld", usec); | |||
gettimeofday(&T0, 0); | |||
static const UInt64 kNanosPerSec = 1000000000ULL; | |||
static const UInt64 kNanosPerUsec = 1000ULL; | |||
gettimeofday(&now, 0); | |||
UInt64 nextDateNanos = now.tv_sec * kNanosPerSec + (now.tv_usec + usec) * kNanosPerUsec; | |||
time.tv_sec = nextDateNanos / kNanosPerSec; | |||
time.tv_nsec = nextDateNanos % kNanosPerSec; | |||
res = pthread_cond_timedwait(&fCond, &fLock, &time); | |||
if (res != 0) | |||
jack_error("pthread_cond_timedwait error usec = %ld err = %s", usec, strerror(res)); | |||
gettimeofday(&T1, 0); | |||
pthread_mutex_unlock(&fLock); | |||
jack_log("JackProcessSync::Wait finished delta = %5.1lf", | |||
(1e6 * T1.tv_sec - 1e6 * T0.tv_sec + T1.tv_usec - T0.tv_usec)); | |||
return (res == 0); | |||
} | |||
void Wait() | |||
{ | |||
int res; | |||
pthread_mutex_lock(&fLock); | |||
jack_log("JackProcessSync::Wait..."); | |||
if ((res = pthread_cond_wait(&fCond, &fLock)) != 0) | |||
jack_error("pthread_cond_wait error err = %s", strerror(errno)); | |||
pthread_mutex_unlock(&fLock); | |||
jack_log("JackProcessSync::Wait finished"); | |||
} | |||
bool TimedWait(long usec); | |||
void Wait(); | |||
void SignalAll() | |||
{ | |||
//pthread_mutex_lock(&fLock); | |||
@@ -150,17 +115,7 @@ class JackInterProcessSync : public JackSyncInterface | |||
return fSynchro->Connect(name, ""); | |||
} | |||
bool TimedWait(long usec) | |||
{ | |||
struct timeval T0, T1; | |||
jack_log("JackInterProcessSync::Wait..."); | |||
gettimeofday(&T0, 0); | |||
bool res = fSynchro->TimedWait(usec); | |||
gettimeofday(&T1, 0); | |||
jack_log("JackInterProcessSync::Wait finished delta = %5.1lf", | |||
(1e6 * T1.tv_sec - 1e6 * T0.tv_sec + T1.tv_usec - T0.tv_usec)); | |||
return res; | |||
} | |||
bool TimedWait(long usec); | |||
void Wait() | |||
{ | |||
@@ -23,8 +23,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
#include "JackConstants.h" | |||
#include "JackChannelTransaction.h" | |||
#include "JackError.h" | |||
#include <stdio.h> | |||
#include <string.h> | |||
namespace Jack | |||
{ | |||
@@ -36,6 +36,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
#include "JackSyncInterface.h" | |||
#include "JackGraphManager.h" | |||
#include "JackInternalClient.h" | |||
#include "JackError.h" | |||
#include "JackMessageBuffer.h" | |||
namespace Jack | |||
{ | |||
@@ -81,6 +83,9 @@ JackServer::~JackServer() | |||
int JackServer::Open(jack_driver_desc_t* driver_desc, JSList* driver_params) | |||
{ | |||
// TODO: move that in reworked JackServerGlobals::Init() | |||
JackMessageBuffer::Create(); | |||
if (fChannel->Open(fEngineControl->fServerName, this) < 0) { | |||
jack_error("Server channel open error"); | |||
return -1; | |||
@@ -141,6 +146,8 @@ int JackServer::Close() | |||
fFreewheelDriver->Close(); | |||
fLoopbackDriver->Close(); | |||
fEngine->Close(); | |||
// TODO: move that in reworked JackServerGlobals::Destroy() | |||
JackMessageBuffer::Destroy(); | |||
return 0; | |||
} | |||
@@ -151,10 +158,9 @@ int JackServer::InternalClientLoad(const char* client_name, const char* so_name, | |||
*status = 0; | |||
JackLoadableInternalClient* client = new JackLoadableInternalClient(fInstance, GetSynchroTable(), so_name, objet_data); | |||
assert(client); | |||
if (client->Open("unused", client_name, (jack_options_t)options, (jack_status_t*)status) < 0) { | |||
int res = client->Open("unused", client_name, (jack_options_t)options, (jack_status_t*)status); | |||
if (res < 0) { | |||
delete client; | |||
int my_status1 = *status | JackFailure; | |||
*status = (jack_status_t)my_status1; | |||
*int_ref = 0; | |||
} else { | |||
*int_ref = client->GetClientControl()->fRefNum; | |||
@@ -164,6 +170,7 @@ int JackServer::InternalClientLoad(const char* client_name, const char* so_name, | |||
*status = (jack_status_t)my_status1; | |||
*int_ref = 0; | |||
} | |||
return 0; | |||
} | |||
@@ -27,17 +27,11 @@ This program is free software; you can redistribute it and/or modify | |||
#include "JackServer.h" | |||
#include "JackDebugClient.h" | |||
#include "JackServerGlobals.h" | |||
#include "JackError.h" | |||
#include "JackServerLaunch.h" | |||
#include "JackTools.h" | |||
#include "JackExports.h" | |||
#include "JackEngine.h" | |||
#ifdef WIN32 | |||
#define EXPORT __declspec(dllexport) | |||
#else | |||
#define EXPORT | |||
#endif | |||
#ifdef __cplusplus | |||
extern "C" | |||
{ | |||
@@ -58,6 +52,9 @@ extern "C" | |||
using namespace Jack; | |||
// beware!!! things can go nasty if one client is started with JackNoStartServer and another without it | |||
bool g_nostart; | |||
EXPORT jack_client_t* jack_client_open_aux(const char* ext_client_name, jack_options_t options, jack_status_t* status, va_list ap) | |||
{ | |||
jack_varargs_t va; /* variable arguments */ | |||
@@ -90,10 +87,13 @@ EXPORT jack_client_t* jack_client_open_aux(const char* ext_client_name, jack_opt | |||
else | |||
jack_varargs_init(&va); | |||
if (!JackServerGlobals::Init()) { // jack server initialisation | |||
int my_status1 = (JackFailure | JackServerError); | |||
*status = (jack_status_t)my_status1; | |||
return NULL; | |||
g_nostart = (options & JackNoStartServer) != 0; | |||
if (!g_nostart) { | |||
if (!JackServerGlobals::Init()) { // jack server initialisation | |||
int my_status1 = (JackFailure | JackServerError); | |||
*status = (jack_status_t)my_status1; | |||
return NULL; | |||
} | |||
} | |||
#ifndef WIN32 | |||
@@ -109,7 +109,9 @@ EXPORT jack_client_t* jack_client_open_aux(const char* ext_client_name, jack_opt | |||
int res = client->Open(va.server_name, client_name, options, status); | |||
if (res < 0) { | |||
delete client; | |||
JackServerGlobals::Destroy(); // jack server destruction | |||
if (!g_nostart) { | |||
JackServerGlobals::Destroy(); // jack server destruction | |||
} | |||
int my_status1 = (JackFailure | JackServerError); | |||
*status = (jack_status_t)my_status1; | |||
return NULL; | |||
@@ -138,7 +140,9 @@ EXPORT int jack_client_close(jack_client_t* ext_client) | |||
int res = client->Close(); | |||
delete client; | |||
jack_log("jack_client_close OK"); | |||
JackServerGlobals::Destroy(); // jack server destruction | |||
if (!g_nostart) { | |||
JackServerGlobals::Destroy(); // jack server destruction | |||
} | |||
return res; | |||
} | |||
} | |||
@@ -22,10 +22,11 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
#endif | |||
#include "JackServerGlobals.h" | |||
#include "JackError.h" | |||
#include "JackTools.h" | |||
#include "shm.h" | |||
#include <getopt.h> | |||
#include <stdio.h> | |||
#include <errno.h> | |||
static char* server_name = NULL; | |||
@@ -277,8 +278,7 @@ bool JackServerGlobals::Init() | |||
jack_error("no access to shm registry"); | |||
goto error; | |||
default: | |||
if (jack_verbose) | |||
jack_info("server `%s' registered", server_name); | |||
jack_info("server `%s' registered", server_name); | |||
} | |||
/* clean up shared memory and files from any previous instance of this server name */ | |||
@@ -30,6 +30,55 @@ using namespace Jack; | |||
#ifndef WIN32 | |||
#if defined(JACK_DBUS) | |||
#include <dbus/dbus.h> | |||
int start_server_dbus(const char* server_name) | |||
{ | |||
DBusError err; | |||
DBusConnection *conn; | |||
DBusMessage *msg; | |||
// initialise the errors | |||
dbus_error_init(&err); | |||
// connect to the bus | |||
conn = dbus_bus_get(DBUS_BUS_SESSION, &err); | |||
if (dbus_error_is_set(&err)) { | |||
fprintf(stderr, "Connection Error (%s)\n", err.message); | |||
dbus_error_free(&err); | |||
} | |||
if (NULL == conn) { | |||
return 1; | |||
} | |||
msg = dbus_message_new_method_call( | |||
"org.jackaudio.service", // target for the method call | |||
"/org/jackaudio/Controller", // object to call on | |||
"org.jackaudio.JackControl", // interface to call on | |||
"StartServer"); // method name | |||
if (NULL == msg) { | |||
fprintf(stderr, "Message Null\n"); | |||
return 1; | |||
} | |||
// send message and get a handle for a reply | |||
if (!dbus_connection_send(conn, msg, NULL)) | |||
{ | |||
fprintf(stderr, "Out Of Memory!\n"); | |||
return 1; | |||
} | |||
dbus_message_unref(msg); | |||
dbus_connection_flush(conn); | |||
dbus_error_free(&err); | |||
return 0; | |||
} | |||
#else | |||
/* Exec the JACK server in this process. Does not return. */ | |||
static void start_server_aux(const char* server_name) | |||
{ | |||
@@ -114,12 +163,18 @@ static void start_server_aux(const char* server_name) | |||
fprintf(stderr, "exec of JACK server (command = \"%s\") failed: %s\n", command, strerror(errno)); | |||
} | |||
#endif | |||
int start_server(const char* server_name, jack_options_t options) | |||
{ | |||
if ((options & JackNoStartServer) || getenv("JACK_NO_START_SERVER")) { | |||
return 1; | |||
} | |||
#if defined(JACK_DBUS) | |||
return start_server_dbus(server_name); | |||
#else | |||
/* The double fork() forces the server to become a child of | |||
* init, which will always clean up zombie process state on | |||
* termination. This even works in cases where the server | |||
@@ -146,6 +201,7 @@ int start_server(const char* server_name, jack_options_t options) | |||
/* only the original parent process goes here */ | |||
return 0; /* (probably) successful */ | |||
#endif | |||
} | |||
int server_connect(char* server_name) | |||
@@ -18,8 +18,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
*/ | |||
#include "JackShmMem.h" | |||
#include "JackError.h" | |||
#include "JackShmMem.h" | |||
#include <stdio.h> | |||
namespace Jack | |||
@@ -82,6 +82,11 @@ void JackShmMem::operator delete(void* p, size_t size) | |||
jack_destroy_shm(&info); | |||
} | |||
void JackShmMem::operator delete(void* p) | |||
{ | |||
JackShmMem::operator delete(p, 0); | |||
} | |||
void LockMemoryImp(void* ptr, size_t size) | |||
{ | |||
if (CHECK_MLOCK(ptr, size)) { | |||
@@ -68,7 +68,7 @@ class JackMem | |||
{ | |||
free(ptr); | |||
} | |||
JackMem(): fSize(gSize) | |||
{} | |||
@@ -107,6 +107,7 @@ class JackShmMem | |||
void* operator new(size_t size); | |||
void* operator new(size_t size, void* memory); | |||
void operator delete(void* p, size_t size); | |||
void operator delete(void* p); | |||
JackShmMem() | |||
{ | |||
@@ -62,6 +62,7 @@ class JackSocketServerChannel : public JackServerChannelInterface, public JackRu | |||
void Close(); // Close the Server/Client connection | |||
// JackRunnableInterface interface | |||
bool Init(); | |||
bool Execute(); | |||
}; | |||
@@ -20,8 +20,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
#ifndef __JackSynchro__ | |||
#define __JackSynchro__ | |||
#include "JackError.h" | |||
#define SYNC_MAX_NAME_SIZE 256 | |||
namespace Jack | |||
@@ -1,22 +1,22 @@ | |||
/* | |||
Copyright (C) 2001 Paul Davis | |||
Copyright (C) 2004-2008 Grame | |||
This program is free software; you can redistribute it and/or modify | |||
it under the terms of the GNU Lesser General Public License as published by | |||
the Free Software Foundation; either version 2.1 of the License, or | |||
(at your option) any later version. | |||
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 Lesser General Public License for more details. | |||
You should have received a copy of the GNU Lesser General Public License | |||
along with this program; if not, write to the Free Software | |||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
*/ | |||
Copyright (C) 2001 Paul Davis | |||
Copyright (C) 2004-2008 Grame | |||
This program is free software; you can redistribute it and/or modify | |||
it under the terms of the GNU Lesser General Public License as published by | |||
the Free Software Foundation; either version 2.1 of the License, or | |||
(at your option) any later version. | |||
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 Lesser General Public License for more details. | |||
You should have received a copy of the GNU Lesser General Public License | |||
along with this program; if not, write to the Free Software | |||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
*/ | |||
#ifndef __JackThread__ | |||
#define __JackThread__ | |||
@@ -32,21 +32,21 @@ typedef unsigned long long UInt64; | |||
namespace Jack | |||
{ | |||
/*! | |||
\brief The base class for runnable objects, that have an <B> Init </B> and <B> Execute </B> method to be called in a thread. | |||
*/ | |||
\brief The base class for runnable objects, that have an <B> Init </B> and <B> Execute </B> method to be called in a thread. | |||
*/ | |||
class JackRunnableInterface | |||
{ | |||
public: | |||
JackRunnableInterface() | |||
{} | |||
virtual ~JackRunnableInterface() | |||
{} | |||
virtual bool Init() /*! Called once when the thread is started */ | |||
{ | |||
return true; | |||
@@ -55,37 +55,37 @@ class JackRunnableInterface | |||
}; | |||
/*! | |||
\brief The thread base class. | |||
*/ | |||
\brief The thread base class. | |||
*/ | |||
class JackThread | |||
{ | |||
public: | |||
enum kThreadState {kIdle, kStarting, kRunning}; | |||
enum kThreadState {kIdle, kStarting, kRunning}; | |||
protected: | |||
JackRunnableInterface* fRunnable; | |||
int fPriority; | |||
bool fRealTime; | |||
volatile kThreadState fStatus; | |||
int fCancellation; | |||
public: | |||
JackThread(JackRunnableInterface* runnable, int priority, bool real_time, int cancellation): | |||
fRunnable(runnable), fPriority(priority), fRealTime(real_time), fStatus(kIdle), fCancellation(cancellation) | |||
fRunnable(runnable), fPriority(priority), fRealTime(real_time), fStatus(kIdle), fCancellation(cancellation) | |||
{} | |||
virtual ~JackThread() | |||
{} | |||
virtual int Start() = 0; | |||
virtual int StartSync() = 0; | |||
virtual int Kill() = 0; | |||
virtual int Stop() = 0; | |||
virtual void Terminate() = 0; | |||
virtual int AcquireRealTime() = 0; | |||
virtual int AcquireRealTime(int priority) = 0; | |||
virtual int DropRealTime() = 0; | |||
@@ -98,14 +98,14 @@ class JackThread | |||
{ | |||
fStatus = status; | |||
} | |||
virtual void SetParams(UInt64 period, UInt64 computation, UInt64 constraint) // Empty implementation, will only make sense on OSX... | |||
{} | |||
virtual pthread_t GetThreadID() = 0; | |||
}; | |||
} // end of namespace | |||
#if defined(WIN32) | |||
@@ -25,6 +25,8 @@ | |||
#include <process.h> | |||
#endif | |||
#include "JackConstants.h" | |||
namespace Jack | |||
{ | |||
@@ -54,7 +56,7 @@ const char* JackTools::DefaultServerName() | |||
{ | |||
const char* server_name; | |||
if ((server_name = getenv("JACK_DEFAULT_SERVER")) == NULL) | |||
server_name = "default"; | |||
server_name = JACK_DEFAULT_SERVER_NAME; | |||
return server_name; | |||
} | |||
@@ -21,38 +21,56 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
#include <iostream> | |||
#include <assert.h> | |||
#include <signal.h> | |||
#include <pwd.h> | |||
#include <sys/types.h> | |||
#include <dirent.h> | |||
#include <getopt.h> | |||
#include "JackServer.h" | |||
#include <string.h> | |||
#include "jack.h" | |||
#include "JackConstants.h" | |||
#include "driver_interface.h" | |||
#include "JackDriverLoader.h" | |||
#include "jslist.h" | |||
#include "JackError.h" | |||
#include "JackTools.h" | |||
#include "shm.h" | |||
#include "jack.h" | |||
/* | |||
This is a simple port of the old jackdmp.cpp file to use the new Jack 2.0 control API. Available options for the server | |||
are "hard-coded" in the source. A much better approach would be to use the control API to: | |||
- dynamically retrieve available server parameters and then prepare to parse them | |||
- get available drivers and their possible parameters, then prepare to parse them. | |||
*/ | |||
#ifdef __APPLE_ | |||
#include <CoreFoundation/CFNotificationCenter.h> | |||
#endif | |||
using namespace Jack; | |||
static void notify_server_start(const char* server_name) | |||
{ | |||
// Send notification to be used in the JackRouter plugin | |||
CFStringRef ref = CFStringCreateWithCString(NULL, server_name, kCFStringEncodingMacRoman); | |||
CFNotificationCenterPostNotificationWithOptions(CFNotificationCenterGetDistributedCenter(), | |||
CFSTR("com.grame.jackserver.start"), | |||
ref, | |||
NULL, | |||
kCFNotificationDeliverImmediately | kCFNotificationPostToAllSessions); | |||
CFRelease(ref); | |||
} | |||
static void notify_server_stop(const char* server_name) | |||
{ | |||
// Send notification to be used in the JackRouter plugin | |||
CFStringRef ref1 = CFStringCreateWithCString(NULL, server_name, kCFStringEncodingMacRoman); | |||
CFNotificationCenterPostNotificationWithOptions(CFNotificationCenterGetDistributedCenter(), | |||
CFSTR("com.grame.jackserver.stop"), | |||
ref1, | |||
NULL, | |||
kCFNotificationDeliverImmediately | kCFNotificationPostToAllSessions); | |||
CFRelease(ref1); | |||
} | |||
static JackServer* fServer; | |||
static char* server_name = NULL; | |||
static int realtime_priority = 10; | |||
static int do_mlock = 1; | |||
static int realtime = 0; | |||
static int loopback = 0; | |||
static int temporary = 0; | |||
static int client_timeout = 0; /* msecs; if zero, use period size. */ | |||
static int do_unlock = 0; | |||
static JSList* drivers = NULL; | |||
static sigset_t signals; | |||
#else | |||
static void notify_server_start(const char* server_name) | |||
{} | |||
static void notify_server_stop(const char* server_name) | |||
{} | |||
#endif | |||
static void silent_jack_error_callback(const char *desc) | |||
{} | |||
@@ -87,63 +105,56 @@ static void usage(FILE* file) | |||
" to display options for each driver\n\n"); | |||
} | |||
static void DoNothingHandler(int sig) | |||
// To put in the control.h interface?? | |||
static jackctl_driver_t * | |||
jackctl_server_get_driver( | |||
jackctl_server_t *server, | |||
const char *driver_name) | |||
{ | |||
/* 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)); | |||
} | |||
const JSList * node_ptr; | |||
static int JackStart(const char* server_name, jack_driver_desc_t* driver_desc, JSList* driver_params, int sync, int temporary, int time_out_ms, int rt, int priority, int loopback, int verbose) | |||
{ | |||
jack_log("Jackdmp: sync = %ld timeout = %ld rt = %ld priority = %ld verbose = %ld ", sync, time_out_ms, rt, priority, verbose); | |||
fServer = new JackServer(sync, temporary, time_out_ms, rt, priority, loopback, verbose, server_name); | |||
int res = fServer->Open(driver_desc, driver_params); | |||
return (res < 0) ? res : fServer->Start(); | |||
} | |||
node_ptr = jackctl_server_get_drivers_list(server); | |||
static int JackStop() | |||
{ | |||
fServer->Stop(); | |||
fServer->Close(); | |||
jack_log("Jackdmp: server close"); | |||
delete fServer; | |||
jack_log("Jackdmp: delete server"); | |||
return 0; | |||
} | |||
while (node_ptr) | |||
{ | |||
if (strcmp(jackctl_driver_get_name((jackctl_driver_t *)node_ptr->data), driver_name) == 0) | |||
{ | |||
return (jackctl_driver_t *)node_ptr->data; | |||
} | |||
static int JackDelete() | |||
{ | |||
delete fServer; | |||
jack_log("Jackdmp: delete server"); | |||
return 0; | |||
node_ptr = jack_slist_next(node_ptr); | |||
} | |||
return NULL; | |||
} | |||
static void FilterSIGPIPE() | |||
static jackctl_parameter_t * | |||
jackctl_get_parameter( | |||
const JSList * parameters_list, | |||
const char * parameter_name) | |||
{ | |||
sigset_t set; | |||
sigemptyset(&set); | |||
sigaddset(&set, SIGPIPE); | |||
//sigprocmask(SIG_BLOCK, &set, 0); | |||
pthread_sigmask(SIG_BLOCK, &set, 0); | |||
while (parameters_list) | |||
{ | |||
if (strcmp(jackctl_parameter_get_name((jackctl_parameter_t *)parameters_list->data), parameter_name) == 0) | |||
{ | |||
return (jackctl_parameter_t *)parameters_list->data; | |||
} | |||
parameters_list = jack_slist_next(parameters_list); | |||
} | |||
return NULL; | |||
} | |||
int main(int argc, char* argv[]) | |||
{ | |||
int sig; | |||
sigset_t allsignals; | |||
struct sigaction action; | |||
int waiting; | |||
jack_driver_desc_t* driver_desc; | |||
jackctl_server_t * server_ctl; | |||
const JSList * server_parameters; | |||
const char* server_name = "default"; | |||
jackctl_driver_t * driver_ctl; | |||
const char *options = "-ad:P:uvrshVRL:STFl:t:mn:"; | |||
struct option long_options[] = { | |||
{ "driver", 1, 0, 'd'}, | |||
{ "driver", 1, 0, 'd' }, | |||
{ "verbose", 0, 0, 'v' }, | |||
{ "help", 0, 0, 'h' }, | |||
{ "port-max", 1, 0, 'p' }, | |||
@@ -161,17 +172,26 @@ int main(int argc, char* argv[]) | |||
{ "sync", 0, 0, 'S' }, | |||
{ 0, 0, 0, 0 } | |||
}; | |||
int opt = 0; | |||
int i,opt = 0; | |||
int option_index = 0; | |||
int seen_driver = 0; | |||
bool seen_driver = false; | |||
char *driver_name = NULL; | |||
char **driver_args = NULL; | |||
JSList* driver_params; | |||
int driver_nargs = 1; | |||
int show_version = 0; | |||
int replace_registry = 0; | |||
int sync = 0; | |||
int rc, i; | |||
bool show_version = false; | |||
sigset_t signals; | |||
jackctl_parameter_t* param; | |||
union jackctl_parameter_value value; | |||
copyright(stdout); | |||
server_ctl = jackctl_server_create(); | |||
if (server_ctl == NULL) { | |||
fprintf(stderr, "Failed to create server object"); | |||
return -1; | |||
} | |||
server_parameters = jackctl_server_get_parameters(server_ctl); | |||
opterr = 0; | |||
while (!seen_driver && | |||
@@ -180,12 +200,16 @@ int main(int argc, char* argv[]) | |||
switch (opt) { | |||
case 'd': | |||
seen_driver = 1; | |||
seen_driver = true; | |||
driver_name = optarg; | |||
break; | |||
case 'v': | |||
jack_verbose = 1; | |||
param = jackctl_get_parameter(server_parameters, "verbose"); | |||
if (param != NULL) { | |||
value.b = true; | |||
jackctl_parameter_set_value(param, &value); | |||
} | |||
break; | |||
case 's': | |||
@@ -193,80 +217,98 @@ int main(int argc, char* argv[]) | |||
break; | |||
case 'S': | |||
sync = 1; | |||
param = jackctl_get_parameter(server_parameters, "sync"); | |||
if (param != NULL) { | |||
value.b = true; | |||
jackctl_parameter_set_value(param, &value); | |||
} | |||
break; | |||
case 'n': | |||
server_name = optarg; | |||
break; | |||
case 'm': | |||
do_mlock = 0; | |||
param = jackctl_get_parameter(server_parameters, "name"); | |||
if (param != NULL) { | |||
strncpy(value.str, optarg, JACK_PARAM_STRING_MAX); | |||
jackctl_parameter_set_value(param, &value); | |||
} | |||
break; | |||
case 'P': | |||
realtime_priority = atoi(optarg); | |||
param = jackctl_get_parameter(server_parameters, "realtime-priority"); | |||
if (param != NULL) { | |||
value.i = atoi(optarg); | |||
jackctl_parameter_set_value(param, &value); | |||
} | |||
break; | |||
case 'r': | |||
replace_registry = 1; | |||
param = jackctl_get_parameter(server_parameters, "replace-registry"); | |||
if (param != NULL) { | |||
value.b = true; | |||
jackctl_parameter_set_value(param, &value); | |||
} | |||
break; | |||
case 'R': | |||
realtime = 1; | |||
param = jackctl_get_parameter(server_parameters, "realtime"); | |||
if (param != NULL) { | |||
value.b = true; | |||
jackctl_parameter_set_value(param, &value); | |||
} | |||
break; | |||
case 'L': | |||
loopback = atoi(optarg); | |||
param = jackctl_get_parameter(server_parameters, "loopback ports"); | |||
if (param != NULL) { | |||
value.ui = atoi(optarg); | |||
jackctl_parameter_set_value(param, &value); | |||
} | |||
break; | |||
case 'T': | |||
temporary = 1; | |||
param = jackctl_get_parameter(server_parameters, "temporary"); | |||
if (param != NULL) { | |||
value.b = true; | |||
jackctl_parameter_set_value(param, &value); | |||
} | |||
break; | |||
case 't': | |||
client_timeout = atoi(optarg); | |||
break; | |||
case 'u': | |||
do_unlock = 1; | |||
param = jackctl_get_parameter(server_parameters, "client-timeout"); | |||
if (param != NULL) { | |||
value.i = atoi(optarg); | |||
jackctl_parameter_set_value(param, &value); | |||
} | |||
break; | |||
case 'V': | |||
show_version = 1; | |||
show_version = true; | |||
break; | |||
default: | |||
fprintf(stderr, "unknown option character %c\n", | |||
optopt); | |||
fprintf(stderr, "unknown option character %c\n", optopt); | |||
/*fallthru*/ | |||
case 'h': | |||
usage(stdout); | |||
return -1; | |||
goto fail_free; | |||
} | |||
} | |||
if (show_version) { | |||
printf("jackdmp version " VERSION | |||
if (show_version) { | |||
printf("jackdmp version" VERSION | |||
"\n"); | |||
return -1; | |||
} | |||
if (!seen_driver) { | |||
usage(stderr); | |||
exit(1); | |||
} | |||
drivers = jack_drivers_load(drivers); | |||
if (!drivers) { | |||
fprintf(stderr, "jackdmp: no drivers found; exiting\n"); | |||
exit(1); | |||
goto fail_free; | |||
} | |||
driver_desc = jack_find_driver_descriptor(drivers, driver_name); | |||
if (!driver_desc) { | |||
fprintf(stderr, "jackdmp: unknown driver '%s'\n", driver_name); | |||
exit(1); | |||
driver_ctl = jackctl_server_get_driver(server_ctl, driver_name); | |||
if (driver_ctl == NULL) { | |||
fprintf(stderr, "Unkown driver \"%s\"\n", driver_name); | |||
goto fail_free; | |||
} | |||
if (optind < argc) { | |||
@@ -278,7 +320,7 @@ int main(int argc, char* argv[]) | |||
if (driver_nargs == 0) { | |||
fprintf(stderr, "No driver specified ... hmm. JACK won't do" | |||
" anything when run like this.\n"); | |||
return -1; | |||
goto fail_free; | |||
} | |||
driver_args = (char **) malloc(sizeof(char *) * driver_nargs); | |||
@@ -288,132 +330,27 @@ int main(int argc, char* argv[]) | |||
driver_args[i] = argv[optind++]; | |||
} | |||
if (jack_parse_driver_params(driver_desc, driver_nargs, | |||
driver_args, &driver_params)) { | |||
exit(0); | |||
} | |||
if (server_name == NULL) | |||
server_name = (char*)JackTools::DefaultServerName(); | |||
copyright(stdout); | |||
rc = jack_register_server(server_name, replace_registry); | |||
switch (rc) { | |||
case EEXIST: | |||
fprintf(stderr, "`%s' server already active\n", server_name); | |||
exit(1); | |||
case ENOSPC: | |||
fprintf(stderr, "too many servers already active\n"); | |||
exit(2); | |||
case ENOMEM: | |||
fprintf(stderr, "no access to shm registry\n"); | |||
exit(3); | |||
default: | |||
if (jack_verbose) | |||
fprintf(stderr, "server `%s' registered\n", server_name); | |||
} | |||
/* clean up shared memory and files from any previous | |||
* instance of this server name */ | |||
jack_cleanup_shm(); | |||
JackTools::CleanupFiles(server_name); | |||
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); | |||
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 | |||
FilterSIGPIPE(); | |||
pthread_sigmask(SIG_BLOCK, &signals, 0); | |||
if (!realtime && client_timeout == 0) | |||
client_timeout = 500; /* 0.5 sec; usable when non realtime. */ | |||
int res = JackStart(server_name, driver_desc, driver_params, sync, temporary, client_timeout, realtime, realtime_priority, loopback, jack_verbose); | |||
if (res < 0) { | |||
jack_error("Cannot start server... exit"); | |||
JackDelete(); | |||
return 0; | |||
} | |||
#ifdef __APPLE__ | |||
CFStringRef ref = CFStringCreateWithCString(NULL, server_name, kCFStringEncodingMacRoman); | |||
// Send notification to be used in the JackRouter plugin | |||
CFNotificationCenterPostNotificationWithOptions(CFNotificationCenterGetDistributedCenter(), | |||
CFSTR("com.grame.jackserver.start"), | |||
ref, | |||
NULL, | |||
kCFNotificationDeliverImmediately | kCFNotificationPostToAllSessions); | |||
CFRelease(ref); | |||
#endif | |||
// install a do-nothing handler because otherwise pthreads | |||
// behaviour is undefined when we enter sigwait. | |||
sigfillset(&allsignals); | |||
action.sa_handler = DoNothingHandler; | |||
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); | |||
} | |||
} | |||
waiting = TRUE; | |||
while (waiting) { | |||
sigwait(&signals, &sig); | |||
fprintf(stderr, "jack main caught signal %d\n", sig); | |||
switch (sig) { | |||
case SIGUSR1: | |||
//jack_dump_configuration(engine, 1); | |||
break; | |||
case SIGUSR2: | |||
// driver exit | |||
waiting = FALSE; | |||
break; | |||
default: | |||
waiting = FALSE; | |||
break; | |||
} | |||
if (jackctl_parse_driver_params(driver_ctl, driver_nargs, driver_args)) { | |||
goto fail_free; | |||
} | |||
if (sig != SIGSEGV) { | |||
// unblock signals so we can see them during shutdown. | |||
// this will help prod developers not to lose sight of | |||
// bugs that cause segfaults etc. during shutdown. | |||
sigprocmask(SIG_UNBLOCK, &signals, 0); | |||
if (!jackctl_server_start(server_ctl, driver_ctl)) { | |||
fprintf(stderr,"Failed to start server"); | |||
goto fail_free; | |||
} | |||
JackStop(); | |||
jack_cleanup_shm(); | |||
JackTools::CleanupFiles(server_name); | |||
jack_unregister_server(server_name); | |||
#ifdef __APPLE__ | |||
CFStringRef ref1 = CFStringCreateWithCString(NULL, server_name, kCFStringEncodingMacRoman); | |||
// Send notification to be used in the JackRouter plugin | |||
CFNotificationCenterPostNotificationWithOptions(CFNotificationCenterGetDistributedCenter(), | |||
CFSTR("com.grame.jackserver.stop"), | |||
ref1, | |||
NULL, | |||
kCFNotificationDeliverImmediately | kCFNotificationPostToAllSessions); | |||
CFRelease(ref1); | |||
#endif | |||
notify_server_start(server_name); | |||
// Waits for signal | |||
signals = jackctl_setup_signals(0); | |||
jackctl_wait_signals(signals); | |||
if (!jackctl_server_stop(server_ctl)) | |||
fprintf(stderr,"Cannot stop server..."); | |||
fail_free: | |||
jackctl_server_destroy(server_ctl); | |||
notify_server_stop(server_name); | |||
return 1; | |||
} |
@@ -23,6 +23,31 @@ import os | |||
import glob | |||
from string import Template | |||
def pkg_config_get_value(module, args): | |||
return env.backtick('pkg-config ' + args + ' ' + module).strip() | |||
def merge_pkg_config_append_string(env, envvar, module, args): | |||
value = pkg_config_get_value(module, args) | |||
#print value | |||
if env._dict.has_key(envvar): | |||
env._dict[envvar] += value | |||
else: | |||
env._dict[envvar] = value | |||
def merge_pkg_config_libs(env, module): | |||
for lib in pkg_config_get_value(module, "--libs").split(' '): | |||
if lib[:2] == '-l': | |||
env._dict['LIBS'].append(lib[2:]) | |||
elif lib[:2] == '-L': | |||
env._dict['LIBPATH'].append(lib[2:]) | |||
def merge_pkg_config_variable(env, envvar, module, pkgvar): | |||
merge_pkg_config_append_string(env, envvar, module, '--variable=' + pkgvar) | |||
def merge_pkg_config_std(env, module): | |||
merge_pkg_config_append_string(env, 'CCFLAGS', module, '--cflags') | |||
merge_pkg_config_libs(env, module) | |||
Import('env') | |||
@@ -51,7 +76,7 @@ srcfiles_common_serverlib = [ | |||
'JackDriver.cpp', | |||
'JackEngine.cpp', | |||
'JackEngineControl.cpp', | |||
'JackError.c', | |||
'JackError.cpp', | |||
'JackExternalClient.cpp', | |||
'JackFrameTimer.cpp', | |||
'JackFreewheelDriver.cpp', | |||
@@ -85,7 +110,10 @@ srcfiles_common_serverlib = [ | |||
'JackServerLaunch.cpp', | |||
'timestamps.c', | |||
'JackTools.cpp', | |||
'ringbuffer.c' | |||
'ringbuffer.c', | |||
'JackControl.cpp', | |||
'JackMessageBuffer.cpp', | |||
'JackProcessSync.cpp' | |||
] | |||
srcfiles_common_clientlib = [ | |||
@@ -95,7 +123,7 @@ srcfiles_common_clientlib = [ | |||
'JackConnectionManager.cpp', | |||
'ringbuffer.c', | |||
'JackServerLaunch.cpp', | |||
'JackError.c', | |||
'JackError.cpp', | |||
'JackFrameTimer.cpp', | |||
'JackGlobalsClient.cpp', | |||
'JackGraphManager.cpp', | |||
@@ -119,7 +147,9 @@ srcfiles_common_clientlib = [ | |||
'JackDebugClient.cpp', | |||
'JackTransportEngine.cpp', | |||
'timestamps.c', | |||
'JackTools.cpp' | |||
'JackTools.cpp', | |||
'JackMessageBuffer.cpp', | |||
'JackProcessSync.cpp' | |||
] | |||
jack_headers = [ | |||
@@ -130,7 +160,9 @@ jack_headers = [ | |||
'statistics.h', | |||
'thread.h', | |||
'transport.h', | |||
'types.h' | |||
'types.h', | |||
'control.h', | |||
'jslist.h' | |||
] | |||
# | |||
@@ -138,6 +170,10 @@ jack_headers = [ | |||
# | |||
# Libraries | |||
if env['ENABLE_DBUS']: | |||
merge_pkg_config_std(env, 'dbus-1') # actually we need this only for client lib | |||
# Each platform should get it's own environment | |||
libenv = env.Copy() | |||
if env['PLATFORM'] == 'posix': | |||
@@ -41,6 +41,34 @@ extern "C" | |||
* Note: More documentation can be found in jack/types.h. | |||
*/ | |||
/** | |||
* Call this function to get version of the JACK, in form of several numbers | |||
* | |||
* @param major_ptr pointer to variable receiving major version of JACK. | |||
* | |||
* @param minor_ptr pointer to variable receiving minor version of JACK. | |||
* | |||
* @param major_ptr pointer to variable receiving micro version of JACK. | |||
* | |||
* @param major_ptr pointer to variable receiving protocol version of JACK. | |||
* | |||
*/ | |||
void | |||
jack_get_version( | |||
int *major_ptr, | |||
int *minor_ptr, | |||
int *micro_ptr, | |||
int *proto_ptr); | |||
/** | |||
* Call this function to get version of the JACK, in form of a string | |||
* | |||
* @return Human readable string describing JACK version being used. | |||
* | |||
*/ | |||
const char * | |||
jack_get_version_string(); | |||
/** | |||
* Open an external client session with a JACK server. This interface | |||
* is more complex but more powerful than jack_client_new(). With it, | |||
@@ -513,6 +541,11 @@ extern "C" | |||
* including a final NULL. | |||
*/ | |||
const char * jack_port_type (const jack_port_t *port); | |||
/** | |||
* @return the @a port type id. | |||
*/ | |||
jack_port_type_id_t jack_port_type_id (const jack_port_t *port); | |||
/** | |||
* @return TRUE if the jack_port_t belongs to the jack_client_t. | |||
@@ -19,10 +19,12 @@ | |||
*/ | |||
#ifndef __jack_types_h__ | |||
#define __jack_types_h__ | |||
#define __jack_types_h__ | |||
#ifdef WIN32 | |||
#include <windows.h> | |||
#ifdef WIN32 | |||
#include <windows.h> | |||
#define vsnprintf _vsnprintf | |||
#define snprintf _snprintf | |||
#ifndef __MINGW32__ | |||
typedef long int32_t; | |||
typedef unsigned long uint32_t; | |||
@@ -97,6 +99,8 @@ typedef uint64_t jack_port_id_t; | |||
typedef uint32_t jack_port_id_t; | |||
#endif | |||
typedef uint32_t jack_port_type_id_t; | |||
/** | |||
* Prototype for the client supplied function that is called | |||
* by the engine anytime there is work to be done. | |||
@@ -1,287 +0,0 @@ | |||
/* | |||
Based on gslist.c from glib-1.2.9 (LGPL). | |||
Adaption to JACK, Copyright (C) 2002 Kai Vehmanen. | |||
- replaced use of gtypes with normal ANSI C types | |||
- glib's memory allocation routines replaced with | |||
malloc/free calls | |||
This program is free software; you can redistribute it and/or modify | |||
it under the terms of the GNU Lesser General Public License as published by | |||
the Free Software Foundation; either version 2.1 of the License, or | |||
(at your option) any later version. | |||
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 Lesser General Public License for more details. | |||
You should have received a copy of the GNU Lesser General Public License | |||
along with this program; if not, write to the Free Software | |||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
*/ | |||
#ifndef __jack_jslist_h__ | |||
#define __jack_jslist_h__ | |||
#include <stdlib.h> | |||
#ifdef WIN32 | |||
#define __inline__ inline | |||
#endif | |||
typedef struct _JSList JSList; | |||
typedef int (*JCompareFunc) (void* a, void* b); | |||
struct _JSList | |||
{ | |||
void *data; | |||
JSList *next; | |||
}; | |||
static __inline__ | |||
JSList* | |||
jack_slist_alloc (void) | |||
{ | |||
JSList *new_list; | |||
new_list = (JSList*)malloc(sizeof(JSList)); | |||
new_list->data = NULL; | |||
new_list->next = NULL; | |||
return new_list; | |||
} | |||
static __inline__ | |||
JSList* | |||
jack_slist_prepend (JSList* list, void* data) | |||
{ | |||
JSList *new_list; | |||
new_list = (JSList*)malloc(sizeof(JSList)); | |||
new_list->data = data; | |||
new_list->next = list; | |||
return new_list; | |||
} | |||
#define jack_slist_next(slist) ((slist) ? (((JSList *)(slist))->next) : NULL) | |||
static __inline__ | |||
JSList* | |||
jack_slist_last (JSList *list) | |||
{ | |||
if (list) { | |||
while (list->next) | |||
list = list->next; | |||
} | |||
return list; | |||
} | |||
static __inline__ | |||
JSList* | |||
jack_slist_remove_link (JSList *list, | |||
JSList *link) | |||
{ | |||
JSList *tmp; | |||
JSList *prev; | |||
prev = NULL; | |||
tmp = list; | |||
while (tmp) { | |||
if (tmp == link) { | |||
if (prev) | |||
prev->next = tmp->next; | |||
if (list == tmp) | |||
list = list->next; | |||
tmp->next = NULL; | |||
break; | |||
} | |||
prev = tmp; | |||
tmp = tmp->next; | |||
} | |||
return list; | |||
} | |||
static __inline__ | |||
void | |||
jack_slist_free (JSList *list) | |||
{ | |||
while (list) { | |||
JSList *next = list->next; | |||
free(list); | |||
list = next; | |||
} | |||
} | |||
static __inline__ | |||
void | |||
jack_slist_free_1 (JSList *list) | |||
{ | |||
if (list) { | |||
free(list); | |||
} | |||
} | |||
static __inline__ | |||
JSList* | |||
jack_slist_remove (JSList *list, | |||
void *data) | |||
{ | |||
JSList *tmp; | |||
JSList *prev; | |||
prev = NULL; | |||
tmp = list; | |||
while (tmp) { | |||
if (tmp->data == data) { | |||
if (prev) | |||
prev->next = tmp->next; | |||
if (list == tmp) | |||
list = list->next; | |||
tmp->next = NULL; | |||
jack_slist_free (tmp); | |||
break; | |||
} | |||
prev = tmp; | |||
tmp = tmp->next; | |||
} | |||
return list; | |||
} | |||
static __inline__ | |||
unsigned int | |||
jack_slist_length (JSList *list) | |||
{ | |||
unsigned int length; | |||
length = 0; | |||
while (list) { | |||
length++; | |||
list = list->next; | |||
} | |||
return length; | |||
} | |||
static __inline__ | |||
JSList* | |||
jack_slist_find (JSList *list, | |||
void *data) | |||
{ | |||
while (list) { | |||
if (list->data == data) | |||
break; | |||
list = list->next; | |||
} | |||
return list; | |||
} | |||
static __inline__ | |||
JSList* | |||
jack_slist_copy (JSList *list) | |||
{ | |||
JSList *new_list = NULL; | |||
if (list) { | |||
JSList *last; | |||
new_list = jack_slist_alloc (); | |||
new_list->data = list->data; | |||
last = new_list; | |||
list = list->next; | |||
while (list) { | |||
last->next = jack_slist_alloc (); | |||
last = last->next; | |||
last->data = list->data; | |||
list = list->next; | |||
} | |||
} | |||
return new_list; | |||
} | |||
static __inline__ | |||
JSList* | |||
jack_slist_append (JSList *list, | |||
void *data) | |||
{ | |||
JSList *new_list; | |||
JSList *last; | |||
new_list = jack_slist_alloc (); | |||
new_list->data = data; | |||
if (list) { | |||
last = jack_slist_last (list); | |||
last->next = new_list; | |||
return list; | |||
} else | |||
return new_list; | |||
} | |||
static __inline__ | |||
JSList* | |||
jack_slist_sort_merge (JSList *l1, | |||
JSList *l2, | |||
JCompareFunc compare_func) | |||
{ | |||
JSList list, *l; | |||
l = &list; | |||
while (l1 && l2) { | |||
if (compare_func(l1->data, l2->data) < 0) { | |||
l = l->next = l1; | |||
l1 = l1->next; | |||
} else { | |||
l = l->next = l2; | |||
l2 = l2->next; | |||
} | |||
} | |||
l->next = l1 ? l1 : l2; | |||
return list.next; | |||
} | |||
static __inline__ | |||
JSList* | |||
jack_slist_sort (JSList *list, | |||
JCompareFunc compare_func) | |||
{ | |||
JSList *l1, *l2; | |||
if (!list) | |||
return NULL; | |||
if (!list->next) | |||
return list; | |||
l1 = list; | |||
l2 = list->next; | |||
while ((l2 = l2->next) != NULL) { | |||
if ((l2 = l2->next) == NULL) | |||
break; | |||
l1 = l1->next; | |||
} | |||
l2 = l1->next; | |||
l1->next = NULL; | |||
return jack_slist_sort_merge (jack_slist_sort (list, compare_func), | |||
jack_slist_sort (l2, compare_func), | |||
compare_func); | |||
} | |||
#endif /* __jack_jslist_h__ */ |
@@ -192,7 +192,7 @@ INLINE_INFO = YES | |||
# alphabetically by member name. If set to NO the members will appear in | |||
# declaration order. | |||
SORT_MEMBER_DOCS = YES | |||
SORT_MEMBER_DOCS = NO | |||
# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC | |||
# tag is set to YES, then doxygen will reuse the documentation of the first | |||
@@ -304,7 +304,7 @@ WARN_LOGFILE = | |||
# directories like "/usr/src/myproject". Separate the files or directories | |||
# with spaces. | |||
INPUT = common macosx linux/alsa windows | |||
INPUT = common macosx linux/alsa windows common/jack/control.h | |||
# If the value of the INPUT tag contains directories, you can use the | |||
# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp | |||
@@ -82,3 +82,6 @@ if env['BUILD_EXAMPLES']: | |||
if clientenv['INSTALL_EXAMPLES']: | |||
env.InstallAs(env['INSTALL_ADDON_DIR'] + '/' + example_lib + '.so', lib) | |||
env.Alias('install', env['INSTALL_ADDON_DIR'] + '/' + example_lib + '.so') | |||
if env['ENABLE_DBUS']: | |||
clientenv.Install(env['BINDIR'], 'jack_control') |
@@ -435,7 +435,7 @@ JackAlsaDriver::alsa_driver_configure_stream (alsa_driver_t *driver, char *devic | |||
handle, hw_params, formats[format].format)) < 0) { | |||
if ((sample_width == 4 | |||
? format++ >= NUMFORMATS - 1 | |||
? format++ >= (int)NUMFORMATS - 1 | |||
: format-- <= 0)) { | |||
jack_error ("Sorry. The audio interface \"%s\"" | |||
" doesn't support any of the" | |||
@@ -450,7 +450,7 @@ JackAlsaDriver::alsa_driver_configure_stream (alsa_driver_t *driver, char *devic | |||
} 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; | |||
} | |||
} | |||
@@ -524,7 +524,7 @@ JackAlsaDriver::alsa_driver_configure_stream (alsa_driver_t *driver, char *devic | |||
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)) { | |||
@@ -1782,6 +1782,11 @@ JackAlsaDriver::alsa_driver_delete (alsa_driver_t *driver) | |||
driver->ctl_handle = 0; | |||
} | |||
if (driver->ctl_handle) { | |||
snd_ctl_close (driver->ctl_handle); | |||
driver->ctl_handle = 0; | |||
} | |||
if (driver->capture_handle) { | |||
snd_pcm_close (driver->capture_handle); | |||
driver->capture_handle = 0; | |||
@@ -2159,7 +2164,7 @@ int JackAlsaDriver::Attach() | |||
// Monitor ports | |||
if (fWithMonitorPorts) { | |||
jack_log("Create monitor port "); | |||
snprintf(name, sizeof(name) - 1, "%s:monitor_%lu", fClientControl->fName, i + 1); | |||
snprintf(name, sizeof(name) - 1, "%s:monitor_%d", fClientControl->fName, i + 1); | |||
if ((port_index = fGraphManager->AllocatePort(fClientControl->fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, fEngineControl->fBufferSize)) == NO_PORT) { | |||
jack_error ("ALSA: cannot register monitor port for %s", name); | |||
} else { | |||
@@ -2713,7 +2718,6 @@ extern "C" | |||
case 'X': | |||
midi_driver = strdup(param->value.str); | |||
break; | |||
} | |||
} | |||
@@ -22,6 +22,8 @@ | |||
#ifdef __cplusplus | |||
extern "C" | |||
{ | |||
#else | |||
#include <stdbool.h> | |||
#endif | |||
typedef struct alsa_midi_t alsa_midi_t; | |||
@@ -67,17 +67,15 @@ extern "C" | |||
#if defined(STANDALONE) | |||
#define MESSAGE(...) fprintf(stderr, __VA_ARGS__) | |||
#elif defined(JACKMP) | |||
#define MESSAGE(...) fprintf(stderr, __VA_ARGS__) ; fprintf(stderr, "\n") | |||
#else | |||
#elif !defined(JACKMP) | |||
#include <jack/messagebuffer.h> | |||
#endif | |||
#define info_log(...) MESSAGE(__VA_ARGS__) | |||
#define error_log(...) MESSAGE(__VA_ARGS__) | |||
#define info_log(...) jack_info(__VA_ARGS__) | |||
#define error_log(...) jack_error(__VA_ARGS__) | |||
#ifdef DEBUG | |||
#define debug_log(...) MESSAGE(__VA_ARGS__) | |||
#ifdef ALSA_MIDI_DEBUG | |||
#define debug_log(...) jack_info(__VA_ARGS__) | |||
#else | |||
#define debug_log(...) | |||
#endif | |||
@@ -35,6 +35,7 @@ | |||
#include "alsa_midi_impl.h" | |||
#include "midi_pack.h" | |||
#include "midi_unpack.h" | |||
#include "JackError.h" | |||
enum { | |||
NANOSLEEP_RESOLUTION = 7000 | |||
@@ -628,6 +629,7 @@ void scan_device(scan_t *scan) | |||
alsa_error("scan: snd_ctl_rawmidi_info on subdevice", err); | |||
continue; | |||
} | |||
scan_port_update(scan); | |||
} | |||
} | |||
@@ -665,7 +667,7 @@ midi_port_t** scan_port_add(scan_t *scan, const alsa_id_t *id, midi_port_t **lis | |||
port->next = *list; | |||
*list = port; | |||
error_log("scan: added port %s %s", port->dev, port->name); | |||
info_log("scan: added port %s %s", port->dev, port->name); | |||
return &port->next; | |||
} | |||
@@ -689,7 +691,7 @@ midi_port_t** scan_port_open(alsa_rawmidi_t *midi, midi_port_t **list) | |||
port->state = PORT_ADDED_TO_JACK; | |||
jack_ringbuffer_write(str->jack.new_ports, (char*) &port, sizeof(port)); | |||
error_log("scan: opened port %s %s", port->dev, port->name); | |||
info_log("scan: opened port %s %s", port->dev, port->name); | |||
return &port->next; | |||
fail_2: | |||
@@ -709,7 +711,7 @@ midi_port_t** scan_port_del(alsa_rawmidi_t *midi, midi_port_t **list) | |||
{ | |||
midi_port_t *port = *list; | |||
if (port->state == PORT_REMOVED_FROM_JACK) { | |||
error_log("scan: deleted port %s %s", port->dev, port->name); | |||
info_log("scan: deleted port %s %s", port->dev, port->name); | |||
*list = port->next; | |||
if (port->id.id[2] ) | |||
(midi->out.port_close)(midi, port); | |||
@@ -49,6 +49,7 @@ | |||
#include <ctype.h> | |||
#include "alsa_midi_impl.h" | |||
#include "JackError.h" | |||
#define NSEC_PER_SEC ((int64_t)1000*1000*1000) | |||
@@ -213,6 +213,8 @@ OSStatus JackCoreAudioDriver::MeasureCallback(AudioDeviceID inDevice, | |||
AudioDeviceRemoveIOProc(driver->fDeviceID, MeasureCallback); | |||
jack_log("JackCoreAudioDriver::MeasureCallback called"); | |||
JackMachThread::GetParams(&driver->fEngineControl->fPeriod, &driver->fEngineControl->fComputation, &driver->fEngineControl->fConstraint); | |||
// Setup threadded based log function | |||
set_threaded_log_function(); | |||
return noErr; | |||
} | |||
@@ -245,7 +247,7 @@ OSStatus JackCoreAudioDriver::DeviceNotificationCallback(AudioDeviceID inDevice, | |||
void* inClientData) | |||
{ | |||
JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inClientData; | |||
switch (inPropertyID) { | |||
case kAudioDeviceProcessorOverload: | |||
@@ -33,38 +33,27 @@ env.AppendUnique(CPPPATH=['#/', '#/common']) | |||
test_programs = { | |||
'synchroClient': [ | |||
'testSynchroClient.cpp', | |||
'#/common/JackPosixSemaphore.cpp', | |||
'#/common/JackPosixThread.cpp', | |||
'#/common/JackError.c', | |||
'#/common/JackFifo.cpp' | |||
'testSynchroClient.cpp' | |||
], | |||
'synchroServer': [ | |||
'testSynchroServer.cpp', | |||
'#/common/JackPosixSemaphore.cpp', | |||
'#/common/JackPosixThread.cpp', | |||
'#/common/JackError.c', | |||
'#/common/JackFifo.cpp' | |||
'testSynchroServer.cpp' | |||
], | |||
'synchroServerClient': [ | |||
'testSynchroServerClient.cpp', | |||
'#/common/JackPosixSemaphore.cpp', | |||
'#/common/JackPosixThread.cpp', | |||
'#/common/JackError.c', | |||
'#/common/JackFifo.cpp' | |||
], | |||
'testSynchroServerClient.cpp' | |||
], | |||
'testSem': [ | |||
'testSem.cpp', | |||
'#/common/JackPosixSemaphore.cpp', | |||
'#/common/JackPosixThread.cpp', | |||
'#/common/JackError.c', | |||
'#/common/JackFifo.cpp' | |||
'testSem.cpp' | |||
], | |||
'jack_test': [ | |||
'jack_test.cpp' | |||
], | |||
} | |||
# Libraries to link | |||
extra_libs = {} | |||
for test_program in test_programs: | |||
extra_libs[test_program] = ['jackserver'] | |||
# | |||
# Build section | |||
# | |||
@@ -20,6 +20,7 @@ | |||
#include <stdio.h> | |||
#include <sys/time.h> | |||
#include <stdlib.h> | |||
#include <string.h> | |||
#ifdef __APPLE__ | |||
#include "JackMachSemaphore.h" | |||
@@ -221,6 +221,8 @@ int JackPortAudioDriver::Render(const void* inputBuffer, void* outputBuffer, | |||
driver->fLastWaitUst = GetMicroSeconds(); // Take callback date here | |||
driver->fInputBuffer = (float**)inputBuffer; | |||
driver->fOutputBuffer = (float**)outputBuffer; | |||
// Setup threadded based log function | |||
set_threaded_log_function(); | |||
return (driver->Process() == 0) ? paContinue : paAbort; | |||
} | |||
@@ -62,17 +62,10 @@ class JackWinProcessSync : public JackSyncInterface | |||
void Destroy() | |||
{} | |||
bool TimedWait(long usec) | |||
{ | |||
DWORD res = WaitForSingleObject(fEvent, usec / 1000); | |||
return (res == WAIT_OBJECT_0); | |||
} | |||
void Wait() | |||
{ | |||
WaitForSingleObject(fEvent, INFINITE); | |||
} | |||
bool TimedWait(long usec); | |||
void Wait(); | |||
void SignalAll() | |||
{ | |||
SetEvent(fEvent); | |||
@@ -1,485 +0,0 @@ | |||
/* | |||
Copyright (C) 2001 Paul Davis | |||
Copyright (C) 2004-2006 Grame | |||
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, or | |||
(at your option) any later version. | |||
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 <iostream> | |||
#include <assert.h> | |||
#include <process.h> | |||
#include <getopt.h> | |||
#include <signal.h> | |||
#include "JackServer.h" | |||
#include "JackConstants.h" | |||
#include "driver_interface.h" | |||
#include "JackDriverLoader.h" | |||
#include "shm.h" | |||
using namespace Jack; | |||
static JackServer* fServer; | |||
static char *server_name = "default"; | |||
static int realtime_priority = 10; | |||
static int do_mlock = 1; | |||
static int realtime = 0; | |||
static int loopback = 0; | |||
static int temporary = 0; | |||
static int client_timeout = 0; /* msecs; if zero, use period size. */ | |||
static int do_unlock = 0; | |||
static JSList* drivers = NULL; | |||
static int sync = 0; | |||
static int xverbose = 0; | |||
#define DEFAULT_TMP_DIR "/tmp" | |||
char *jack_tmpdir = DEFAULT_TMP_DIR; | |||
HANDLE waitEvent; | |||
void jack_print_driver_options (jack_driver_desc_t * desc, FILE *file); | |||
void jack_print_driver_param_usage (jack_driver_desc_t * desc, unsigned long param, FILE *file); | |||
int jack_parse_driver_params (jack_driver_desc_t * desc, int argc, char* argv[], JSList ** param_ptr); | |||
static void silent_jack_error_callback (const char *desc) | |||
{} | |||
static void copyright(FILE* file) | |||
{ | |||
fprintf (file, "jackdmp " VERSION "\n" | |||
"Copyright 2001-2005 Paul Davis and others.\n" | |||
"Copyright 2004-2008 Grame.\n" | |||
"jackdmp comes with ABSOLUTELY NO WARRANTY\n" | |||
"This is free software, and you are welcome to redistribute it\n" | |||
"under certain conditions; see the file COPYING for details\n"); | |||
} | |||
static void usage (FILE *file) | |||
{ | |||
copyright (file); | |||
fprintf (file, "\n" | |||
"usage: jackdmp [ --realtime OR -R [ --realtime-priority OR -P priority ] ]\n" | |||
" [ --name OR -n server-name ]\n" | |||
" [ --timeout OR -t client-timeout-in-msecs ]\n" | |||
" [ --loopback OR -L loopback-port-number ]\n" | |||
" [ --verbose OR -v ]\n" | |||
" [ --replace-registry OR -r ]\n" | |||
" [ --silent OR -s ]\n" | |||
" [ --sync OR -S ]\n" | |||
" [ --version OR -V ]\n" | |||
" -d driver [ ... driver args ... ]\n" | |||
" where driver can be `alsa', `coreaudio', 'portaudio' or `dummy'\n" | |||
" jackdmp -d driver --help\n" | |||
" to display options for each driver\n\n"); | |||
} | |||
static int JackStart(jack_driver_desc_t* driver_desc, JSList* driver_params, int sync, int time_out_ms, int rt, int priority, int loopback, int verbose, const char* server_name) | |||
{ | |||
printf("Jackdmp: sync = %ld timeout = %ld rt = %ld priority = %ld verbose = %ld \n", sync, time_out_ms, rt, priority, verbose); | |||
fServer = new JackServer(sync, temporary, time_out_ms, rt, priority, loopback, verbose, server_name); | |||
int res = fServer->Open(driver_desc, driver_params); | |||
return (res < 0) ? res : fServer->Start(); | |||
} | |||
static int JackStop() | |||
{ | |||
fServer->Stop(); | |||
fServer->Close(); | |||
printf("Jackdmp: server close\n"); | |||
delete fServer; | |||
printf("Jackdmp: delete server\n"); | |||
return 0; | |||
} | |||
static int JackDelete() | |||
{ | |||
delete fServer; | |||
printf("Jackdmp: delete server\n"); | |||
return 0; | |||
} | |||
static void intrpt(int signum) | |||
{ | |||
printf("jack main caught signal %d\n", signum); | |||
(void) signal(SIGINT, SIG_DFL); | |||
SetEvent(waitEvent); | |||
} | |||
/* | |||
static char* jack_default_server_name(void) | |||
{ | |||
char *server_name; | |||
if ((server_name = getenv("JACK_DEFAULT_SERVER")) == NULL) | |||
server_name = "default"; | |||
return server_name; | |||
} | |||
// returns the name of the per-user subdirectory of jack_tmpdir | |||
static char* jack_user_dir(void) | |||
{ | |||
static char user_dir[PATH_MAX] = ""; | |||
// format the path name on the first call | |||
if (user_dir[0] == '\0') { | |||
snprintf (user_dir, sizeof (user_dir), "%s/jack-%d", | |||
jack_tmpdir, _getuid ()); | |||
} | |||
return user_dir; | |||
} | |||
// returns the name of the per-server subdirectory of jack_user_dir() | |||
static char* get_jack_server_dir(const char * toto) | |||
{ | |||
static char server_dir[PATH_MAX] = ""; | |||
// format the path name on the first call | |||
if (server_dir[0] == '\0') { | |||
snprintf (server_dir, sizeof (server_dir), "%s/%s", | |||
jack_user_dir (), server_name); | |||
} | |||
return server_dir; | |||
} | |||
static void jack_cleanup_files (const char *server_name) | |||
{ | |||
DIR *dir; | |||
struct dirent *dirent; | |||
char *dir_name = get_jack_server_dir (server_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]; | |||
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)); | |||
} | |||
} | |||
} | |||
*/ | |||
/* | |||
BOOL CtrlHandler( DWORD fdwCtrlType ) | |||
{ | |||
switch( fdwCtrlType ) | |||
{ | |||
// Handle the CTRL-C signal. | |||
case CTRL_C_EVENT: | |||
printf( "Ctrl-C event\n\n" ); | |||
Beep( 750, 300 ); | |||
SetEvent(waitEvent); | |||
return( TRUE ); | |||
// CTRL-CLOSE: confirm that the user wants to exit. | |||
case CTRL_CLOSE_EVENT: | |||
Beep( 600, 200 ); | |||
printf( "Ctrl-Close event\n\n" ); | |||
SetEvent(waitEvent); | |||
return( TRUE ); | |||
// Pass other signals to the next handler. | |||
case CTRL_BREAK_EVENT: | |||
Beep( 900, 200 ); | |||
printf( "Ctrl-Break event\n\n" ); | |||
return FALSE; | |||
case CTRL_LOGOFF_EVENT: | |||
Beep( 1000, 200 ); | |||
printf( "Ctrl-Logoff event\n\n" ); | |||
return FALSE; | |||
case CTRL_SHUTDOWN_EVENT: | |||
Beep( 750, 500 ); | |||
printf( "Ctrl-Shutdown event\n\n" ); | |||
return FALSE; | |||
default: | |||
return FALSE; | |||
} | |||
} | |||
*/ | |||
int main(int argc, char* argv[]) | |||
{ | |||
jack_driver_desc_t * driver_desc; | |||
const char *options = "-ad:P:uvshVRL:STFl:t:mn:"; | |||
struct option long_options[] = { | |||
{ "driver", 1, 0, 'd'}, | |||
{ "verbose", 0, 0, 'v' }, | |||
{ "help", 0, 0, 'h' }, | |||
{ "port-max", 1, 0, 'p' }, | |||
{ "no-mlock", 0, 0, 'm' }, | |||
{ "name", 0, 0, 'n' }, | |||
{ "unlock", 0, 0, 'u' }, | |||
{ "realtime", 0, 0, 'R' }, | |||
{ "replace-registry", 0, 0, 'r' }, | |||
{ "loopback", 0, 0, 'L' }, | |||
{ "realtime-priority", 1, 0, 'P' }, | |||
{ "timeout", 1, 0, 't' }, | |||
{ "temporary", 0, 0, 'T' }, | |||
{ "version", 0, 0, 'V' }, | |||
{ "silent", 0, 0, 's' }, | |||
{ "sync", 0, 0, 'S' }, | |||
{ 0, 0, 0, 0 } | |||
}; | |||
int opt = 0; | |||
int option_index = 0; | |||
int seen_driver = 0; | |||
char *driver_name = NULL; | |||
char **driver_args = NULL; | |||
JSList * driver_params; | |||
int driver_nargs = 1; | |||
int show_version = 0; | |||
int replace_registry = 0; | |||
int sync = 0; | |||
int i; | |||
int rc; | |||
char c; | |||
// Creates wait event | |||
if ((waitEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL) { | |||
printf("CreateEvent fails err = %ld\n", GetLastError()); | |||
return 0; | |||
} | |||
opterr = 0; | |||
while (!seen_driver && | |||
(opt = getopt_long(argc, argv, options, | |||
long_options, &option_index)) != EOF) { | |||
switch (opt) { | |||
case 'd': | |||
seen_driver = 1; | |||
driver_name = optarg; | |||
break; | |||
case 'v': | |||
xverbose = 1; | |||
break; | |||
case 's': | |||
// steph | |||
//jack_set_error_function(silent_jack_error_callback); | |||
break; | |||
case 'S': | |||
sync = 1; | |||
break; | |||
case 'n': | |||
server_name = optarg; | |||
break; | |||
case 'm': | |||
do_mlock = 0; | |||
break; | |||
case 'P': | |||
realtime_priority = atoi(optarg); | |||
break; | |||
case 'r': | |||
replace_registry = 1; | |||
break; | |||
case 'R': | |||
realtime = 1; | |||
break; | |||
case 'L': | |||
loopback = atoi(optarg); | |||
break; | |||
case 'T': | |||
temporary = 1; | |||
break; | |||
case 't': | |||
client_timeout = atoi(optarg); | |||
break; | |||
case 'u': | |||
do_unlock = 1; | |||
break; | |||
case 'V': | |||
show_version = 1; | |||
break; | |||
default: | |||
fprintf(stderr, "unknown option character %c\n", | |||
optopt); | |||
/*fallthru*/ | |||
case 'h': | |||
usage(stdout); | |||
return -1; | |||
} | |||
} | |||
if (!seen_driver) { | |||
usage (stderr); | |||
//exit (1); | |||
return 0; | |||
} | |||
drivers = jack_drivers_load (drivers); | |||
if (!drivers) { | |||
fprintf (stderr, "jackdmp: no drivers found; exiting\n"); | |||
//exit (1); | |||
return 0; | |||
} | |||
driver_desc = jack_find_driver_descriptor (drivers, driver_name); | |||
if (!driver_desc) { | |||
fprintf (stderr, "jackdmp: unknown driver '%s'\n", driver_name); | |||
//exit (1); | |||
return 0; | |||
} | |||
if (optind < argc) { | |||
driver_nargs = 1 + argc - optind; | |||
} else { | |||
driver_nargs = 1; | |||
} | |||
if (driver_nargs == 0) { | |||
fprintf (stderr, "No driver specified ... hmm. JACK won't do" | |||
" anything when run like this.\n"); | |||
return -1; | |||
} | |||
driver_args = (char **) malloc (sizeof (char *) * driver_nargs); | |||
driver_args[0] = driver_name; | |||
for (i = 1; i < driver_nargs; i++) { | |||
driver_args[i] = argv[optind++]; | |||
} | |||
if (jack_parse_driver_params (driver_desc, driver_nargs, | |||
driver_args, &driver_params)) { | |||
// exit (0); | |||
return 0; | |||
} | |||
//if (server_name == NULL) | |||
// server_name = jack_default_server_name (); | |||
copyright (stdout); | |||
rc = jack_register_server (server_name, replace_registry); | |||
switch (rc) { | |||
case EEXIST: | |||
fprintf (stderr, "`%s' server already active\n", server_name); | |||
//exit (1); | |||
return 0; | |||
case ENOSPC: | |||
fprintf (stderr, "too many servers already active\n"); | |||
//exit (2); | |||
return 0; | |||
case ENOMEM: | |||
fprintf (stderr, "no access to shm registry\n"); | |||
//exit (3); | |||
return 0; | |||
default: | |||
if (xverbose) | |||
fprintf (stderr, "server `%s' registered\n", | |||
server_name); | |||
} | |||
/* clean up shared memory and files from any previous | |||
* instance of this server name */ | |||
jack_cleanup_shm(); | |||
// jack_cleanup_files(server_name); | |||
if (!realtime && client_timeout == 0) | |||
client_timeout = 500; /* 0.5 sec; usable when non realtime. */ | |||
int res = JackStart(driver_desc, driver_params, sync, client_timeout, realtime, realtime_priority, loopback, xverbose, server_name); | |||
if (res < 0) { | |||
printf("Cannot start server... exit\n"); | |||
JackDelete(); | |||
return 0; | |||
} | |||
/* | |||
if( SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE ) ) | |||
{ | |||
printf( "\nThe Control Handler is installed.\n" ); | |||
} else { | |||
printf( "\nERROR: Could not set control handler"); | |||
} | |||
*/ | |||
(void) signal(SIGINT, intrpt); | |||
(void) signal(SIGABRT, intrpt); | |||
(void) signal(SIGTERM, intrpt); | |||
if ((res = WaitForSingleObject(waitEvent, INFINITE)) != WAIT_OBJECT_0) { | |||
printf("WaitForSingleObject fails err = %ld\n", GetLastError()); | |||
} | |||
/* | |||
printf("Type 'q' to quit\n"); | |||
while ((c = getchar()) != 'q') {} | |||
*/ | |||
JackStop(); | |||
jack_cleanup_shm(); | |||
// jack_cleanup_files(server_name); | |||
jack_unregister_server(server_name); | |||
CloseHandle(waitEvent); | |||
return 1; | |||
} | |||
@@ -65,7 +65,7 @@ LINK32=link.exe | |||
# PROP Ignore_Export_Lib 0 | |||
# PROP Target_Dir "" | |||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c | |||
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "." /I "../common/" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c | |||
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "." /I "../common/" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c | |||
# ADD BASE RSC /l 0x40c /d "_DEBUG" | |||
# ADD RSC /l 0x40c /d "_DEBUG" | |||
BSC32=bscmake.exe | |||
@@ -41,7 +41,7 @@ RSC=rc.exe | |||
# PROP Intermediate_Dir "Release" | |||
# PROP Target_Dir "" | |||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c | |||
# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I "../common/" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c | |||
# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I "../common/" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c | |||
# ADD BASE RSC /l 0x40c /d "NDEBUG" | |||
# ADD RSC /l 0x40c /d "NDEBUG" | |||
BSC32=bscmake.exe | |||
@@ -95,7 +95,7 @@ SOURCE=.\getopt1.c | |||
# End Source File | |||
# Begin Source File | |||
SOURCE=.\JackdmpWIN32.cpp | |||
SOURCE=..\common\Jackdmp.cpp | |||
# End Source File | |||
# End Group | |||
# Begin Group "Header Files" | |||
@@ -115,7 +115,7 @@ SOURCE=..\common\JackEngineControl.cpp | |||
# End Source File | |||
# Begin Source File | |||
SOURCE=..\common\JackError.c | |||
SOURCE=..\common\JackError.cpp | |||
# End Source File | |||
# Begin Source File | |||
@@ -143,6 +143,10 @@ SOURCE=..\common\JackLibClient.cpp | |||
# End Source File | |||
# Begin Source File | |||
SOURCE=..\common\JackMessageBuffer.cpp | |||
# End Source File | |||
# Begin Source File | |||
SOURCE=..\common\JackMidiAPI.cpp | |||
# End Source File | |||
# Begin Source File | |||
@@ -183,6 +187,10 @@ SOURCE=.\JackWinNamedPipeClientChannel.cpp | |||
# End Source File | |||
# Begin Source File | |||
SOURCE=.\JackWinProcessSync.cpp | |||
# End Source File | |||
# Begin Source File | |||
SOURCE=.\JackWinSemaphore.cpp | |||
# End Source File | |||
# Begin Source File | |||
@@ -124,6 +124,10 @@ SOURCE=..\common\JackConnectionManager.cpp | |||
# End Source File | |||
# Begin Source File | |||
SOURCE=..\common\JackControl.cpp | |||
# End Source File | |||
# Begin Source File | |||
SOURCE=..\common\JackDriver.cpp | |||
# End Source File | |||
# Begin Source File | |||
@@ -140,7 +144,7 @@ SOURCE=..\common\JackEngineControl.cpp | |||
# End Source File | |||
# Begin Source File | |||
SOURCE=..\common\JackError.c | |||
SOURCE=..\common\JackError.cpp | |||
# End Source File | |||
# Begin Source File | |||
@@ -176,6 +180,10 @@ SOURCE=..\common\JackLoopbackDriver.cpp | |||
# End Source File | |||
# Begin Source File | |||
SOURCE=..\common\JackMessageBuffer.cpp | |||
# End Source File | |||
# Begin Source File | |||
SOURCE=..\common\JackMidiAPI.cpp | |||
# End Source File | |||
# Begin Source File | |||
@@ -244,6 +252,10 @@ SOURCE=.\JackWinNamedPipeServerNotifyChannel.cpp | |||
# End Source File | |||
# Begin Source File | |||
SOURCE=.\JackWinProcessSync.cpp | |||
# End Source File | |||
# Begin Source File | |||
SOURCE=.\JackWinSemaphore.cpp | |||
# End Source File | |||
# Begin Source File | |||