Browse Source

New libjacknet library with net.h and JackNetAPI.cpp files. New netmaster.c and netmaster.c examples.

git-svn-id: http://subversion.jackaudio.org/jack/jack2/branches/libjacknet@3337 0c269be4-1314-0410-8aa9-9f06e86f4224
tags/1.9.8
sletz 16 years ago
parent
commit
926a25f6c6
7 changed files with 1691 additions and 1 deletions
  1. +4
    -0
      ChangeLog
  2. +1029
    -0
      common/JackNetAPI.cpp
  3. +300
    -0
      common/jack/net.h
  4. +25
    -0
      common/wscript
  5. +165
    -0
      example-clients/netmaster.c
  6. +160
    -0
      example-clients/netslave.c
  7. +8
    -1
      example-clients/wscript

+ 4
- 0
ChangeLog View File

@@ -23,6 +23,10 @@ Michael Voigt
Jackdmp changes log
---------------------------

2009-02-24 Stephane Letz <letz@grame.fr>
* New libjacknet library with net.h and JackNetAPI.cpp files. New netmaster.c and netmaster.c examples.

2009-02-23 Stephane Letz <letz@grame.fr>
* Another fix in systemdeps.h and types.h: jack_time_t now uniquely defined in types.h.


+ 1029
- 0
common/JackNetAPI.cpp
File diff suppressed because it is too large
View File


+ 300
- 0
common/jack/net.h View File

@@ -0,0 +1,300 @@
/*
Copyright (C) 2009 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 __net_h__
#define __net_h__

#ifdef __cplusplus
extern "C"
{
#endif

#include <jack/systemdeps.h>
#include <jack/types.h>

#define DEFAULT_MULTICAST_IP "225.3.19.154"
#define DEFAULT_PORT 19000
#define DEFAULT_MTU 1500
#define MASTER_NAME_SIZE 256

#define SOCKET_ERROR -1

enum JackNetMode {

JackFastMode = 'f',
JackNormalMode = 'n',
JackSlowMode = 's',
};
typedef struct {
int audio_input;
int audio_output;
int midi_input;
int midi_ouput;
int mtu;
int time_out; // in millisecond, -1 means in infinite
char mode;

} jack_slave_t;

typedef struct {
jack_nframes_t buffer_size;
jack_nframes_t sample_rate;
char master_name[MASTER_NAME_SIZE];

} jack_master_t;

/**
* jack_net_t is an opaque type. You may only access it using the
* API provided.
*/
typedef struct _jack_net_slave jack_net_slave_t;

/**
* Open a network connection with the master machine.
* @param ip the multicast address of the master
* @param port the connection port
* @param request a connection request structure
* @param result a connection result structure
*
* @return Opaque net handle if successful or NULL in case of error.
*/
jack_net_slave_t* jack_net_slave_open(const char* ip, int port, const char* name, jack_slave_t* request, jack_master_t* result);

/**
* Close the network connection with the master machine.
* @param net the network connection to be closed
*
* @return 0 on success, otherwise a non-zero error code
*/
int jack_net_slave_close(jack_net_slave_t* net);

/**
* Prototype for Process callback.
* @param nframes buffer size
* @param audio_input number of audio inputs
* @param audio_input_buffer an array of audio input buffers
* @param midi_input number of MIDI inputs
* @param midi_input_buffer an array of MIDI input buffers
* @param audio_output number of audio outputs
* @param audio_output_buffer an array of audio output buffers
* @param midi_output number of MIDI outputs
* @param midi_output_buffer an array of MIDI output buffers
* @param arg pointer to a client supplied structure supplied by jack_set_net_process_callback().
*
* @return zero on success, non-zero on error
*/
typedef int (* JackNetSlaveProcessCallback) (jack_nframes_t buffer_size,
int audio_input,
float** audio_input_buffer,
int midi_input,
void** midi_input_buffer,
int audio_output,
float** audio_output_buffer,
int midi_output,
void** midi_output_buffer,
void* data);

/**
* Set network process callback.
* @param net the network connection
* @param net_callback the process callback
* @param arg pointer to a client supplied structure
*
* @return 0 on success, otherwise a non-zero error code
*/
int jack_set_net_slave_process_callback(jack_net_slave_t * net, JackNetSlaveProcessCallback net_callback, void *arg);

/**
* Start processing thread, the net_callback will start to be called.
* @param net the network connection
*
* @return 0 on success, otherwise a non-zero error code
*/
int jack_net_slave_activate(jack_net_slave_t* net);

/**
* Stop processing thread.
* @param net the network connection
*
* @return 0 on success, otherwise a non-zero error code
*/
int jack_net_slave_deactivate(jack_net_slave_t* net);

/**
* Prototype for BufferSize callback.
* @param nframes buffer size
* @param arg pointer to a client supplied structure supplied by jack_set_net_buffer_size_callback().
*
* @return zero on success, non-zero on error
*/
typedef int (*JackNetSlaveBufferSizeCallback)(jack_nframes_t nframes, void *arg);

/**
* Prototype for SampleRate callback
* @param nframes sample rate
* @param arg pointer to a client supplied structure supplied by jack_set_net_sample_rate_callback().
*
* @return zero on success, non-zero on error
*/
typedef int (*JackNetSlaveSampleRateCallback)(jack_nframes_t nframes, void *arg);

/**
* Set network buffer size callback.
* @param net the network connection
* @param bufsize_callback the buffer size callback
* @param arg pointer to a client supplied structure
*
* @return 0 on success, otherwise a non-zero error code
*/
int jack_set_net_slave_buffer_size_callback(jack_net_slave_t *net, JackNetSlaveBufferSizeCallback bufsize_callback, void *arg);

/**
* Set network sample rate callback.
* @param net the network connection
* @param samplerate_callback the sample rate callback
* @param arg pointer to a client supplied structure
*
* @return 0 on success, otherwise a non-zero error code
*/
int jack_set_net_slave_sample_rate_callback(jack_net_slave_t *net, JackNetSlaveSampleRateCallback samplerate_callback, void *arg);

/**
* Prototype for server Shutdown callback (if not set, the client will just restart, waiting for an available master again.)
* @param arg pointer to a client supplied structure supplied by jack_set_net_shutdown_callback().
*/
typedef void (*JackNetSlaveShutdownCallback)(void* data);

/**
* Set network shutdown callback.
* @param net the network connection
* @param shutdown_callback the shutdown callback
* @param arg pointer to a client supplied structure
*
* @return 0 on success, otherwise a non-zero error code
*/
int jack_set_net_slave_shutdown_callback(jack_net_slave_t *net, JackNetSlaveShutdownCallback shutdown_callback, void *arg);

/**
* jack_net_t is an opaque type. You may only access it using the
* API provided.
*/
typedef struct _jack_net_master jack_net_master_t;
/**
* Open a network connection with the slave machine.
* @param ip the multicast address of the master
* @param port the connection port
* @param request a connection request structure
* @param result a connection result structure
*
* @return Opaque net handle if successful or NULL in case of error.
*/
jack_net_master_t* jack_net_master_open(const char* ip, int port, const char* name, jack_master_t* request, jack_slave_t* result);

/**
* Close the network connection with the master machine.
* @param net the network connection to be closed
*
* @return 0 on success, otherwise a non-zero error code
*/
int jack_net_master_close(jack_net_master_t* net);
/**
* Receive sync and data from the network
* @param net the network connection
* @param audio_input number of audio inputs
* @param audio_input_buffer an array of audio input buffers
* @param midi_input number of MIDI inputs
* @param midi_input_buffer an array of MIDI input buffers
*
* @return zero on success, non-zero on error
*/
int jack_net_master_recv(jack_net_master_t* net, int audio_input, float** audio_input_buffer, int midi_input, void** midi_input_buffer);

/**
* Send sync and data to the network
* @param net the network connection
* @param audio_output number of audio ouputs
* @param audio_output_buffer an array of audio output buffers
* @param midi_output number of MIDI ouputs
* @param midi_output_buffer an array of MIDI output buffers
*
* @return zero on success, non-zero on error
*/
int jack_net_master_send(jack_net_master_t* net, int audio_output, float** audio_output_buffer, int midi_output, void** midi_output_buffer);

// Experimental Adapter API

/**
* jack_adapter_t is an opaque type. You may only access it using the
* API provided.
*/
typedef struct _jack_adapter jack_adapter_t;

/**
* Create an adapter.
*
* @return 0 on success, otherwise a non-zero error code
*/
jack_adapter_t* jack_create_adapter(jack_nframes_t buffer_size, jack_nframes_t sample_rate);

/**
* Destroy an adapter.
*
* @return 0 on success, otherwise a non-zero error code
*/
int jack_destroy_adapter(jack_adapter_t* adapter);

/**
* Push input to ringbuffer
*
* @return 0 on success, otherwise a non-zero error code
*/
int jack_adapter_push_input(jack_adapter_t * adapter, int channels, float** buffers);

/**
* Pull input from ringbuffer
*
* @return 0 on success, otherwise a non-zero error code
*/
int jack_adapter_pull_input(jack_adapter_t * adapter, int channels, float** buffers);
/**
* Push output to ringbuffer
*
* @return error code.
*/
int jack_adapter_push_output(jack_adapter_t * adapter, int channels, float** buffers);

/**
* Pull output from ringbuffer
*
* @return 0 on success, otherwise a non-zero error code
*/
int jack_adapter_pull_output(jack_adapter_t * adapter, int channels, float** buffers);


#ifdef __cplusplus
}
#endif

#endif /* __net_h__ */

+ 25
- 0
common/wscript View File

@@ -173,6 +173,31 @@ def build(bld):
if bld.env['IS_SUN']:
serverlib.env.append_value("LINKFLAGS", "-lnsl -lsocket")

netlib = bld.new_task_gen('cxx', 'shlib')
netlib.features.append('cc')
netlib.defines = ['HAVE_CONFIG_H','SERVER_SIDE']
netlib.includes = includes
netlib.name = 'netlib'
netlib.target = 'jacknet'
netlib.uselib = uselib
netlib.install_path = '${LIBDIR}'
netlib.source = ['JackNetAPI.cpp', 'JackNetInterface.cpp', 'JackNetTool.cpp', 'JackAudioAdapterInterface.cpp', 'JackResampler.cpp', 'ringbuffer.c']

if bld.env['IS_LINUX']:
netlib.source += ['./posix/JackNetUnixSocket.cpp','./posix/JackPosixThread.cpp']
netlib.env.append_value("CPPFLAGS", "-fvisibility=hidden")

if bld.env['IS_SUN']:
netlib.source += ['./posix/JackNetUnixSocket.cpp','./posix/JackPosixThread.cpp']
netlib.env.append_value("CPPFLAGS", "-fvisibility=hidden")

if bld.env['IS_MACOSX']:
netlib.source += ['../posix/JackNetUnixSocket.cpp','../posix/JackPosixThread.cpp', '../macosx/JackMachThread.cpp', '../macosx/JackMachTime.c']
netlib.env.append_value("LINKFLAGS", "-framework CoreAudio -single_module")

netlib.vnum = bld.env['JACK_API_VERSION']

clientlib = bld.new_task_gen('cxx', 'shlib')
clientlib.features.append('cc')
clientlib.defines = 'HAVE_CONFIG_H'


+ 165
- 0
example-clients/netmaster.c View File

@@ -0,0 +1,165 @@
/*
Copyright (C) 2009 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 <stdlib.h>
#include <stdio.h>
#include <errno.h>
#ifndef WIN32
#include <unistd.h>
#endif
#include <math.h>
#include <signal.h>
#include <getopt.h>
#include <string.h>

#include <jack/net.h>

jack_net_master_t* net;

#define BUFFER_SIZE 512
#define SAMPLE_RATE 44100

static void signal_handler(int sig)
{
jack_net_master_close(net);
fprintf(stderr, "signal received, exiting ...\n");
exit(0);
}

static void
usage ()
{
fprintf (stderr, "\n"
"usage: jack_net_master \n"
" [ -b buffer size (default = %d) ]\n"
" [ -r sample rate (default = %d) ]\n"
" [ -a hostname (default = %s) ]\n"
" [ -p port (default = %d) ]\n", BUFFER_SIZE, SAMPLE_RATE, DEFAULT_MULTICAST_IP, DEFAULT_PORT);
}

int
main (int argc, char *argv[])
{
int buffer_size = BUFFER_SIZE;
int sample_rate = SAMPLE_RATE;
int port = DEFAULT_PORT;
char* multicast_ip = DEFAULT_MULTICAST_IP;
const char *options = "b:r:a:p:";
int option_index;
int opt;
struct option long_options[] =
{
{"buffer size", 1, 0, 'b'},
{"sample rate", 1, 0, 'r'},
{"hostname", 1, 0, 'a'},
{"port", 1, 0, 'p'},
{0, 0, 0, 0}
};
while ((opt = getopt_long (argc, argv, options, long_options, &option_index)) != EOF) {
switch (opt) {
case 'b':
buffer_size = atoi(optarg);
break;
case 'r':
sample_rate = atoi(optarg);
break;
case 'a':
multicast_ip = strdup(optarg);
break;
case 'p':
port = atoi(optarg);
break;
case 'h':
usage();
return -1;
}
}
int i;
jack_master_t request = { buffer_size, sample_rate, "master" };
jack_slave_t result;
float** audio_input_buffer;
float** audio_output_buffer;
int wait_usec = (int) ((((float)buffer_size) * 1000000) / ((float)sample_rate));
printf("Waiting for a slave...\n");

if ((net = jack_net_master_open(DEFAULT_MULTICAST_IP, DEFAULT_PORT, "net_master", &request, &result)) == 0) {
fprintf(stderr, "jack server not running?\n");
return 1;
}
/* install a signal handler to properly quits jack client */
#ifdef WIN32
signal(SIGINT, signal_handler);
signal(SIGABRT, signal_handler);
signal(SIGTERM, signal_handler);
#else
signal(SIGQUIT, signal_handler);
signal(SIGTERM, signal_handler);
signal(SIGHUP, signal_handler);
signal(SIGINT, signal_handler);
#endif
// Allocate buffers
audio_input_buffer = calloc(result.audio_input, sizeof(float*));
for (i = 0; i < result.audio_input; i++) {
audio_input_buffer[i] = calloc(buffer_size, sizeof(float));
}
audio_output_buffer = calloc(result.audio_output, sizeof(float*));
for (i = 0; i < result.audio_output; i++) {
audio_output_buffer[i] = calloc(buffer_size, sizeof(float));
}

// Run until interrupted
while (1) {
// Copy input to output
for (i = 0; i < result.audio_input; i++) {
memcpy(audio_output_buffer[i], audio_input_buffer[i], buffer_size * sizeof(float));
}
jack_net_master_send(net, result.audio_output, audio_output_buffer, 0, NULL);
jack_net_master_recv(net, result.audio_input, audio_input_buffer, 0, NULL);
usleep(wait_usec);
};
// Wait for application end
jack_net_master_close(net);
for (i = 0; i < result.audio_input; i++) {
free(audio_input_buffer[i]);
}
free(audio_input_buffer);
for (i = 0; i < result.audio_output; i++) {
free(audio_output_buffer[i]);
}
free(audio_output_buffer);
exit (0);
}

+ 160
- 0
example-clients/netslave.c View File

@@ -0,0 +1,160 @@
/*
Copyright (C) 2009 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 <stdlib.h>
#include <stdio.h>
#include <errno.h>
#ifndef WIN32
#include <unistd.h>
#endif
#include <math.h>
#include <signal.h>
#include <getopt.h>
#include <string.h>

#include <jack/net.h>

jack_net_slave_t* net;

static void signal_handler(int sig)
{
jack_net_slave_close(net);
fprintf(stderr, "signal received, exiting ...\n");
exit(0);
}

static void
usage ()
{
fprintf (stderr, "\n"
"usage: jack_net_slave \n"
" [ -C capture channels (default = 2)]\n"
" [ -P playback channels (default = 2) ]\n"
" [ -a hostname (default = %s) ]\n"
" [ -p port (default = %d)]\n", DEFAULT_MULTICAST_IP, DEFAULT_PORT);
}


static int net_process(jack_nframes_t buffer_size,
int audio_input,
float** audio_input_buffer,
int midi_input,
void** midi_input_buffer,
int audio_output,
float** audio_output_buffer,
int midi_output,
void** midi_output_buffer,
void* data)
{
int i;
// Copy input to output
for (i = 0; i < audio_input; i++) {
memcpy(audio_output_buffer[i], audio_input_buffer[i], buffer_size * sizeof(float));
}
return 0;
}

int
main (int argc, char *argv[])
{
int audio_input = 2;
int audio_output = 2;
int port = DEFAULT_PORT;
char* multicast_ip = DEFAULT_MULTICAST_IP;
const char *options = "C:P:a:p:";
int option_index;
int opt;
struct option long_options[] =
{
{"audio input", 1, 0, 'C'},
{"audio output", 1, 0, 'P'},
{"hostname", 1, 0, 'a'},
{"port", 1, 0, 'p'},
{0, 0, 0, 0}
};
while ((opt = getopt_long (argc, argv, options, long_options, &option_index)) != EOF) {
switch (opt) {
case 'C':
audio_input = atoi(optarg);
break;
case 'P':
audio_output = atoi(optarg);
break;
case 'a':
multicast_ip = strdup(optarg);
break;
case 'p':
port = atoi(optarg);
break;
case 'h':
usage();
return -1;
}
}

jack_slave_t request = { audio_input, audio_output, 0, 0, DEFAULT_MTU, -1, JackSlowMode };
jack_master_t result;
printf("Waiting for a master...\n");

if ((net = jack_net_slave_open(DEFAULT_MULTICAST_IP, DEFAULT_PORT, "net_slave", &request, &result)) == 0) {
fprintf(stderr, "jack server not running?\n");
return 1;
}

jack_set_net_slave_process_callback(net, net_process, NULL);
if (jack_net_slave_activate(net) != 0) {
fprintf(stderr, "Cannot sactivate client\n");
return 1;
}
/* install a signal handler to properly quits jack client */
#ifdef WIN32
signal(SIGINT, signal_handler);
signal(SIGABRT, signal_handler);
signal(SIGTERM, signal_handler);
#else
signal(SIGQUIT, signal_handler);
signal(SIGTERM, signal_handler);
signal(SIGHUP, signal_handler);
signal(SIGINT, signal_handler);
#endif

/* run until interrupted */
while (1) {
#ifdef WIN32
Sleep(1000);
#else
sleep(1);
#endif
};
// Wait for application end
jack_net_slave_deactivate(net);
jack_net_slave_close(net);
exit (0);
}

+ 8
- 1
example-clients/wscript View File

@@ -21,6 +21,8 @@ example_programs = {
'jack_thru' : 'thru_client.c',
'jack_cpu_load' : 'cpu_load.c',
'jack_server_control' : 'server_control.cpp',
'jack_net_slave' : 'netslave.c',
'jack_net_master' : 'netmaster.c',
}

example_libs = {
@@ -69,8 +71,13 @@ def build(bld):
prog.env.append_value("LINKFLAGS", "-lm")
if example_program == 'jack_server_control':
prog.uselib_local = 'serverlib'
elif example_program == 'jack_net_slave':
prog.uselib_local = 'netlib'
elif example_program == 'jack_net_master':
prog.uselib_local = 'netlib'
else:
prog.uselib_local = 'clientlib'
prog.uselib_local = 'clientlib'
prog.target = example_program
#if bld.env['BUILD_EXAMPLE_CLIENT_TRANSPORT']


Loading…
Cancel
Save