Commit 926a25f6 authored by sletz's avatar sletz
Browse files

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

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
parent 22add8c3
......@@ -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.
......
This diff is collapsed.
/*
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__ */
......@@ -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'
......
/*
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);
}
/*
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 = {