diff --git a/README.md b/README.md index ede699c..783bbfe 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ vban - Linux command-line VBAN tools 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). 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 ---------------------------- @@ -20,9 +20,9 @@ Usual package names are: vban is distributed with autotools build scripts, therefore, to build, you need to invoke: - $ ./autogen.sh # probably only once for ever - $ ./configure # with or without options (--help to get the list of possible options) - $ make # with or without options + $ ./autogen.sh # probably only once for ever + $ ./configure # with or without options (--help to get the list of possible options) + $ make # with or without options 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 : -Usage: vban_receptor [OPTIONS]... + Usage: vban [OPTIONS]... -i, --ipaddress=IP : MANDATORY. ipaddress to get stream from -p, --port=PORT : MANDATORY. port to listen to -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 - -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 - -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 - -d, --debug=LEVEL : Log level, from 0 (FATAL) to 4 (DEBUG). default is 1 (ERROR) + -c, --channels=LIST : TEMPORARY DISABLED + -o, --output=NAME : DEPRECATED. please use -d + -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 -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: * 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,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_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) diff --git a/src/common/backend/pulseaudio_backend.c b/src/common/backend/pulseaudio_backend.c index 58161c2..cc40a6a 100644 --- a/src/common/backend/pulseaudio_backend.c +++ b/src/common/backend/pulseaudio_backend.c @@ -10,9 +10,10 @@ struct pulseaudio_backend_t 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_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) { @@ -59,6 +60,7 @@ int pulseaudio_backend_init(audio_backend_handle_t* handle) pulseaudio_backend->parent.open = pulseaudio_open; pulseaudio_backend->parent.close = pulseaudio_close; pulseaudio_backend->parent.write = pulseaudio_write; + pulseaudio_backend->parent.read = pulseaudio_read; *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; 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; } - 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) { 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; } +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; +} + diff --git a/src/emitter/main.c b/src/emitter/main.c index 37e8fe3..891be27 100644 --- a/src/emitter/main.c +++ b/src/emitter/main.c @@ -56,12 +56,14 @@ void usage() printf("-i, --ipaddress=IP : MANDATORY. ipaddress to send stream to\n"); printf("-p, --port=PORT : MANDATORY. port 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("-r, --rate=VALUE : Audio device sample rate. default 44100\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("-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("-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); break; - case 'b': - strncpy(config->audio.backend_name, optarg, AUDIO_BACKEND_NAME_SIZE); +/*XXX case 'b': + strncpy(config->audio.backend_name, optarg, AUDIO_BACKEND_NAME_SIZE);*/ case 'd': 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); break; - case 'c': +/*XXX case 'c': ret = audio_parse_map_config(&config->map, optarg); - break; + break;*/ case 'l': logger_set_output_level(atoi(optarg)); diff --git a/src/receptor/main.c b/src/receptor/main.c index fb0f4f0..7dd3459 100644 --- a/src/receptor/main.c +++ b/src/receptor/main.c @@ -58,7 +58,8 @@ void usage() printf("-s, --streamname=NAME : MANDATORY. streamname to play\n"); 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("-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("-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"); @@ -155,9 +156,9 @@ int get_options(struct config_t* config, int argc, char* const* argv) quality = atoi(optarg); break; - case 'c': +/*XXX case 'c': ret = audio_parse_map_config(&config->map, optarg); - break; + break;*/ case 'o': case 'd':