mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-12-14 08:56:37 -05:00
adapter-control: add CLI options
-To select between non-native(via control channel) and native modes(via audio adapter ). The control port will be opened only in the non-native mode. -To select different sample and sample step sizes. The Legacy non-native mode also uses these params now. -To provide the alsa device.
This commit is contained in:
parent
b1b5367d40
commit
075fd49ccc
1 changed files with 229 additions and 132 deletions
|
|
@ -24,6 +24,7 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
|
||||||
#include <spa/control/control.h>
|
#include <spa/control/control.h>
|
||||||
#include <spa/graph/graph.h>
|
#include <spa/graph/graph.h>
|
||||||
|
|
@ -45,6 +46,13 @@ static SPA_LOG_IMPL(default_log);
|
||||||
#define MIN_LATENCY 1024
|
#define MIN_LATENCY 1024
|
||||||
#define CONTROL_BUFFER_SIZE 32768
|
#define CONTROL_BUFFER_SIZE 32768
|
||||||
|
|
||||||
|
#define DEFAULT_SAMPLES (64*1*1024)
|
||||||
|
#define DEFAULT_STEP_SAMPLES 200
|
||||||
|
#define DEFAULT_DEVICE "hw:0,0"
|
||||||
|
|
||||||
|
#define NON_NATIVE "non-native"
|
||||||
|
#define NATIVE "native"
|
||||||
|
#define DEFAULT_MODE NON_NATIVE
|
||||||
|
|
||||||
struct buffer {
|
struct buffer {
|
||||||
struct spa_buffer buffer;
|
struct spa_buffer buffer;
|
||||||
|
|
@ -91,6 +99,15 @@ struct data {
|
||||||
double volume_accum;
|
double volume_accum;
|
||||||
uint32_t volume_offs;
|
uint32_t volume_offs;
|
||||||
|
|
||||||
|
const char *alsa_device;
|
||||||
|
|
||||||
|
const char *mode;
|
||||||
|
|
||||||
|
uint32_t volume_ramp_samples;
|
||||||
|
uint32_t volume_ramp_step_samples;
|
||||||
|
uint32_t volume_ramp_time;
|
||||||
|
uint32_t volume_ramp_step_time;
|
||||||
|
|
||||||
bool running;
|
bool running;
|
||||||
pthread_t thread;
|
pthread_t thread;
|
||||||
};
|
};
|
||||||
|
|
@ -282,130 +299,125 @@ exit_cleanup:
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SAMPLES (64*1*1024)
|
|
||||||
#define STEP_SAMPLES 200
|
|
||||||
|
|
||||||
#define USE_NATIVE_VOLUME_RAMPER
|
|
||||||
|
|
||||||
static int fade_in(struct data *data)
|
static int fade_in(struct data *data)
|
||||||
{
|
{
|
||||||
#ifndef USE_NATIVE_VOLUME_RAMPER
|
|
||||||
struct spa_pod_builder b;
|
|
||||||
struct spa_pod_frame f[1];
|
|
||||||
void *buffer = data->control_buffer->datas[0].data;
|
|
||||||
uint32_t buffer_size = data->control_buffer->datas[0].maxsize;
|
|
||||||
data->control_buffer->datas[0].chunk[0].size = buffer_size;
|
|
||||||
|
|
||||||
printf("fading in\n");
|
printf("fading in\n");
|
||||||
|
if (spa_streq (data->mode, NON_NATIVE)) {
|
||||||
|
struct spa_pod_builder b;
|
||||||
|
struct spa_pod_frame f[1];
|
||||||
|
void *buffer = data->control_buffer->datas[0].data;
|
||||||
|
double step_size = ((double) data->volume_ramp_step_samples / (double) data->volume_ramp_samples);
|
||||||
|
uint32_t buffer_size = data->control_buffer->datas[0].maxsize;
|
||||||
|
data->control_buffer->datas[0].chunk[0].size = buffer_size;
|
||||||
|
|
||||||
spa_pod_builder_init(&b, buffer, buffer_size);
|
spa_pod_builder_init(&b, buffer, buffer_size);
|
||||||
spa_pod_builder_push_sequence(&b, &f[0], 0);
|
spa_pod_builder_push_sequence(&b, &f[0], 0);
|
||||||
data->volume_offs = 0;
|
data->volume_offs = 0;
|
||||||
do {
|
do {
|
||||||
printf("volume_accum is %f\n", data->volume_accum);
|
spa_pod_builder_control(&b, data->volume_offs, SPA_CONTROL_Properties);
|
||||||
spa_pod_builder_control(&b, data->volume_offs, SPA_CONTROL_Properties);
|
spa_pod_builder_add_object(&b,
|
||||||
spa_pod_builder_add_object(&b,
|
SPA_TYPE_OBJECT_Props, 0,
|
||||||
SPA_TYPE_OBJECT_Props, 0,
|
SPA_PROP_volume, SPA_POD_Float(data->volume_accum));
|
||||||
SPA_PROP_volume, SPA_POD_Float(data->volume_accum));
|
data->volume_accum += step_size;
|
||||||
data->volume_accum += 0.003;
|
data->volume_offs += data->volume_ramp_step_samples;
|
||||||
data->volume_offs += 200;
|
} while (data->volume_accum < 1.0);
|
||||||
} while (data->volume_accum < 1.0);
|
spa_pod_builder_pop(&b, &f[0]);
|
||||||
spa_pod_builder_pop(&b, &f[0]);
|
}
|
||||||
#else
|
else {
|
||||||
struct spa_pod_builder b;
|
struct spa_pod_builder b;
|
||||||
struct spa_pod *props;
|
struct spa_pod *props;
|
||||||
int res = 0;
|
int res = 0;
|
||||||
uint8_t buffer[1024];
|
uint8_t buffer[1024];
|
||||||
printf("fading in\n");
|
printf("fading in\n");
|
||||||
spa_pod_builder_init(&b, buffer, sizeof(buffer));
|
spa_pod_builder_init(&b, buffer, sizeof(buffer));
|
||||||
props = spa_pod_builder_add_object(&b,
|
props = spa_pod_builder_add_object(&b,
|
||||||
SPA_TYPE_OBJECT_Props, 0,
|
SPA_TYPE_OBJECT_Props, 0,
|
||||||
SPA_PROP_volume, SPA_POD_Float(1.0));
|
SPA_PROP_volume, SPA_POD_Float(1.0));
|
||||||
if ((res = spa_node_set_param(data->sink_node, SPA_PARAM_Props, 0, props)) < 0) {
|
if ((res = spa_node_set_param(data->sink_node, SPA_PARAM_Props, 0, props)) < 0) {
|
||||||
printf("can't call volramp set params %d\n", res);
|
printf("can't call volramp set params %d\n", res);
|
||||||
return res;
|
return res;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fade_out(struct data *data)
|
static int fade_out(struct data *data)
|
||||||
{
|
{
|
||||||
#ifndef USE_NATIVE_VOLUME_RAMPER
|
|
||||||
struct spa_pod_builder b;
|
|
||||||
struct spa_pod_frame f[1];
|
|
||||||
void *buffer = data->control_buffer->datas[0].data;
|
|
||||||
uint32_t buffer_size = data->control_buffer->datas[0].maxsize;
|
|
||||||
data->control_buffer->datas[0].chunk[0].size = buffer_size;
|
|
||||||
|
|
||||||
printf("fading out\n");
|
printf("fading out\n");
|
||||||
|
if (spa_streq (data->mode, NON_NATIVE)) {
|
||||||
|
struct spa_pod_builder b;
|
||||||
|
struct spa_pod_frame f[1];
|
||||||
|
double step_size = ((double) data->volume_ramp_step_samples / (double) data->volume_ramp_samples);
|
||||||
|
|
||||||
spa_pod_builder_init(&b, buffer, buffer_size);
|
void *buffer = data->control_buffer->datas[0].data;
|
||||||
spa_pod_builder_push_sequence(&b, &f[0], 0);
|
uint32_t buffer_size = data->control_buffer->datas[0].maxsize;
|
||||||
data->volume_offs = 200;
|
data->control_buffer->datas[0].chunk[0].size = buffer_size;
|
||||||
do {
|
|
||||||
printf("volume_accum is %f\n", data->volume_accum);
|
spa_pod_builder_init(&b, buffer, buffer_size);
|
||||||
spa_pod_builder_control(&b, data->volume_offs, SPA_CONTROL_Properties);
|
spa_pod_builder_push_sequence(&b, &f[0], 0);
|
||||||
|
data->volume_offs = data->volume_ramp_step_samples;
|
||||||
|
do {
|
||||||
|
spa_pod_builder_control(&b, data->volume_offs, SPA_CONTROL_Properties);
|
||||||
spa_pod_builder_add_object(&b,
|
spa_pod_builder_add_object(&b,
|
||||||
SPA_TYPE_OBJECT_Props, 0,
|
SPA_TYPE_OBJECT_Props, 0,
|
||||||
SPA_PROP_volume, SPA_POD_Float(data->volume_accum));
|
SPA_PROP_volume, SPA_POD_Float(data->volume_accum));
|
||||||
data->volume_accum -= 0.003;
|
data->volume_accum -= step_size;
|
||||||
data->volume_offs += 200;
|
data->volume_offs += data->volume_ramp_step_samples;
|
||||||
} while (data->volume_accum > 0.0);
|
} while (data->volume_accum > 0.0);
|
||||||
spa_pod_builder_pop(&b, &f[0]);
|
spa_pod_builder_pop(&b, &f[0]);
|
||||||
#else
|
} else {
|
||||||
struct spa_pod_builder b;
|
struct spa_pod_builder b;
|
||||||
uint8_t buffer[1024];
|
uint8_t buffer[1024];
|
||||||
struct spa_pod *props;
|
struct spa_pod *props;
|
||||||
int res = 0;
|
int res = 0;
|
||||||
printf("fading out\n");
|
|
||||||
|
|
||||||
spa_pod_builder_init(&b, buffer, sizeof(buffer));
|
spa_pod_builder_init(&b, buffer, sizeof(buffer));
|
||||||
props = spa_pod_builder_add_object(&b,
|
props = spa_pod_builder_add_object(&b,
|
||||||
SPA_TYPE_OBJECT_Props, 0,
|
SPA_TYPE_OBJECT_Props, 0,
|
||||||
SPA_PROP_volume, SPA_POD_Float(0.0));
|
SPA_PROP_volume, SPA_POD_Float(0.0));
|
||||||
if ((res = spa_node_set_param(data->sink_node, SPA_PARAM_Props, 0, props)) < 0) {
|
if ((res = spa_node_set_param(data->sink_node, SPA_PARAM_Props, 0, props)) < 0) {
|
||||||
printf("can't call volramp set params %d\n", res);
|
printf("can't call volramp set params %d\n", res);
|
||||||
return res;
|
return res;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_fade(struct data *data)
|
static void do_fade(struct data *data)
|
||||||
{
|
{
|
||||||
#ifndef USE_NATIVE_VOLUME_RAMPER
|
if (spa_streq (data->mode, NON_NATIVE)) {
|
||||||
switch (data->control_io.status) {
|
switch (data->control_io.status) {
|
||||||
case SPA_STATUS_OK:
|
case SPA_STATUS_OK:
|
||||||
case SPA_STATUS_NEED_DATA:
|
case SPA_STATUS_NEED_DATA:
|
||||||
break;
|
break;
|
||||||
case SPA_STATUS_HAVE_DATA:
|
case SPA_STATUS_HAVE_DATA:
|
||||||
case SPA_STATUS_STOPPED:
|
case SPA_STATUS_STOPPED:
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
/* fade */
|
/* fade */
|
||||||
if (data->start_fade_in)
|
if (data->start_fade_in)
|
||||||
fade_in(data);
|
fade_in(data);
|
||||||
else
|
else
|
||||||
fade_out(data);
|
fade_out(data);
|
||||||
|
|
||||||
#ifndef USE_NATIVE_VOLUME_RAMPER
|
if (spa_streq (data->mode, NON_NATIVE)) {
|
||||||
data->control_io.status = SPA_STATUS_HAVE_DATA;
|
data->control_io.status = SPA_STATUS_HAVE_DATA;
|
||||||
data->control_io.buffer_id = 0;
|
data->control_io.buffer_id = 0;
|
||||||
#endif
|
}
|
||||||
|
|
||||||
/* alternate */
|
/* alternate */
|
||||||
data->start_fade_in = !data->start_fade_in;
|
data->start_fade_in = !data->start_fade_in;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int on_sink_node_ready(void *_data, int status)
|
static int on_sink_node_ready(void *_data, int status)
|
||||||
{
|
{
|
||||||
struct data *data = _data;
|
struct data *data = _data;
|
||||||
|
int runway = (data->volume_ramp_samples / 1024);
|
||||||
|
|
||||||
/* only do fade in/out when buffer count is 0 */
|
/* only do fade in/out when buffer count is 0 */
|
||||||
if (data->buffer_count == 0)
|
if (data->buffer_count == 0)
|
||||||
|
|
@ -413,7 +425,7 @@ static int on_sink_node_ready(void *_data, int status)
|
||||||
|
|
||||||
/* update buffer count */
|
/* update buffer count */
|
||||||
data->buffer_count++;
|
data->buffer_count++;
|
||||||
if (data->buffer_count > 64)
|
if (data->buffer_count > (runway * 2))
|
||||||
data->buffer_count = 0;
|
data->buffer_count = 0;
|
||||||
|
|
||||||
spa_graph_node_process(&data->graph_source_node);
|
spa_graph_node_process(&data->graph_source_node);
|
||||||
|
|
@ -426,7 +438,7 @@ static const struct spa_node_callbacks sink_node_callbacks = {
|
||||||
.ready = on_sink_node_ready,
|
.ready = on_sink_node_ready,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int make_nodes(struct data *data, const char *device)
|
static int make_nodes(struct data *data)
|
||||||
{
|
{
|
||||||
int res = 0;
|
int res = 0;
|
||||||
struct spa_pod *props;
|
struct spa_pod *props;
|
||||||
|
|
@ -535,13 +547,13 @@ static int make_nodes(struct data *data, const char *device)
|
||||||
spa_pod_builder_init(&b, buffer, sizeof(buffer));
|
spa_pod_builder_init(&b, buffer, sizeof(buffer));
|
||||||
props = spa_pod_builder_add_object(&b,
|
props = spa_pod_builder_add_object(&b,
|
||||||
SPA_TYPE_OBJECT_Props, 0,
|
SPA_TYPE_OBJECT_Props, 0,
|
||||||
SPA_PROP_device, SPA_POD_String(device ? device : "hw:0"),
|
SPA_PROP_device, SPA_POD_String(data->alsa_device),
|
||||||
SPA_PROP_minLatency, SPA_POD_Int(MIN_LATENCY));
|
SPA_PROP_minLatency, SPA_POD_Int(MIN_LATENCY));
|
||||||
if ((res = spa_node_set_param(data->sink_follower_node, SPA_PARAM_Props, 0, props)) < 0) {
|
if ((res = spa_node_set_param(data->sink_follower_node, SPA_PARAM_Props, 0, props)) < 0) {
|
||||||
printf("can't setup sink follower node %d\n", res);
|
printf("can't setup sink follower node %d\n", res);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
printf("Selected (%s) Sound card\n", (device ? device : "hw:0"));
|
printf("Selected (%s) alsa device\n", data->alsa_device);
|
||||||
|
|
||||||
if (!data->start_fade_in)
|
if (!data->start_fade_in)
|
||||||
initial_volume = 1.0;
|
initial_volume = 1.0;
|
||||||
|
|
@ -554,14 +566,22 @@ static int make_nodes(struct data *data, const char *device)
|
||||||
info.position[0] = SPA_AUDIO_CHANNEL_MONO;
|
info.position[0] = SPA_AUDIO_CHANNEL_MONO;
|
||||||
spa_pod_builder_init(&b, buffer, sizeof(buffer));
|
spa_pod_builder_init(&b, buffer, sizeof(buffer));
|
||||||
param = spa_format_audio_raw_build(&b, SPA_PARAM_Format, &info);
|
param = spa_format_audio_raw_build(&b, SPA_PARAM_Format, &info);
|
||||||
param = spa_pod_builder_add_object(&b,
|
|
||||||
SPA_TYPE_OBJECT_ParamPortConfig, SPA_PARAM_PortConfig,
|
if (spa_streq (data->mode, NON_NATIVE))
|
||||||
SPA_PARAM_PORT_CONFIG_direction, SPA_POD_Id(SPA_DIRECTION_INPUT),
|
param = spa_pod_builder_add_object(&b,
|
||||||
SPA_PARAM_PORT_CONFIG_mode, SPA_POD_Id(SPA_PARAM_PORT_CONFIG_MODE_dsp),
|
SPA_TYPE_OBJECT_ParamPortConfig, SPA_PARAM_PortConfig,
|
||||||
#ifndef USE_NATIVE_VOLUME_RAMPER
|
SPA_PARAM_PORT_CONFIG_direction, SPA_POD_Id(SPA_DIRECTION_INPUT),
|
||||||
SPA_PARAM_PORT_CONFIG_control, SPA_POD_Bool(true),
|
SPA_PARAM_PORT_CONFIG_mode, SPA_POD_Id(SPA_PARAM_PORT_CONFIG_MODE_dsp),
|
||||||
#endif
|
SPA_PARAM_PORT_CONFIG_control, SPA_POD_Bool(true),
|
||||||
SPA_PARAM_PORT_CONFIG_format, SPA_POD_Pod(param));
|
SPA_PARAM_PORT_CONFIG_format, SPA_POD_Pod(param));
|
||||||
|
else
|
||||||
|
param = spa_pod_builder_add_object(&b,
|
||||||
|
SPA_TYPE_OBJECT_ParamPortConfig, SPA_PARAM_PortConfig,
|
||||||
|
SPA_PARAM_PORT_CONFIG_direction, SPA_POD_Id(SPA_DIRECTION_INPUT),
|
||||||
|
SPA_PARAM_PORT_CONFIG_mode, SPA_POD_Id(SPA_PARAM_PORT_CONFIG_MODE_dsp),
|
||||||
|
SPA_PARAM_PORT_CONFIG_format, SPA_POD_Pod(param));
|
||||||
|
|
||||||
|
|
||||||
if ((res = spa_node_set_param(data->sink_node, SPA_PARAM_PortConfig, 0, param) < 0)) {
|
if ((res = spa_node_set_param(data->sink_node, SPA_PARAM_PortConfig, 0, param) < 0)) {
|
||||||
printf("can't setup sink node %d\n", res);
|
printf("can't setup sink node %d\n", res);
|
||||||
return res;
|
return res;
|
||||||
|
|
@ -576,16 +596,17 @@ static int make_nodes(struct data *data, const char *device)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
spa_pod_builder_init(&b, buffer, sizeof(buffer));
|
if (spa_streq (data->mode, NATIVE)) {
|
||||||
props = spa_pod_builder_add_object(&b,
|
spa_pod_builder_init(&b, buffer, sizeof(buffer));
|
||||||
SPA_TYPE_OBJECT_Props, 0,
|
props = spa_pod_builder_add_object(&b,
|
||||||
SPA_PROP_volumeRampSamples, SPA_POD_Int(SAMPLES),
|
SPA_TYPE_OBJECT_Props, 0,
|
||||||
SPA_PROP_volumeRampStepSamples, SPA_POD_Int(STEP_SAMPLES));
|
SPA_PROP_volumeRampSamples, SPA_POD_Int(data->volume_ramp_samples),
|
||||||
if ((res = spa_node_set_param(data->sink_node, SPA_PARAM_Props, 0, props)) < 0) {
|
SPA_PROP_volumeRampStepSamples, SPA_POD_Int(data->volume_ramp_step_samples));
|
||||||
printf("can't call volramp set params %d\n", res);
|
if ((res = spa_node_set_param(data->sink_node, SPA_PARAM_Props, 0, props)) < 0) {
|
||||||
return res;
|
printf("can't call volramp set params %d\n", res);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set io buffers on source and sink nodes */
|
/* set io buffers on source and sink nodes */
|
||||||
data->source_sink_io[0] = SPA_IO_BUFFERS_INIT;
|
data->source_sink_io[0] = SPA_IO_BUFFERS_INIT;
|
||||||
if ((res = spa_node_port_set_io(data->source_node,
|
if ((res = spa_node_port_set_io(data->source_node,
|
||||||
|
|
@ -637,16 +658,16 @@ static int make_nodes(struct data *data, const char *device)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef USE_NATIVE_VOLUME_RAMPER
|
if (spa_streq (data->mode, NON_NATIVE)) {
|
||||||
/* set io buffers on control port of sink node */
|
/* set io buffers on control port of sink node */
|
||||||
if ((res = spa_node_port_set_io(data->sink_node,
|
if ((res = spa_node_port_set_io(data->sink_node,
|
||||||
SPA_DIRECTION_INPUT, 1,
|
SPA_DIRECTION_INPUT, 1,
|
||||||
SPA_IO_Buffers,
|
SPA_IO_Buffers,
|
||||||
&data->control_io, sizeof(data->control_io))) < 0) {
|
&data->control_io, sizeof(data->control_io))) < 0) {
|
||||||
printf("can't set io buffers on control port 1 of sink node\n");
|
printf("can't set io buffers on control port 1 of sink node\n");
|
||||||
return res;
|
return res;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
/* add source node to the graph */
|
/* add source node to the graph */
|
||||||
spa_graph_node_init(&data->graph_source_node, &data->graph_source_state);
|
spa_graph_node_init(&data->graph_source_node, &data->graph_source_state);
|
||||||
spa_graph_node_set_callbacks(&data->graph_source_node, &spa_graph_node_impl_default, data->source_node);
|
spa_graph_node_set_callbacks(&data->graph_source_node, &spa_graph_node_impl_default, data->source_node);
|
||||||
|
|
@ -728,18 +749,18 @@ static int negotiate_formats(struct data *data)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef USE_NATIVE_VOLUME_RAMPER
|
if (spa_streq (data->mode, NON_NATIVE)) {
|
||||||
spa_pod_builder_init(&b, buffer, sizeof(buffer));
|
spa_pod_builder_init(&b, buffer, sizeof(buffer));
|
||||||
param = spa_pod_builder_add_object(&b,
|
param = spa_pod_builder_add_object(&b,
|
||||||
SPA_TYPE_OBJECT_Format, SPA_PARAM_Format,
|
SPA_TYPE_OBJECT_Format, SPA_PARAM_Format,
|
||||||
SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_application),
|
SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_application),
|
||||||
SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_control));
|
SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_control));
|
||||||
if ((res = spa_node_port_set_param(data->sink_node,
|
if ((res = spa_node_port_set_param(data->sink_node,
|
||||||
SPA_DIRECTION_INPUT, 1, SPA_PARAM_Format, 0, param)) < 0) {
|
SPA_DIRECTION_INPUT, 1, SPA_PARAM_Format, 0, param)) < 0) {
|
||||||
printf("can't set format on control port of source node: %d\n", res);
|
printf("can't set format on control port of source node: %d\n", res);
|
||||||
return res;
|
return res;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* get the source node buffer size */
|
/* get the source node buffer size */
|
||||||
spa_pod_builder_init(&b, buffer, sizeof(buffer));
|
spa_pod_builder_init(&b, buffer, sizeof(buffer));
|
||||||
|
|
@ -763,14 +784,14 @@ static int negotiate_formats(struct data *data)
|
||||||
return res;
|
return res;
|
||||||
printf("allocated and assigned buffers to sink node %p\n", data->sink_node);
|
printf("allocated and assigned buffers to sink node %p\n", data->sink_node);
|
||||||
|
|
||||||
#ifndef USE_NATIVE_VOLUME_RAMPER
|
if (spa_streq (data->mode, NON_NATIVE)) {
|
||||||
/* Set the control buffers */
|
/* Set the control buffers */
|
||||||
init_buffer(data, data->control_buffers, data->control_buffer, 1, CONTROL_BUFFER_SIZE);
|
init_buffer(data, data->control_buffers, data->control_buffer, 1, CONTROL_BUFFER_SIZE);
|
||||||
if ((res = spa_node_port_use_buffers(data->sink_node,
|
if ((res = spa_node_port_use_buffers(data->sink_node,
|
||||||
SPA_DIRECTION_INPUT, 1, 0, data->control_buffers, 1)) < 0)
|
SPA_DIRECTION_INPUT, 1, 0, data->control_buffers, 1)) < 0)
|
||||||
return res;
|
return res;
|
||||||
printf("allocated and assigned control buffers(%d) to sink node %p\n", CONTROL_BUFFER_SIZE, data->sink_node);
|
printf("allocated and assigned control buffers(%d) to sink node %p\n", CONTROL_BUFFER_SIZE, data->sink_node);
|
||||||
#endif
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -831,10 +852,82 @@ static void run_async_sink(struct data *data)
|
||||||
printf("got error %d\n", res);
|
printf("got error %d\n", res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void show_help(struct data *data, const char *name, bool error)
|
||||||
|
{
|
||||||
|
fprintf(error ? stderr : stdout, "%s [options] [command]\n"
|
||||||
|
" -h, --help Show this help\n"
|
||||||
|
" -d, --alsa-device ALSA device(\"aplay -l\" for more info) to play the samples on(default %s)\n"
|
||||||
|
" -m, --mode Volume Ramp Mode(\"NonNative\"(via Control Port) \"Native\" (via Volume Ramp Params of AudioAdapter plugin)) (default %s)\n"
|
||||||
|
" -s, --ramp-samples SPA_PROP_volumeRampSamples(Samples to ramp the volume over)(default %d)\n"
|
||||||
|
" -a, --ramp-step-samples SPA_PROP_volumeRampStepSamples(Step or incremental Samples to ramp the volume over)(default %d)\n"
|
||||||
|
" -t, --ramp-time SPA_PROP_volumeRampTime(Time to ramp the volume over)\n"
|
||||||
|
" -i, --ramp-step-time SPA_PROP_volumeRampStepTime(Step or incremental Time to ramp the volume over)\n"
|
||||||
|
" -c, --ramp-scale SPA_PROP_volumeRampScale(the scale or graph to used to ramp the volume)\n",
|
||||||
|
name,
|
||||||
|
DEFAULT_DEVICE,
|
||||||
|
DEFAULT_MODE,
|
||||||
|
DEFAULT_SAMPLES,
|
||||||
|
DEFAULT_STEP_SAMPLES);
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
struct data data = { 0 };
|
struct data data = { 0 };
|
||||||
int res = 0;
|
int res = 0;
|
||||||
|
char c;
|
||||||
|
|
||||||
|
/* default values*/
|
||||||
|
data.volume_ramp_samples = DEFAULT_SAMPLES;
|
||||||
|
data.volume_ramp_step_samples = DEFAULT_STEP_SAMPLES;
|
||||||
|
data.alsa_device = DEFAULT_DEVICE;
|
||||||
|
data.mode = DEFAULT_MODE;
|
||||||
|
|
||||||
|
static const struct option long_options[] = {
|
||||||
|
{ "help", no_argument, NULL, 'h' },
|
||||||
|
{ "alsa-device", required_argument, NULL, 'd' },
|
||||||
|
{ "mode", required_argument, NULL, 'm' },
|
||||||
|
{ "ramp-samples", required_argument, NULL, 's' },
|
||||||
|
{ "ramp-time", required_argument, NULL, 't' },
|
||||||
|
{ "ramp-step-samples", required_argument, NULL, 'a' },
|
||||||
|
{ "ramp-step-time", required_argument, NULL, 'i' },
|
||||||
|
{ NULL, 0, NULL, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
setlocale(LC_ALL, "");
|
||||||
|
|
||||||
|
while ((c = getopt_long(argc, argv, "hdmstia:", long_options, NULL)) != -1) {
|
||||||
|
printf("\nhere_we_are %s %s(%u) c=%c \n",__FILE__,__func__,__LINE__, c);
|
||||||
|
switch (c) {
|
||||||
|
case 'h':
|
||||||
|
show_help(&data, argv[0], false);
|
||||||
|
return 0;
|
||||||
|
case 'm':
|
||||||
|
if (!spa_streq (optarg, NATIVE) && !spa_streq (optarg, NON_NATIVE))
|
||||||
|
printf("Invalid Mode(\"%s\"), using default(\"%s\")\n", optarg, DEFAULT_MODE);
|
||||||
|
else
|
||||||
|
data.mode = optarg;
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
data.alsa_device = optarg;
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
data.volume_ramp_samples = atoi(optarg);
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
data.volume_ramp_time = atoi(optarg);
|
||||||
|
break;
|
||||||
|
case 'a':
|
||||||
|
data.volume_ramp_step_samples = atoi(optarg);
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
data.volume_ramp_step_time = atoi(optarg);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
show_help(&data, argv[0], true);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* init data */
|
/* init data */
|
||||||
if ((res = init_data(&data)) < 0) {
|
if ((res = init_data(&data)) < 0) {
|
||||||
|
|
@ -843,7 +936,7 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
/* make the nodes (audiotestsrc and adapter with alsa-pcm-sink as follower) */
|
/* make the nodes (audiotestsrc and adapter with alsa-pcm-sink as follower) */
|
||||||
if ((res = make_nodes(&data, argc > 1 ? argv[1] : NULL)) < 0) {
|
if ((res = make_nodes(&data)) < 0) {
|
||||||
printf("can't make nodes: %d (%s)\n", res, spa_strerror(res));
|
printf("can't make nodes: %d (%s)\n", res, spa_strerror(res));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -854,6 +947,10 @@ int main(int argc, char *argv[])
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf("using %s mode\n", data.mode);
|
||||||
|
printf("using %d samples with a step size of %d samples\n",
|
||||||
|
data.volume_ramp_samples, data.volume_ramp_step_samples);
|
||||||
|
|
||||||
spa_loop_control_enter(data.control);
|
spa_loop_control_enter(data.control);
|
||||||
run_async_sink(&data);
|
run_async_sink(&data);
|
||||||
spa_loop_control_leave(data.control);
|
spa_loop_control_leave(data.control);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue