diff --git a/spa/examples/adapter-control.c b/spa/examples/adapter-control.c index 6007f2c88..a49237700 100644 --- a/spa/examples/adapter-control.c +++ b/spa/examples/adapter-control.c @@ -62,7 +62,9 @@ static SPA_LOG_IMPL(default_log); -#define MIN_LATENCY 1024 +#define MIN_LATENCY 1024 +#define CONTROL_BUFFER_SIZE 32768 + struct buffer { struct spa_buffer buffer; @@ -100,6 +102,14 @@ struct data { struct spa_buffer *source_buffers[1]; struct buffer source_buffer[1]; + struct spa_io_buffers control_io; + struct spa_buffer *control_buffers[1]; + struct buffer control_buffer[1]; + + int buffer_count; + bool start_faid_in; + double volume_accum; + bool running; pthread_t thread; }; @@ -168,6 +178,10 @@ int init_data(struct data *data) str = PLUGINDIR; data->plugin_dir = str; + /* start not doing fade-in */ + data->start_faid_in = true; + data->volume_accum = 0.0; + /* init the graph */ spa_graph_init(&data->graph, &data->graph_state); @@ -274,9 +288,92 @@ exit_cleanup: return res; } +static int fade_in(struct data *data) +{ + 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"); + + spa_pod_builder_init(&b, buffer, buffer_size); + spa_pod_builder_push_sequence(&b, &f[0], 0); + do { + spa_pod_builder_control(&b, 200, SPA_CONTROL_Properties); + spa_pod_builder_add_object(&b, + SPA_TYPE_OBJECT_Props, 0, + SPA_PROP_volume, SPA_POD_Float(data->volume_accum)); + data->volume_accum += 0.003; + } while (data->volume_accum < 1.0); + spa_pod_builder_pop(&b, &f[0]); + + return 0; +} + +static int fade_out(struct data *data) +{ + 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"); + + spa_pod_builder_init(&b, buffer, buffer_size); + spa_pod_builder_push_sequence(&b, &f[0], 0); + do { + spa_pod_builder_control(&b, 200, SPA_CONTROL_Properties); + spa_pod_builder_add_object(&b, + SPA_TYPE_OBJECT_Props, 0, + SPA_PROP_volume, SPA_POD_Float(data->volume_accum)); + data->volume_accum -= 0.003; + } while (data->volume_accum > 0.0); + spa_pod_builder_pop(&b, &f[0]); + + return 0; +} + +static void do_fade(struct data *data) +{ + switch (data->control_io.status) { + case SPA_STATUS_OK: + case SPA_STATUS_NEED_DATA: + break; + case SPA_STATUS_HAVE_DATA: + case SPA_STATUS_STOPPED: + default: + return; + } + + /* fade */ + if (data->start_faid_in) + fade_in(data); + else + fade_out(data); + + data->control_io.status = SPA_STATUS_HAVE_DATA; + data->control_io.buffer_id = 0; + + /* alternate */ + data->start_faid_in = !data->start_faid_in; +} + static int on_sink_node_ready(void *_data, int status) { struct data *data = _data; + + /* only do fade in/out when buffer count is 0 */ + if (data->buffer_count == 0) + do_fade(data); + + /* update buffer count */ + data->buffer_count++; + if (data->buffer_count > 16) + data->buffer_count = 0; + spa_graph_node_process(&data->graph_source_node); spa_graph_node_process(&data->graph_sink_node); return 0; @@ -410,6 +507,7 @@ static int make_nodes(struct data *data, const char *device) 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_control, SPA_POD_Bool(true), SPA_PARAM_PORT_CONFIG_format, SPA_POD_Pod(param)); if ((res = spa_node_set_param(data->sink_node, SPA_PARAM_PortConfig, 0, param) < 0)) { printf("can't setup sink node %d\n", res); @@ -460,6 +558,15 @@ static int make_nodes(struct data *data, const char *device) return res; } + /* set io buffers on control port of sink node */ + if ((res = spa_node_port_set_io(data->sink_node, + SPA_DIRECTION_INPUT, 1, + SPA_IO_Buffers, + &data->control_io, sizeof(data->control_io))) < 0) { + printf("can't set io buffers on control port 1 of sink node\n"); + return res; + } + /* add source node to the graph */ 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); @@ -557,6 +664,12 @@ static int negotiate_formats(struct data *data) SPA_DIRECTION_INPUT, 0, 0, data->source_buffers, 1)) < 0) return res; + /* Set the control buffers */ + init_buffer(data, data->control_buffers, data->control_buffer, 1, CONTROL_BUFFER_SIZE); + if ((res = spa_node_port_use_buffers(data->sink_node, + SPA_DIRECTION_INPUT, 1, 0, data->control_buffers, 1)) < 0) + return res; + return 0; }