emitter and receptor confirmed to work. emitter only works with alsa backend

This commit is contained in:
Benoit Quiniou 2017-08-16 09:39:00 +02:00
parent 57beb269c7
commit 8fb752a0f8
4 changed files with 74 additions and 23 deletions

View File

@ -6,7 +6,7 @@ vban - Linux command-line VBAN tools
vban project is an open-source implementation of VBAN protocol. vban project is an open-source implementation of VBAN protocol.
VBAN is a simple audio over UDP protocol proposed by VB-Audio, see [VBAN Audio webpage](http://vb-audio.pagesperso-orange.fr/Voicemeeter/vban.htm). VBAN is a simple audio over UDP protocol proposed by VB-Audio, see [VBAN Audio webpage](http://vb-audio.pagesperso-orange.fr/Voicemeeter/vban.htm).
It is composed of several command-line tools allowing to stream audio coming from audio backend interfaces to VBAN stream (vban_emitter) or playout incoming VBAN stream to audio backend interfaces (vban_receptor) It is composed of several command-line tools allowing to stream audio coming from audio backend interfaces to VBAN stream (vban_emitter) or playout incoming VBAN stream to audio backend interfaces (vban_receptor)
Up to now, Alsa, PulseAudio and Jack audio backends have been implemented. A fifo (pipe) output is also existing, to allow chaining command-line tools, its status is experimental. Up to now, Alsa, PulseAudio and Jack audio backends have been implemented. A fifo (pipe) output is also existing, to allow chaining command-line tools, and a file output too (writing raw pcm data).
Compilation and installation Compilation and installation
---------------------------- ----------------------------
@ -20,9 +20,9 @@ Usual package names are:
vban is distributed with autotools build scripts, therefore, to build, you need to invoke: vban is distributed with autotools build scripts, therefore, to build, you need to invoke:
$ ./autogen.sh # probably only once for ever $ ./autogen.sh # probably only once for ever
$ ./configure # with or without options (--help to get the list of possible options) $ ./configure # with or without options (--help to get the list of possible options)
$ make # with or without options $ make # with or without options
To install, simply invoke: To install, simply invoke:
@ -38,19 +38,37 @@ Usage
Invoking vban_receptor or vban_emitter without any parameter will give hints on how to use them : Invoking vban_receptor or vban_emitter without any parameter will give hints on how to use them :
Usage: vban_receptor [OPTIONS]... Usage: vban [OPTIONS]...
-i, --ipaddress=IP : MANDATORY. ipaddress to get stream from -i, --ipaddress=IP : MANDATORY. ipaddress to get stream from
-p, --port=PORT : MANDATORY. port to listen to -p, --port=PORT : MANDATORY. port to listen to
-s, --streamname=NAME : MANDATORY. streamname to play -s, --streamname=NAME : MANDATORY. streamname to play
-b, --backend=TYPE : audio backend to use. possible values: alsa, pulseaudio, jack and pipe (EXPERIMENTAL). default is first in this list that is actually compiled -b, --backend=TYPE : audio backend to use. Available audio backends are: alsa pulseaudio jack pipe file . default is alsa.
-q, --quality=ID : network quality indicator from 0 (low latency) to 4. default is 1 -q, --quality=ID : network quality indicator from 0 (low latency) to 4. default is 1
-c, --channels=LIST : channels from the stream to use. LIST is of form x,y,z,... default is to forward the stream as it is -c, --channels=LIST : TEMPORARY DISABLED
-o, --output=NAME : Output device (server for jack backend) name , (as given by "aplay -L" output for alsa). using backend's default by default. not used for jack or pipe -o, --output=NAME : DEPRECATED. please use -d
-d, --debug=LEVEL : Log level, from 0 (FATAL) to 4 (DEBUG). default is 1 (ERROR) -d, --device=NAME : Audio device name. This is file name for file backend, server name for jack backend, device for alsa, stream_name for pulseaudio.
-l, --loglevel=LEVEL : Log level, from 0 (FATAL) to 4 (DEBUG). default is 1 (ERROR)
-h, --help : display this message -h, --help : display this message
TODO: missing vban_emitter doc Usage: vban_emitter [OPTIONS]...
-i, --ipaddress=IP : MANDATORY. ipaddress to send stream to
-p, --port=PORT : MANDATORY. port to use
-s, --streamname=NAME : MANDATORY. streamname to use
-b, --backend=TYPE : TEMPORARY DISABLED. audio backend to use. Only alsa backend is working at this time
-d, --device=NAME : Audio device name. This is file name for file backend, server name for jack backend, device for alsa, stream_name for pulseaudio.
-r, --rate=VALUE : Audio device sample rate. default 44100
-n, --nbchannels=VALUE : Audio device number of channels. default 2
-f, --format=VALUE : Audio device sample format (see below). default is 16I (16bits integer)
-c, --channels=LIST : TEMPORARY DISABLED.
-l, --loglevel=LEVEL : Log level, from 0 (FATAL) to 4 (DEBUG). default is 1 (ERROR)
-h, --help : display this message
Recognized bit format are 8I, 16I, 24I, 32I, 32F, 64F, 12I, 10I
Temporarily disabled
--------------------
About --channels option, a bit more tips: About --channels option, a bit more tips:
* channels indexes are from 1 to 256 (as specified by VBAN specifications for vban_receptor, and well, its probably enough for any soundcard or jack configuration) * channels indexes are from 1 to 256 (as specified by VBAN specifications for vban_receptor, and well, its probably enough for any soundcard or jack configuration)
@ -63,4 +81,4 @@ Examples:
vban_receptor -i IP -p PORT -s STREAMNAME -c1 # keep only channel 1 and play out as mono vban_receptor -i IP -p PORT -s STREAMNAME -c1 # keep only channel 1 and play out as mono
vban_receptor -i IP -p PORT -s STREAMNAME -c1,1,1,1 # keep only channel 1 and play it out on 4 output channels (given that your output device is able to do it) vban_receptor -i IP -p PORT -s STREAMNAME -c1,1,1,1 # keep only channel 1 and play it out on 4 output channels (given that your output device is able to do it)
vban_receptor -i IP -p PORT -s STREAMNAME -c2,41,125,7,1,45 # select some channels and play them out on 6 output channels (same comment) vban_receptor -i IP -p PORT -s STREAMNAME -c2,41,125,7,1,45 # select some channels and play them out on 6 output channels (same comment)
vban_emitter -i IP -p PORT -s STREAMNAME -c1,1,1,1 # use audio source channel 1 (opening it in mono therefore, and build up a 4 channels stream with copies of the same data in all channels) vban_emitter -i IP -p PORT -s STREAMNAME -c1,1,1,1 # use audio source channel 1 (opening it in mono therefore, and build up a 4 channels stream with copies of the same data in all channels)

View File

@ -10,9 +10,10 @@ struct pulseaudio_backend_t
pa_simple* pulseaudio_handle; pa_simple* pulseaudio_handle;
}; };
static int pulseaudio_open(audio_backend_handle_t handle, char const* output_name, enum audio_direction direction, size_t buffer_size, struct stream_config_t const* config); static int pulseaudio_open(audio_backend_handle_t handle, char const* device_name, enum audio_direction direction, size_t buffer_size, struct stream_config_t const* config);
static int pulseaudio_close(audio_backend_handle_t handle); static int pulseaudio_close(audio_backend_handle_t handle);
static int pulseaudio_write(audio_backend_handle_t handle, char const* data, size_t size); static int pulseaudio_write(audio_backend_handle_t handle, char const* data, size_t size);
static int pulseaudio_read(audio_backend_handle_t handle, char* data, size_t size);
static enum pa_sample_format vban_to_pulseaudio_format(enum VBanBitResolution bit_resolution) static enum pa_sample_format vban_to_pulseaudio_format(enum VBanBitResolution bit_resolution)
{ {
@ -59,6 +60,7 @@ int pulseaudio_backend_init(audio_backend_handle_t* handle)
pulseaudio_backend->parent.open = pulseaudio_open; pulseaudio_backend->parent.open = pulseaudio_open;
pulseaudio_backend->parent.close = pulseaudio_close; pulseaudio_backend->parent.close = pulseaudio_close;
pulseaudio_backend->parent.write = pulseaudio_write; pulseaudio_backend->parent.write = pulseaudio_write;
pulseaudio_backend->parent.read = pulseaudio_read;
*handle = (audio_backend_handle_t)pulseaudio_backend; *handle = (audio_backend_handle_t)pulseaudio_backend;
@ -66,7 +68,7 @@ int pulseaudio_backend_init(audio_backend_handle_t* handle)
} }
int pulseaudio_open(audio_backend_handle_t handle, char const* output_name, enum audio_direction direction, size_t buffer_size, struct stream_config_t const* config) int pulseaudio_open(audio_backend_handle_t handle, char const* device_name, enum audio_direction direction, size_t buffer_size, struct stream_config_t const* config)
{ {
int ret; int ret;
struct pulseaudio_backend_t* const pulseaudio_backend = (struct pulseaudio_backend_t*)handle; struct pulseaudio_backend_t* const pulseaudio_backend = (struct pulseaudio_backend_t*)handle;
@ -92,7 +94,8 @@ int pulseaudio_open(audio_backend_handle_t handle, char const* output_name, enum
return -EINVAL; return -EINVAL;
} }
pulseaudio_backend->pulseaudio_handle = pa_simple_new(0, "vban", PA_STREAM_PLAYBACK, (output_name[0] == '\0') ? 0 : output_name, "", &ss, 0, &ba, &ret); pulseaudio_backend->pulseaudio_handle = pa_simple_new(0, "vban", (direction == AUDIO_OUT) ? PA_STREAM_PLAYBACK : PA_STREAM_RECORD, (device_name[0] == '\0') ? 0 : device_name,
(direction == AUDIO_OUT) ? "playback": "record", &ss, 0, (direction == AUDIO_OUT) ? &ba : 0, &ret);
if (pulseaudio_backend->pulseaudio_handle == 0) if (pulseaudio_backend->pulseaudio_handle == 0)
{ {
logger_log(LOG_FATAL, "pulseaudio_open: open error: %s", pa_strerror(ret)); logger_log(LOG_FATAL, "pulseaudio_open: open error: %s", pa_strerror(ret));
@ -152,3 +155,30 @@ int pulseaudio_write(audio_backend_handle_t handle, char const* data, size_t siz
return (ret < 0) ? ret : size; return (ret < 0) ? ret : size;
} }
int pulseaudio_read(audio_backend_handle_t handle, char* data, size_t size)
{
int ret = 0;
int error;
struct pulseaudio_backend_t* const pulseaudio_backend = (struct pulseaudio_backend_t*)handle;
if ((handle == 0) || (data == 0))
{
logger_log(LOG_ERROR, "%s: handle or data pointer is null", __func__);
return -EINVAL;
}
if (pulseaudio_backend->pulseaudio_handle == 0)
{
logger_log(LOG_ERROR, "%s: device not open", __func__);
return -ENODEV;
}
ret = pa_simple_read(pulseaudio_backend->pulseaudio_handle, data, size, &error);
if (ret < 0)
{
logger_log(LOG_ERROR, "%s: pa_simple_read failed: %s", __func__, pa_strerror(error));
}
return (ret < 0) ? ret : size;
}

View File

@ -56,12 +56,14 @@ void usage()
printf("-i, --ipaddress=IP : MANDATORY. ipaddress to send stream to\n"); printf("-i, --ipaddress=IP : MANDATORY. ipaddress to send stream to\n");
printf("-p, --port=PORT : MANDATORY. port to use\n"); printf("-p, --port=PORT : MANDATORY. port to use\n");
printf("-s, --streamname=NAME : MANDATORY. streamname to use\n"); printf("-s, --streamname=NAME : MANDATORY. streamname to use\n");
printf("-b, --backend=TYPE : audio backend to use. %s\n", audio_backend_get_help()); //XXX printf("-b, --backend=TYPE : audio backend to use. %s\n", audio_backend_get_help());
printf("-b, --backend=TYPE : TEMPORARY DISABLED. audio backend to use. Only alsa backend is working at this time\n");
printf("-d, --device=NAME : Audio device name. This is file name for file backend, server name for jack backend, device for alsa, stream_name for pulseaudio.\n"); printf("-d, --device=NAME : Audio device name. This is file name for file backend, server name for jack backend, device for alsa, stream_name for pulseaudio.\n");
printf("-r, --rate=VALUE : Audio device sample rate. default 44100\n"); printf("-r, --rate=VALUE : Audio device sample rate. default 44100\n");
printf("-n, --nbchannels=VALUE : Audio device number of channels. default 2\n"); printf("-n, --nbchannels=VALUE : Audio device number of channels. default 2\n");
printf("-f, --format=VALUE : Audio device sample format (see below). default is 16I (16bits integer)\n"); printf("-f, --format=VALUE : Audio device sample format (see below). default is 16I (16bits integer)\n");
printf("-c, --channels=LIST : channels from the audio device to use. LIST is of form x,y,z,... default is to forward the stream as it is\n"); //XXX printf("-c, --channels=LIST : channels from the audio device to use. LIST is of form x,y,z,... default is to forward the stream as it is\n");
printf("-c, --channels=LIST : TEMPORARY DISABLED.\n");
printf("-l, --loglevel=LEVEL : Log level, from 0 (FATAL) to 4 (DEBUG). default is 1 (ERROR)\n"); printf("-l, --loglevel=LEVEL : Log level, from 0 (FATAL) to 4 (DEBUG). default is 1 (ERROR)\n");
printf("-h, --help : display this message\n\n"); printf("-h, --help : display this message\n\n");
@ -118,8 +120,8 @@ int get_options(struct config_t* config, int argc, char* const* argv)
strncpy(config->stream_name, optarg, VBAN_STREAM_NAME_SIZE); strncpy(config->stream_name, optarg, VBAN_STREAM_NAME_SIZE);
break; break;
case 'b': /*XXX case 'b':
strncpy(config->audio.backend_name, optarg, AUDIO_BACKEND_NAME_SIZE); strncpy(config->audio.backend_name, optarg, AUDIO_BACKEND_NAME_SIZE);*/
case 'd': case 'd':
strncpy(config->audio.device_name, optarg, AUDIO_DEVICE_NAME_SIZE); strncpy(config->audio.device_name, optarg, AUDIO_DEVICE_NAME_SIZE);
@ -137,9 +139,9 @@ int get_options(struct config_t* config, int argc, char* const* argv)
config->stream.bit_fmt = stream_parse_bit_fmt(optarg); config->stream.bit_fmt = stream_parse_bit_fmt(optarg);
break; break;
case 'c': /*XXX case 'c':
ret = audio_parse_map_config(&config->map, optarg); ret = audio_parse_map_config(&config->map, optarg);
break; break;*/
case 'l': case 'l':
logger_set_output_level(atoi(optarg)); logger_set_output_level(atoi(optarg));

View File

@ -58,7 +58,8 @@ void usage()
printf("-s, --streamname=NAME : MANDATORY. streamname to play\n"); printf("-s, --streamname=NAME : MANDATORY. streamname to play\n");
printf("-b, --backend=TYPE : audio backend to use. %s\n", audio_backend_get_help()); printf("-b, --backend=TYPE : audio backend to use. %s\n", audio_backend_get_help());
printf("-q, --quality=ID : network quality indicator from 0 (low latency) to 4. default is 1\n"); printf("-q, --quality=ID : network quality indicator from 0 (low latency) to 4. default is 1\n");
printf("-c, --channels=LIST : channels from the stream to use. LIST is of form x,y,z,... default is to forward the stream as it is\n"); //XXX printf("-c, --channels=LIST : channels from the stream to use. LIST is of form x,y,z,... default is to forward the stream as it is\n");
printf("-c, --channels=LIST : TEMPORARY DISABLED\n");
printf("-o, --output=NAME : DEPRECATED. please use -d\n"); printf("-o, --output=NAME : DEPRECATED. please use -d\n");
printf("-d, --device=NAME : Audio device name. This is file name for file backend, server name for jack backend, device for alsa, stream_name for pulseaudio.\n"); printf("-d, --device=NAME : Audio device name. This is file name for file backend, server name for jack backend, device for alsa, stream_name for pulseaudio.\n");
printf("-l, --loglevel=LEVEL : Log level, from 0 (FATAL) to 4 (DEBUG). default is 1 (ERROR)\n"); printf("-l, --loglevel=LEVEL : Log level, from 0 (FATAL) to 4 (DEBUG). default is 1 (ERROR)\n");
@ -155,9 +156,9 @@ int get_options(struct config_t* config, int argc, char* const* argv)
quality = atoi(optarg); quality = atoi(optarg);
break; break;
case 'c': /*XXX case 'c':
ret = audio_parse_map_config(&config->map, optarg); ret = audio_parse_map_config(&config->map, optarg);
break; break;*/
case 'o': case 'o':
case 'd': case 'd':