mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-12-13 08:56:39 -05:00
node: remove node state
Remove the node state. The state of the node is based on the state of the ports, which can be derived directly from calling the port methods. Track this state in the Port instead. Add a mixer module that puts a mixer in from of audio sinks. This allows multiple clients to play on one sink (still has some bugs). do some fixes in the mixer and the scheduler to make this work.
This commit is contained in:
parent
28389e05f3
commit
d3682067fa
30 changed files with 618 additions and 509 deletions
|
|
@ -428,16 +428,16 @@ on_context_data (SpaSource *source,
|
|||
continue;
|
||||
}
|
||||
if (opcode >= proxy->iface->n_events) {
|
||||
pinos_log_error ("context %p: invalid method %u", this, opcode);
|
||||
pinos_log_error ("context %p: invalid method %u for %u", this, opcode, id);
|
||||
continue;
|
||||
}
|
||||
|
||||
demarshal = proxy->iface->events;
|
||||
if (demarshal[opcode]) {
|
||||
if (!demarshal[opcode] (proxy, message, size))
|
||||
pinos_log_error ("context %p: invalid message received %u", this, opcode);
|
||||
pinos_log_error ("context %p: invalid message received %u for %u", this, opcode, id);
|
||||
} else
|
||||
pinos_log_error ("context %p: function %d not implemented", this, opcode);
|
||||
pinos_log_error ("context %p: function %d not implemented on %u", this, opcode, id);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -157,8 +157,6 @@ typedef struct {
|
|||
const SpaFormat *format,
|
||||
const SpaProps *props,
|
||||
const SpaPortInfo *info);
|
||||
void (*state_change) (void *object,
|
||||
SpaNodeState state);
|
||||
void (*event) (void *object,
|
||||
SpaEvent *event);
|
||||
void (*destroy) (void *object);
|
||||
|
|
@ -166,7 +164,6 @@ typedef struct {
|
|||
|
||||
#define pinos_client_node_do_update(r,...) ((PinosClientNodeMethods*)r->iface->methods)->update(r,__VA_ARGS__)
|
||||
#define pinos_client_node_do_port_update(r,...) ((PinosClientNodeMethods*)r->iface->methods)->port_update(r,__VA_ARGS__)
|
||||
#define pinos_client_node_do_state_change(r,...) ((PinosClientNodeMethods*)r->iface->methods)->state_change(r,__VA_ARGS__)
|
||||
#define pinos_client_node_do_event(r,...) ((PinosClientNodeMethods*)r->iface->methods)->event(r,__VA_ARGS__)
|
||||
#define pinos_client_node_do_destroy(r) ((PinosClientNodeMethods*)r->iface->methods)->destroy(r)
|
||||
|
||||
|
|
|
|||
|
|
@ -535,23 +535,6 @@ client_node_marshal_port_update (void *object,
|
|||
pinos_connection_end_write (connection, proxy->id, 1, b.b.offset);
|
||||
}
|
||||
|
||||
static void
|
||||
client_node_marshal_state_change (void *object,
|
||||
SpaNodeState state)
|
||||
{
|
||||
PinosProxy *proxy = object;
|
||||
PinosConnection *connection = proxy->context->protocol_private;
|
||||
Builder b = { { NULL, 0, 0, NULL, write_pod }, connection };
|
||||
SpaPODFrame f;
|
||||
|
||||
core_update_map (proxy->context);
|
||||
|
||||
spa_pod_builder_struct (&b.b, &f,
|
||||
SPA_POD_TYPE_INT, state);
|
||||
|
||||
pinos_connection_end_write (connection, proxy->id, 2, b.b.offset);
|
||||
}
|
||||
|
||||
static void
|
||||
client_node_marshal_event (void *object,
|
||||
SpaEvent *event)
|
||||
|
|
@ -566,7 +549,7 @@ client_node_marshal_event (void *object,
|
|||
spa_pod_builder_struct (&b.b, &f,
|
||||
SPA_POD_TYPE_POD, event);
|
||||
|
||||
pinos_connection_end_write (connection, proxy->id, 3, b.b.offset);
|
||||
pinos_connection_end_write (connection, proxy->id, 2, b.b.offset);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -581,7 +564,7 @@ client_node_marshal_destroy (void *object)
|
|||
|
||||
spa_pod_builder_struct (&b.b, &f, 0);
|
||||
|
||||
pinos_connection_end_write (connection, proxy->id, 4, b.b.offset);
|
||||
pinos_connection_end_write (connection, proxy->id, 3, b.b.offset);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
@ -1042,7 +1025,6 @@ static const PinosInterface pinos_protocol_native_client_registry_interface = {
|
|||
static const PinosClientNodeMethods pinos_protocol_native_client_client_node_methods = {
|
||||
&client_node_marshal_update,
|
||||
&client_node_marshal_port_update,
|
||||
&client_node_marshal_state_change,
|
||||
&client_node_marshal_event,
|
||||
&client_node_marshal_destroy
|
||||
};
|
||||
|
|
@ -1062,7 +1044,7 @@ static const PinosDemarshalFunc pinos_protocol_native_client_client_node_demarsh
|
|||
};
|
||||
|
||||
static const PinosInterface pinos_protocol_native_client_client_node_interface = {
|
||||
5, &pinos_protocol_native_client_client_node_methods,
|
||||
4, &pinos_protocol_native_client_client_node_methods,
|
||||
11, pinos_protocol_native_client_client_node_demarshal,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ typedef struct
|
|||
{
|
||||
PinosStream this;
|
||||
|
||||
SpaNodeState node_state;
|
||||
uint32_t port_state;
|
||||
|
||||
uint32_t n_possible_formats;
|
||||
SpaFormat **possible_formats;
|
||||
|
|
@ -224,7 +224,7 @@ pinos_stream_new (PinosContext *context,
|
|||
|
||||
this->state = PINOS_STREAM_STATE_UNCONNECTED;
|
||||
|
||||
impl->node_state = SPA_NODE_STATE_INIT;
|
||||
impl->port_state = SPA_PORT_STATE_INIT;
|
||||
pinos_array_init (&impl->mem_ids, 64);
|
||||
pinos_array_ensure_size (&impl->mem_ids, sizeof (MemId) * 64);
|
||||
pinos_array_init (&impl->buffer_ids, 32);
|
||||
|
|
@ -304,7 +304,7 @@ pinos_stream_destroy (PinosStream *stream)
|
|||
}
|
||||
|
||||
static void
|
||||
add_node_update (PinosStream *stream, uint32_t change_mask, bool flush)
|
||||
add_node_update (PinosStream *stream, uint32_t change_mask)
|
||||
{
|
||||
PinosStreamImpl *impl = SPA_CONTAINER_OF (stream, PinosStreamImpl, this);
|
||||
uint32_t max_input_ports = 0, max_output_ports = 0;
|
||||
|
|
@ -322,19 +322,7 @@ add_node_update (PinosStream *stream, uint32_t change_mask, bool flush)
|
|||
}
|
||||
|
||||
static void
|
||||
add_state_change (PinosStream *stream, SpaNodeState state, bool flush)
|
||||
{
|
||||
PinosStreamImpl *impl = SPA_CONTAINER_OF (stream, PinosStreamImpl, this);
|
||||
|
||||
if (impl->node_state != state) {
|
||||
impl->node_state = state;
|
||||
pinos_client_node_do_state_change (impl->node_proxy,
|
||||
state);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
add_port_update (PinosStream *stream, uint32_t change_mask, bool flush)
|
||||
add_port_update (PinosStream *stream, uint32_t change_mask)
|
||||
{
|
||||
PinosStreamImpl *impl = SPA_CONTAINER_OF (stream, PinosStreamImpl, this);
|
||||
|
||||
|
|
@ -384,7 +372,7 @@ send_have_output (PinosStream *stream)
|
|||
}
|
||||
|
||||
static void
|
||||
add_request_clock_update (PinosStream *stream, bool flush)
|
||||
add_request_clock_update (PinosStream *stream)
|
||||
{
|
||||
PinosStreamImpl *impl = SPA_CONTAINER_OF (stream, PinosStreamImpl, this);
|
||||
SpaEventNodeRequestClockUpdate rcu =
|
||||
|
|
@ -397,8 +385,7 @@ add_request_clock_update (PinosStream *stream, bool flush)
|
|||
static void
|
||||
add_async_complete (PinosStream *stream,
|
||||
uint32_t seq,
|
||||
SpaResult res,
|
||||
bool flush)
|
||||
SpaResult res)
|
||||
{
|
||||
PinosStreamImpl *impl = SPA_CONTAINER_OF (stream, PinosStreamImpl, this);
|
||||
SpaEventNodeAsyncComplete ac =
|
||||
|
|
@ -413,14 +400,12 @@ do_node_init (PinosStream *stream)
|
|||
PinosStreamImpl *impl = SPA_CONTAINER_OF (stream, PinosStreamImpl, this);
|
||||
|
||||
add_node_update (stream, PINOS_MESSAGE_NODE_UPDATE_MAX_INPUTS |
|
||||
PINOS_MESSAGE_NODE_UPDATE_MAX_OUTPUTS,
|
||||
false);
|
||||
PINOS_MESSAGE_NODE_UPDATE_MAX_OUTPUTS);
|
||||
|
||||
impl->port_info.flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS;
|
||||
add_port_update (stream, PINOS_MESSAGE_PORT_UPDATE_POSSIBLE_FORMATS |
|
||||
PINOS_MESSAGE_PORT_UPDATE_INFO,
|
||||
false);
|
||||
add_state_change (stream, SPA_NODE_STATE_CONFIGURE, true);
|
||||
PINOS_MESSAGE_PORT_UPDATE_INFO);
|
||||
add_async_complete (stream, 0, SPA_RESULT_OK);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -428,8 +413,7 @@ on_timeout (SpaSource *source,
|
|||
void *data)
|
||||
{
|
||||
PinosStream *stream = data;
|
||||
|
||||
add_request_clock_update (stream, true);
|
||||
add_request_clock_update (stream);
|
||||
}
|
||||
|
||||
static MemId *
|
||||
|
|
@ -606,14 +590,12 @@ handle_node_command (PinosStream *stream,
|
|||
impl->rtsocket_source,
|
||||
SPA_IO_ERR | SPA_IO_HUP);
|
||||
|
||||
add_state_change (stream, SPA_NODE_STATE_PAUSED, false);
|
||||
add_async_complete (stream, seq, SPA_RESULT_OK, true);
|
||||
add_async_complete (stream, seq, SPA_RESULT_OK);
|
||||
stream_set_state (stream, PINOS_STREAM_STATE_PAUSED, NULL);
|
||||
}
|
||||
else if (SPA_COMMAND_TYPE (command) == context->type.command_node.Start) {
|
||||
pinos_log_debug ("stream %p: start %d %d", stream, seq, impl->direction);
|
||||
add_state_change (stream, SPA_NODE_STATE_STREAMING, false);
|
||||
add_async_complete (stream, seq, SPA_RESULT_OK, true);
|
||||
add_async_complete (stream, seq, SPA_RESULT_OK);
|
||||
|
||||
pinos_loop_update_io (stream->context->loop,
|
||||
impl->rtsocket_source,
|
||||
|
|
@ -640,7 +622,7 @@ handle_node_command (PinosStream *stream,
|
|||
}
|
||||
else {
|
||||
pinos_log_warn ("unhandled node command %d", SPA_COMMAND_TYPE (command));
|
||||
add_async_complete (stream, seq, SPA_RESULT_NOT_IMPLEMENTED, true);
|
||||
add_async_complete (stream, seq, SPA_RESULT_NOT_IMPLEMENTED);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -854,18 +836,14 @@ client_node_use_buffers (void *object,
|
|||
pinos_signal_emit (&stream->add_buffer, stream, bid->id);
|
||||
}
|
||||
|
||||
if (n_buffers) {
|
||||
add_state_change (stream, SPA_NODE_STATE_PAUSED, false);
|
||||
} else {
|
||||
clear_mems (stream);
|
||||
add_state_change (stream, SPA_NODE_STATE_READY, false);
|
||||
}
|
||||
add_async_complete (stream, seq, SPA_RESULT_OK, true);
|
||||
add_async_complete (stream, seq, SPA_RESULT_OK);
|
||||
|
||||
if (n_buffers)
|
||||
stream_set_state (stream, PINOS_STREAM_STATE_PAUSED, NULL);
|
||||
else
|
||||
else {
|
||||
clear_mems (stream);
|
||||
stream_set_state (stream, PINOS_STREAM_STATE_READY, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1031,19 +1009,15 @@ pinos_stream_finish_format (PinosStream *stream,
|
|||
|
||||
if (SPA_RESULT_IS_OK (res)) {
|
||||
add_port_update (stream, PINOS_MESSAGE_PORT_UPDATE_INFO |
|
||||
PINOS_MESSAGE_PORT_UPDATE_FORMAT,
|
||||
false);
|
||||
if (impl->format) {
|
||||
add_state_change (stream, SPA_NODE_STATE_READY, false);
|
||||
} else {
|
||||
PINOS_MESSAGE_PORT_UPDATE_FORMAT);
|
||||
|
||||
if (!impl->format)
|
||||
clear_buffers (stream);
|
||||
add_state_change (stream, SPA_NODE_STATE_CONFIGURE, false);
|
||||
}
|
||||
}
|
||||
impl->port_info.params = NULL;
|
||||
impl->port_info.n_params = 0;
|
||||
|
||||
add_async_complete (stream, impl->pending_seq, res, true);
|
||||
add_async_complete (stream, impl->pending_seq, res);
|
||||
|
||||
impl->pending_seq = SPA_ID_INVALID;
|
||||
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ transport_area_get_size (PinosTransportArea *area)
|
|||
}
|
||||
|
||||
static void
|
||||
transport_setup_area (void *p, PinosTransport *trans)
|
||||
transport_setup_area (void *p, PinosTransport *trans, bool reset)
|
||||
{
|
||||
PinosTransportArea *a;
|
||||
int i;
|
||||
|
|
@ -66,36 +66,37 @@ transport_setup_area (void *p, PinosTransport *trans)
|
|||
p = SPA_MEMBER (p, sizeof (PinosTransportArea), SpaPortIO);
|
||||
|
||||
trans->inputs = p;
|
||||
for (i = 0; i < a->max_inputs; i++) {
|
||||
trans->inputs[i].state = SPA_PORT_STATE_FLAG_NONE;
|
||||
trans->inputs[i].flags = SPA_PORT_IO_FLAG_NONE;
|
||||
trans->inputs[i].buffer_id = SPA_ID_INVALID;
|
||||
trans->inputs[i].status = SPA_RESULT_OK;
|
||||
}
|
||||
p = SPA_MEMBER (p, a->max_inputs * sizeof (SpaPortIO), void);
|
||||
|
||||
trans->outputs = p;
|
||||
for (i = 0; i < a->max_outputs; i++) {
|
||||
trans->outputs[i].state = SPA_PORT_STATE_FLAG_NONE;
|
||||
trans->outputs[i].flags = SPA_PORT_IO_FLAG_NONE;
|
||||
trans->outputs[i].buffer_id = SPA_ID_INVALID;
|
||||
trans->outputs[i].status = SPA_RESULT_OK;
|
||||
}
|
||||
p = SPA_MEMBER (p, a->max_outputs * sizeof (SpaPortIO), void);
|
||||
|
||||
trans->input_buffer = p;
|
||||
spa_ringbuffer_init (trans->input_buffer, INPUT_BUFFER_SIZE);
|
||||
p = SPA_MEMBER (p, sizeof (SpaRingbuffer), void);
|
||||
|
||||
trans->input_data = p;
|
||||
p = SPA_MEMBER (p, INPUT_BUFFER_SIZE, void);
|
||||
|
||||
trans->output_buffer = p;
|
||||
spa_ringbuffer_init (trans->output_buffer, OUTPUT_BUFFER_SIZE);
|
||||
p = SPA_MEMBER (p, sizeof (SpaRingbuffer), void);
|
||||
|
||||
trans->output_data = p;
|
||||
p = SPA_MEMBER (p, OUTPUT_BUFFER_SIZE, void);
|
||||
|
||||
if (reset) {
|
||||
for (i = 0; i < a->max_inputs; i++) {
|
||||
trans->inputs[i].flags = 0;
|
||||
trans->inputs[i].buffer_id = SPA_ID_INVALID;
|
||||
trans->inputs[i].status = SPA_RESULT_OK;
|
||||
}
|
||||
for (i = 0; i < a->max_outputs; i++) {
|
||||
trans->outputs[i].flags = 0;
|
||||
trans->outputs[i].buffer_id = SPA_ID_INVALID;
|
||||
trans->outputs[i].status = SPA_RESULT_OK;
|
||||
}
|
||||
spa_ringbuffer_init (trans->input_buffer, INPUT_BUFFER_SIZE);
|
||||
spa_ringbuffer_init (trans->output_buffer, OUTPUT_BUFFER_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
PinosTransport *
|
||||
|
|
@ -127,7 +128,7 @@ pinos_transport_new (uint32_t max_inputs,
|
|||
&impl->mem);
|
||||
|
||||
memcpy (impl->mem.ptr, &area, sizeof (PinosTransportArea));
|
||||
transport_setup_area (impl->mem.ptr, trans);
|
||||
transport_setup_area (impl->mem.ptr, trans, true);
|
||||
|
||||
return trans;
|
||||
}
|
||||
|
|
@ -158,7 +159,7 @@ pinos_transport_new_from_info (PinosTransportInfo *info)
|
|||
|
||||
impl->offset = info->offset;
|
||||
|
||||
transport_setup_area (impl->mem.ptr, trans);
|
||||
transport_setup_area (impl->mem.ptr, trans, false);
|
||||
|
||||
tmp = trans->output_buffer;
|
||||
trans->output_buffer = trans->input_buffer;
|
||||
|
|
|
|||
|
|
@ -624,7 +624,7 @@ gst_pinos_sink_setcaps (GstBaseSink * bsink, GstCaps * caps)
|
|||
|
||||
if (!gst_buffer_pool_is_active (GST_BUFFER_POOL_CAST (pinossink->pool))) {
|
||||
GstStructure *config = gst_buffer_pool_get_config (GST_BUFFER_POOL_CAST (pinossink->pool));
|
||||
gst_buffer_pool_config_set_params (config, caps, 8192, 8, 16);
|
||||
gst_buffer_pool_config_set_params (config, caps, 8192, 16, 32);
|
||||
gst_buffer_pool_set_config (GST_BUFFER_POOL_CAST (pinossink->pool), config);
|
||||
gst_buffer_pool_set_active (GST_BUFFER_POOL_CAST (pinossink->pool), TRUE);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,15 @@ pinos_module_autolink = shared_library('pinos-module-autolink', [ 'module-autoli
|
|||
dependencies : [mathlib, dl_lib, pinos_dep, pinoscore_dep],
|
||||
)
|
||||
|
||||
pinos_module_mixer = shared_library('pinos-module-mixer', [ 'module-mixer.c' ],
|
||||
c_args : pinos_module_c_args,
|
||||
include_directories : [configinc, spa_inc],
|
||||
link_with : spalib,
|
||||
install : true,
|
||||
install_dir : '@0@/pinos-0.1'.format(get_option('libdir')),
|
||||
dependencies : [mathlib, dl_lib, pinos_dep, pinoscore_dep],
|
||||
)
|
||||
|
||||
pinos_module_protocol_dbus = shared_library('pinos-module-protocol-dbus', [ 'module-protocol-dbus.c', gdbus_target ],
|
||||
c_args : pinos_module_c_args,
|
||||
include_directories : [configinc, spa_inc],
|
||||
|
|
|
|||
188
pinos/modules/module-mixer.c
Normal file
188
pinos/modules/module-mixer.c
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
/* Pinos
|
||||
* Copyright (C) 2017 Wim Taymans <wim.taymans@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "pinos/server/core.h"
|
||||
#include "pinos/server/module.h"
|
||||
|
||||
#define AUDIOMIXER_LIB "build/spa/plugins/audiomixer/libspa-audiomixer.so"
|
||||
|
||||
typedef struct {
|
||||
PinosCore *core;
|
||||
PinosProperties *properties;
|
||||
|
||||
void *hnd;
|
||||
const SpaHandleFactory *factory;
|
||||
|
||||
PinosListener check_send;
|
||||
PinosListener check_dispatch;
|
||||
} ModuleImpl;
|
||||
|
||||
static const SpaHandleFactory *
|
||||
find_factory (ModuleImpl *impl)
|
||||
{
|
||||
SpaEnumHandleFactoryFunc enum_func;
|
||||
uint32_t index;
|
||||
const SpaHandleFactory *factory = NULL;
|
||||
SpaResult res;
|
||||
|
||||
if ((impl->hnd = dlopen (AUDIOMIXER_LIB, RTLD_NOW)) == NULL) {
|
||||
pinos_log_error ("can't load %s: %s", AUDIOMIXER_LIB, dlerror());
|
||||
return NULL;
|
||||
}
|
||||
if ((enum_func = dlsym (impl->hnd, "spa_enum_handle_factory")) == NULL) {
|
||||
pinos_log_error ("can't find enum function");
|
||||
goto no_symbol;
|
||||
}
|
||||
|
||||
for (index = 0; ; index++) {
|
||||
if ((res = enum_func (&factory, index)) < 0) {
|
||||
if (res != SPA_RESULT_ENUM_END)
|
||||
pinos_log_error ("can't enumerate factories: %d", res);
|
||||
goto enum_failed;
|
||||
}
|
||||
if (strcmp (factory->name, "audiomixer") == 0)
|
||||
break;
|
||||
}
|
||||
return factory;
|
||||
|
||||
enum_failed:
|
||||
no_symbol:
|
||||
dlclose (impl->hnd);
|
||||
impl->hnd = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static PinosNode *
|
||||
make_node (ModuleImpl *impl)
|
||||
{
|
||||
SpaHandle *handle;
|
||||
SpaResult res;
|
||||
void *iface;
|
||||
SpaNode *spa_node;
|
||||
SpaClock *spa_clock;
|
||||
PinosNode *node;
|
||||
|
||||
handle = calloc (1, impl->factory->size);
|
||||
if ((res = spa_handle_factory_init (impl->factory,
|
||||
handle,
|
||||
NULL,
|
||||
impl->core->support,
|
||||
impl->core->n_support)) < 0) {
|
||||
pinos_log_error ("can't make factory instance: %d", res);
|
||||
goto init_failed;
|
||||
}
|
||||
if ((res = spa_handle_get_interface (handle,
|
||||
impl->core->type.spa_node,
|
||||
&iface)) < 0) {
|
||||
pinos_log_error ("can't get interface %d", res);
|
||||
goto interface_failed;
|
||||
}
|
||||
spa_node = iface;
|
||||
|
||||
if ((res = spa_handle_get_interface (handle,
|
||||
impl->core->type.spa_clock,
|
||||
&iface)) < 0) {
|
||||
iface = NULL;
|
||||
}
|
||||
spa_clock = iface;
|
||||
|
||||
node = pinos_node_new (impl->core,
|
||||
"audiomixer",
|
||||
false,
|
||||
spa_node,
|
||||
spa_clock,
|
||||
NULL);
|
||||
return node;
|
||||
|
||||
interface_failed:
|
||||
spa_handle_clear (handle);
|
||||
init_failed:
|
||||
free (handle);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static ModuleImpl *
|
||||
module_new (PinosCore *core,
|
||||
PinosProperties *properties)
|
||||
{
|
||||
ModuleImpl *impl;
|
||||
PinosNode *n;
|
||||
|
||||
impl = calloc (1, sizeof (ModuleImpl));
|
||||
pinos_log_debug ("module %p: new", impl);
|
||||
|
||||
impl->core = core;
|
||||
impl->properties = properties;
|
||||
|
||||
impl->factory = find_factory (impl);
|
||||
|
||||
spa_list_for_each (n, &core->node_list, link) {
|
||||
const char *str;
|
||||
char *error;
|
||||
PinosNode *node;
|
||||
PinosPort *ip, *op;
|
||||
|
||||
if (n->global == NULL)
|
||||
continue;
|
||||
|
||||
if (n->properties == NULL)
|
||||
continue;
|
||||
|
||||
if ((str = pinos_properties_get (n->properties, "media.class")) == NULL)
|
||||
continue;
|
||||
|
||||
if (strcmp (str, "Audio/Sink") != 0)
|
||||
continue;
|
||||
|
||||
if ((ip = pinos_node_get_free_port (n, PINOS_DIRECTION_INPUT)) == NULL)
|
||||
continue;
|
||||
|
||||
node = make_node (impl);
|
||||
op = pinos_node_get_free_port (node, PINOS_DIRECTION_OUTPUT);
|
||||
if (op == NULL)
|
||||
continue;
|
||||
|
||||
pinos_port_link (op, ip, NULL, NULL, &error);
|
||||
}
|
||||
return impl;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
module_destroy (ModuleImpl *impl)
|
||||
{
|
||||
pinos_log_debug ("module %p: destroy", impl);
|
||||
|
||||
free (impl);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool
|
||||
pinos__module_init (PinosModule * module, const char * args)
|
||||
{
|
||||
module_new (module->core, NULL);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -113,6 +113,7 @@ add_item (PinosSpaMonitor *this, SpaMonitorItem *item)
|
|||
mitem->id = strdup (id);
|
||||
mitem->node = pinos_node_new (impl->core,
|
||||
name,
|
||||
false,
|
||||
node_iface,
|
||||
clock_iface,
|
||||
props);
|
||||
|
|
|
|||
|
|
@ -113,6 +113,7 @@ pinos_spa_node_load (PinosCore *core,
|
|||
|
||||
this->node = pinos_node_new (core,
|
||||
name,
|
||||
false,
|
||||
spa_node,
|
||||
spa_clock,
|
||||
properties);
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ typedef struct {
|
|||
SpaFormat *format;
|
||||
uint32_t n_formats;
|
||||
SpaFormat **formats;
|
||||
void *io;
|
||||
SpaPortIO *io;
|
||||
|
||||
uint32_t n_buffers;
|
||||
ProxyBuffer buffers[MAX_BUFFERS];
|
||||
|
|
@ -129,15 +129,6 @@ typedef struct
|
|||
int data_fd;
|
||||
} PinosClientNodeImpl;
|
||||
|
||||
static void
|
||||
send_async_complete (SpaProxy *this, uint32_t seq, SpaResult res)
|
||||
{
|
||||
PinosCore *core = this->pnode->core;
|
||||
SpaEventNodeAsyncComplete ac = SPA_EVENT_NODE_ASYNC_COMPLETE_INIT (core->type.event_node.AsyncComplete,
|
||||
seq, res);
|
||||
this->event_cb (&this->node, (SpaEvent *)&ac, this->user_data);
|
||||
}
|
||||
|
||||
static SpaResult
|
||||
clear_buffers (SpaProxy *this, SpaProxyPort *port)
|
||||
{
|
||||
|
|
@ -758,7 +749,6 @@ spa_proxy_node_port_reuse_buffer (SpaNode *node,
|
|||
{
|
||||
SpaProxy *this;
|
||||
PinosNode *pnode;
|
||||
//uint64_t cmd = 1;
|
||||
|
||||
if (node == NULL)
|
||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||
|
|
@ -769,11 +759,11 @@ spa_proxy_node_port_reuse_buffer (SpaNode *node,
|
|||
if (!CHECK_OUT_PORT (this, SPA_DIRECTION_OUTPUT, port_id))
|
||||
return SPA_RESULT_INVALID_PORT;
|
||||
|
||||
spa_log_trace (this->log, "reuse buffer %d", buffer_id);
|
||||
{
|
||||
SpaEventNodeReuseBuffer rb = SPA_EVENT_NODE_REUSE_BUFFER_INIT (pnode->core->type.event_node.ReuseBuffer,
|
||||
port_id, buffer_id);
|
||||
pinos_transport_add_event (pnode->transport, (SpaEvent *)&rb);
|
||||
//write (this->data_source.fd, &cmd, 8);
|
||||
}
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
|
|
@ -815,15 +805,23 @@ static SpaResult
|
|||
spa_proxy_node_process_output (SpaNode *node)
|
||||
{
|
||||
SpaProxy *this;
|
||||
int i;
|
||||
|
||||
if (node == NULL)
|
||||
return SPA_RESULT_INVALID_ARGUMENTS;
|
||||
|
||||
this = SPA_CONTAINER_OF (node, SpaProxy, node);
|
||||
|
||||
for (i = 0; i < MAX_OUTPUTS; i++) {
|
||||
SpaPortIO *io = this->out_ports[i].io;
|
||||
if (io && io->buffer_id != SPA_ID_INVALID) {
|
||||
spa_proxy_node_port_reuse_buffer (node, i, io->buffer_id);
|
||||
io->buffer_id = SPA_ID_INVALID;
|
||||
}
|
||||
}
|
||||
send_need_input (this);
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
return SPA_RESULT_HAVE_OUTPUT;
|
||||
}
|
||||
|
||||
static SpaResult
|
||||
|
|
@ -893,22 +891,6 @@ client_node_port_update (void *object,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
client_node_state_change (void *object,
|
||||
SpaNodeState state)
|
||||
{
|
||||
PinosResource *resource = object;
|
||||
PinosClientNode *node = resource->object;
|
||||
PinosClientNodeImpl *impl = SPA_CONTAINER_OF (node, PinosClientNodeImpl, this);
|
||||
SpaProxy *this = &impl->proxy;
|
||||
SpaNodeState old = this->node.state;
|
||||
|
||||
spa_log_info (this->log, "proxy %p: got node state change %d -> %d", this, old, state);
|
||||
this->node.state = state;
|
||||
if (old == SPA_NODE_STATE_INIT)
|
||||
send_async_complete (this, 0, SPA_RESULT_OK);
|
||||
}
|
||||
|
||||
static void
|
||||
client_node_event (void *object,
|
||||
SpaEvent *event)
|
||||
|
|
@ -932,7 +914,6 @@ client_node_destroy (void *object)
|
|||
static PinosClientNodeMethods client_node_methods = {
|
||||
&client_node_update,
|
||||
&client_node_port_update,
|
||||
&client_node_state_change,
|
||||
&client_node_event,
|
||||
&client_node_destroy,
|
||||
};
|
||||
|
|
@ -965,7 +946,6 @@ proxy_on_data_fd_events (SpaSource *source)
|
|||
static const SpaNode proxy_node = {
|
||||
sizeof (SpaNode),
|
||||
NULL,
|
||||
SPA_NODE_STATE_INIT,
|
||||
spa_proxy_node_get_props,
|
||||
spa_proxy_node_set_props,
|
||||
spa_proxy_node_send_command,
|
||||
|
|
@ -1153,6 +1133,7 @@ pinos_client_node_new (PinosClient *client,
|
|||
|
||||
this->node = pinos_node_new (client->core,
|
||||
name,
|
||||
true,
|
||||
&impl->proxy.node,
|
||||
NULL,
|
||||
properties);
|
||||
|
|
|
|||
|
|
@ -543,20 +543,22 @@ pinos_core_find_format (PinosCore *core,
|
|||
SpaFormat **format_filterss,
|
||||
char **error)
|
||||
{
|
||||
SpaNodeState out_state, in_state;
|
||||
uint32_t out_state, in_state;
|
||||
SpaResult res;
|
||||
SpaFormat *filter = NULL, *format;
|
||||
uint32_t iidx = 0, oidx = 0;
|
||||
|
||||
out_state = output->node->node->state;
|
||||
in_state = input->node->node->state;
|
||||
out_state = output->state;
|
||||
in_state = input->state;
|
||||
|
||||
if (out_state > SPA_NODE_STATE_CONFIGURE && output->node->state == PINOS_NODE_STATE_IDLE)
|
||||
out_state = SPA_NODE_STATE_CONFIGURE;
|
||||
if (in_state > SPA_NODE_STATE_CONFIGURE && input->node->state == PINOS_NODE_STATE_IDLE)
|
||||
in_state = SPA_NODE_STATE_CONFIGURE;
|
||||
pinos_log_debug ("core %p: finding best format %d %d", core, out_state, in_state);
|
||||
|
||||
if (in_state == SPA_NODE_STATE_CONFIGURE && out_state > SPA_NODE_STATE_CONFIGURE) {
|
||||
if (out_state > SPA_PORT_STATE_CONFIGURE && output->node->state == PINOS_NODE_STATE_IDLE)
|
||||
out_state = SPA_PORT_STATE_CONFIGURE;
|
||||
if (in_state > SPA_PORT_STATE_CONFIGURE && input->node->state == PINOS_NODE_STATE_IDLE)
|
||||
in_state = SPA_PORT_STATE_CONFIGURE;
|
||||
|
||||
if (in_state == SPA_PORT_STATE_CONFIGURE && out_state > SPA_PORT_STATE_CONFIGURE) {
|
||||
/* only input needs format */
|
||||
if ((res = spa_node_port_get_format (output->node->node,
|
||||
SPA_DIRECTION_OUTPUT,
|
||||
|
|
@ -565,7 +567,7 @@ pinos_core_find_format (PinosCore *core,
|
|||
asprintf (error, "error get output format: %d", res);
|
||||
goto error;
|
||||
}
|
||||
} else if (out_state == SPA_NODE_STATE_CONFIGURE && in_state > SPA_NODE_STATE_CONFIGURE) {
|
||||
} else if (out_state == SPA_PORT_STATE_CONFIGURE && in_state > SPA_PORT_STATE_CONFIGURE) {
|
||||
/* only output needs format */
|
||||
if ((res = spa_node_port_get_format (input->node->node,
|
||||
SPA_DIRECTION_INPUT,
|
||||
|
|
@ -574,7 +576,7 @@ pinos_core_find_format (PinosCore *core,
|
|||
asprintf (error, "error get input format: %d", res);
|
||||
goto error;
|
||||
}
|
||||
} else if (in_state == SPA_NODE_STATE_CONFIGURE && out_state == SPA_NODE_STATE_CONFIGURE) {
|
||||
} else if (in_state == SPA_PORT_STATE_CONFIGURE && out_state == SPA_PORT_STATE_CONFIGURE) {
|
||||
again:
|
||||
/* both ports need a format */
|
||||
pinos_log_debug ("core %p: finding best format", core);
|
||||
|
|
|
|||
|
|
@ -76,14 +76,14 @@ pinos_link_update_state (PinosLink *link,
|
|||
}
|
||||
|
||||
static SpaResult
|
||||
do_negotiate (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
|
||||
do_negotiate (PinosLink *this, uint32_t in_state, uint32_t out_state)
|
||||
{
|
||||
PinosLinkImpl *impl = SPA_CONTAINER_OF (this, PinosLinkImpl, this);
|
||||
SpaResult res = SPA_RESULT_ERROR, res2;
|
||||
SpaFormat *format;
|
||||
char *error = NULL;
|
||||
|
||||
if (in_state != SPA_NODE_STATE_CONFIGURE && out_state != SPA_NODE_STATE_CONFIGURE)
|
||||
if (in_state != SPA_PORT_STATE_CONFIGURE && out_state != SPA_PORT_STATE_CONFIGURE)
|
||||
return SPA_RESULT_OK;
|
||||
|
||||
pinos_link_update_state (this, PINOS_LINK_STATE_NEGOTIATING, NULL);
|
||||
|
|
@ -98,20 +98,20 @@ do_negotiate (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
|
|||
if (format == NULL)
|
||||
goto error;
|
||||
|
||||
if (out_state > SPA_NODE_STATE_CONFIGURE && this->output->node->state == PINOS_NODE_STATE_IDLE) {
|
||||
if (out_state > SPA_PORT_STATE_CONFIGURE && this->output->node->state == PINOS_NODE_STATE_IDLE) {
|
||||
pinos_node_set_state (this->output->node, PINOS_NODE_STATE_SUSPENDED);
|
||||
out_state = SPA_NODE_STATE_CONFIGURE;
|
||||
out_state = SPA_PORT_STATE_CONFIGURE;
|
||||
}
|
||||
if (in_state > SPA_NODE_STATE_CONFIGURE && this->input->node->state == PINOS_NODE_STATE_IDLE) {
|
||||
if (in_state > SPA_PORT_STATE_CONFIGURE && this->input->node->state == PINOS_NODE_STATE_IDLE) {
|
||||
pinos_node_set_state (this->input->node, PINOS_NODE_STATE_SUSPENDED);
|
||||
in_state = SPA_NODE_STATE_CONFIGURE;
|
||||
in_state = SPA_PORT_STATE_CONFIGURE;
|
||||
}
|
||||
|
||||
pinos_log_debug ("link %p: doing set format", this);
|
||||
if (pinos_log_level_enabled (SPA_LOG_LEVEL_DEBUG))
|
||||
spa_debug_format (format, this->core->type.map);
|
||||
|
||||
if (out_state == SPA_NODE_STATE_CONFIGURE) {
|
||||
if (out_state == SPA_PORT_STATE_CONFIGURE) {
|
||||
pinos_log_debug ("link %p: doing set format on output", this);
|
||||
if ((res = spa_node_port_set_format (this->output->node->node,
|
||||
SPA_DIRECTION_OUTPUT,
|
||||
|
|
@ -121,9 +121,10 @@ do_negotiate (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
|
|||
asprintf (&error, "error set output format: %d", res);
|
||||
goto error;
|
||||
}
|
||||
this->output->state = SPA_PORT_STATE_READY;
|
||||
pinos_work_queue_add (impl->work, this->output->node, res, NULL, NULL);
|
||||
}
|
||||
if (in_state == SPA_NODE_STATE_CONFIGURE) {
|
||||
if (in_state == SPA_PORT_STATE_CONFIGURE) {
|
||||
pinos_log_debug ("link %p: doing set format on input", this);
|
||||
if ((res2 = spa_node_port_set_format (this->input->node->node,
|
||||
SPA_DIRECTION_INPUT,
|
||||
|
|
@ -133,6 +134,7 @@ do_negotiate (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
|
|||
asprintf (&error, "error set input format: %d", res2);
|
||||
goto error;
|
||||
}
|
||||
this->input->state = SPA_PORT_STATE_READY;
|
||||
pinos_work_queue_add (impl->work, this->input->node, res2, NULL, NULL);
|
||||
res = res2 != SPA_RESULT_OK ? res2 : res;
|
||||
}
|
||||
|
|
@ -322,7 +324,7 @@ alloc_buffers (PinosLink *this,
|
|||
}
|
||||
|
||||
static SpaResult
|
||||
do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
|
||||
do_allocation (PinosLink *this, uint32_t in_state, uint32_t out_state)
|
||||
{
|
||||
PinosLinkImpl *impl = SPA_CONTAINER_OF (this, PinosLinkImpl, this);
|
||||
SpaResult res;
|
||||
|
|
@ -330,7 +332,7 @@ do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
|
|||
SpaPortInfoFlags in_flags, out_flags;
|
||||
char *error = NULL;
|
||||
|
||||
if (in_state != SPA_NODE_STATE_READY && out_state != SPA_NODE_STATE_READY)
|
||||
if (in_state != SPA_PORT_STATE_READY && out_state != SPA_PORT_STATE_READY)
|
||||
return SPA_RESULT_OK;
|
||||
|
||||
pinos_link_update_state (this, PINOS_LINK_STATE_ALLOCATING, NULL);
|
||||
|
|
@ -361,7 +363,7 @@ do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
|
|||
this->input->node->live = true;
|
||||
}
|
||||
|
||||
if (in_state == SPA_NODE_STATE_READY && out_state == SPA_NODE_STATE_READY) {
|
||||
if (in_state == SPA_PORT_STATE_READY && out_state == SPA_PORT_STATE_READY) {
|
||||
if ((out_flags & SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS) &&
|
||||
(in_flags & SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS)) {
|
||||
out_flags = SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS;
|
||||
|
|
@ -383,10 +385,10 @@ do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
|
|||
res = SPA_RESULT_ERROR;
|
||||
goto error;
|
||||
}
|
||||
} else if (in_state == SPA_NODE_STATE_READY && out_state > SPA_NODE_STATE_READY) {
|
||||
} else if (in_state == SPA_PORT_STATE_READY && out_state > SPA_PORT_STATE_READY) {
|
||||
out_flags &= ~SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS;
|
||||
in_flags &= ~SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS;
|
||||
} else if (out_state == SPA_NODE_STATE_READY && in_state > SPA_NODE_STATE_READY) {
|
||||
} else if (out_state == SPA_PORT_STATE_READY && in_state > SPA_PORT_STATE_READY) {
|
||||
in_flags &= ~SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS;
|
||||
out_flags &= ~SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS;
|
||||
} else {
|
||||
|
|
@ -505,6 +507,7 @@ do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
|
|||
asprintf (&error, "error alloc output buffers: %d", res);
|
||||
goto error;
|
||||
}
|
||||
this->output->state = SPA_PORT_STATE_PAUSED;
|
||||
pinos_work_queue_add (impl->work, this->output->node, res, NULL, NULL);
|
||||
this->output->buffers = impl->buffers;
|
||||
this->output->n_buffers = impl->n_buffers;
|
||||
|
|
@ -521,6 +524,7 @@ do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
|
|||
asprintf (&error, "error alloc input buffers: %d", res);
|
||||
goto error;
|
||||
}
|
||||
this->input->state = SPA_PORT_STATE_PAUSED;
|
||||
pinos_work_queue_add (impl->work, this->input->node, res, NULL, NULL);
|
||||
this->input->buffers = impl->buffers;
|
||||
this->input->n_buffers = impl->n_buffers;
|
||||
|
|
@ -541,6 +545,7 @@ do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
|
|||
asprintf (&error, "error use input buffers: %d", res);
|
||||
goto error;
|
||||
}
|
||||
this->input->state = SPA_PORT_STATE_PAUSED;
|
||||
pinos_work_queue_add (impl->work, this->input->node, res, NULL, NULL);
|
||||
this->input->buffers = impl->buffers;
|
||||
this->input->n_buffers = impl->n_buffers;
|
||||
|
|
@ -556,6 +561,7 @@ do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
|
|||
asprintf (&error, "error use output buffers: %d", res);
|
||||
goto error;
|
||||
}
|
||||
this->output->state = SPA_PORT_STATE_PAUSED;
|
||||
pinos_work_queue_add (impl->work, this->output->node, res, NULL, NULL);
|
||||
this->output->buffers = impl->buffers;
|
||||
this->output->n_buffers = impl->n_buffers;
|
||||
|
|
@ -581,24 +587,26 @@ error:
|
|||
}
|
||||
|
||||
static SpaResult
|
||||
do_start (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
|
||||
do_start (PinosLink *this, uint32_t in_state, uint32_t out_state)
|
||||
{
|
||||
SpaResult res = SPA_RESULT_OK;
|
||||
PinosLinkImpl *impl = SPA_CONTAINER_OF (this, PinosLinkImpl, this);
|
||||
|
||||
if (in_state < SPA_NODE_STATE_PAUSED || out_state < SPA_NODE_STATE_PAUSED)
|
||||
if (in_state < SPA_PORT_STATE_PAUSED || out_state < SPA_PORT_STATE_PAUSED)
|
||||
return SPA_RESULT_OK;
|
||||
else if (in_state == SPA_NODE_STATE_STREAMING && out_state == SPA_NODE_STATE_STREAMING) {
|
||||
else if (in_state == SPA_PORT_STATE_STREAMING && out_state == SPA_PORT_STATE_STREAMING) {
|
||||
pinos_link_update_state (this, PINOS_LINK_STATE_RUNNING, NULL);
|
||||
} else {
|
||||
pinos_link_update_state (this, PINOS_LINK_STATE_PAUSED, NULL);
|
||||
|
||||
if (in_state == SPA_NODE_STATE_PAUSED) {
|
||||
if (in_state == SPA_PORT_STATE_PAUSED) {
|
||||
res = pinos_node_set_state (this->input->node, PINOS_NODE_STATE_RUNNING);
|
||||
pinos_work_queue_add (impl->work, this->input->node, res, NULL, NULL);
|
||||
this->input->state = SPA_PORT_STATE_STREAMING;
|
||||
}
|
||||
if (out_state == SPA_NODE_STATE_PAUSED) {
|
||||
if (out_state == SPA_PORT_STATE_PAUSED) {
|
||||
res = pinos_node_set_state (this->output->node, PINOS_NODE_STATE_RUNNING);
|
||||
this->output->state = SPA_PORT_STATE_STREAMING;
|
||||
pinos_work_queue_add (impl->work, this->input->node, res, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
|
@ -611,7 +619,7 @@ check_states (PinosLink *this,
|
|||
SpaResult res)
|
||||
{
|
||||
PinosLinkImpl *impl = SPA_CONTAINER_OF (this, PinosLinkImpl, this);
|
||||
SpaNodeState in_state, out_state;
|
||||
uint32_t in_state, out_state;
|
||||
|
||||
again:
|
||||
if (this->state == PINOS_LINK_STATE_ERROR)
|
||||
|
|
@ -624,8 +632,8 @@ again:
|
|||
this->output->node->state == PINOS_NODE_STATE_ERROR)
|
||||
return SPA_RESULT_ERROR;
|
||||
|
||||
in_state = this->input->node->node->state;
|
||||
out_state = this->output->node->node->state;
|
||||
in_state = this->input->state;
|
||||
out_state = this->output->state;
|
||||
|
||||
pinos_log_debug ("link %p: input state %d, output state %d", this, in_state, out_state);
|
||||
|
||||
|
|
@ -638,9 +646,9 @@ again:
|
|||
if ((res = do_start (this, in_state, out_state)) != SPA_RESULT_OK)
|
||||
goto exit;
|
||||
|
||||
if (this->input->node->node->state != in_state)
|
||||
if (this->input->state != in_state)
|
||||
goto again;
|
||||
if (this->output->node->node->state != out_state)
|
||||
if (this->output->state != out_state)
|
||||
goto again;
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
|
|
@ -737,6 +745,7 @@ pinos_link_activate (PinosLink *this)
|
|||
{
|
||||
PinosLinkImpl *impl = SPA_CONTAINER_OF (this, PinosLinkImpl, this);
|
||||
|
||||
pinos_log_debug ("link %p: activate", this);
|
||||
pinos_work_queue_add (impl->work,
|
||||
this,
|
||||
SPA_RESULT_WAIT_SYNC,
|
||||
|
|
@ -902,6 +911,7 @@ clear_port_buffers (PinosLink *link, PinosPort *port)
|
|||
port->direction,
|
||||
port->port_id,
|
||||
NULL, 0);
|
||||
port->state = SPA_PORT_STATE_READY;
|
||||
port->buffers = NULL;
|
||||
port->n_buffers = 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,9 @@ typedef struct
|
|||
{
|
||||
PinosNode this;
|
||||
|
||||
#define STATE_IN 0
|
||||
#define STATE_OUT 1
|
||||
int state;
|
||||
PinosWorkQueue *work;
|
||||
|
||||
bool async_init;
|
||||
|
|
@ -41,13 +44,14 @@ typedef struct
|
|||
static void init_complete (PinosNode *this);
|
||||
|
||||
static void
|
||||
update_port_ids (PinosNode *node, bool create)
|
||||
update_port_ids (PinosNode *node)
|
||||
{
|
||||
PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, this);
|
||||
uint32_t *input_port_ids, *output_port_ids;
|
||||
uint32_t n_input_ports, n_output_ports, max_input_ports, max_output_ports;
|
||||
uint32_t i;
|
||||
SpaList *ports;
|
||||
SpaResult res;
|
||||
|
||||
if (node->node == NULL)
|
||||
return;
|
||||
|
|
@ -58,6 +62,15 @@ update_port_ids (PinosNode *node, bool create)
|
|||
&n_output_ports,
|
||||
&max_output_ports);
|
||||
|
||||
node->transport = pinos_transport_new (max_input_ports,
|
||||
max_output_ports);
|
||||
|
||||
node->input_port_map = calloc (max_input_ports, sizeof (PinosPort *));
|
||||
node->output_port_map = calloc (max_output_ports, sizeof (PinosPort *));
|
||||
|
||||
node->transport->area->n_inputs = n_input_ports;
|
||||
node->transport->area->n_outputs = n_output_ports;
|
||||
|
||||
input_port_ids = alloca (sizeof (uint32_t) * n_input_ports);
|
||||
output_port_ids = alloca (sizeof (uint32_t) * n_output_ports);
|
||||
|
||||
|
|
@ -67,9 +80,6 @@ update_port_ids (PinosNode *node, bool create)
|
|||
max_output_ports,
|
||||
output_port_ids);
|
||||
|
||||
node->input_port_map = realloc (node->input_port_map, sizeof (PinosPort *) * max_input_ports);
|
||||
node->output_port_map = realloc (node->output_port_map, sizeof (PinosPort *) * max_output_ports);
|
||||
|
||||
pinos_log_debug ("node %p: update_port ids %u/%u, %u/%u", node,
|
||||
n_input_ports, max_input_ports, n_output_ports, max_output_ports);
|
||||
|
||||
|
|
@ -88,6 +98,10 @@ update_port_ids (PinosNode *node, bool create)
|
|||
pinos_log_debug ("node %p: input port added %d", node, input_port_ids[i]);
|
||||
|
||||
np = pinos_port_new (node, PINOS_DIRECTION_INPUT, input_port_ids[i]);
|
||||
np->io = &node->transport->inputs[np->port_id];
|
||||
if ((res = spa_node_port_set_io (node->node, SPA_DIRECTION_INPUT, np->port_id, np->io)) < 0)
|
||||
pinos_log_warn ("node %p: can't set input IO %d", node, res);
|
||||
|
||||
spa_list_insert (ports, &np->link);
|
||||
ports = np->link.next;
|
||||
node->input_port_map[np->port_id] = np;
|
||||
|
|
@ -123,6 +137,10 @@ update_port_ids (PinosNode *node, bool create)
|
|||
pinos_log_debug ("node %p: output port added %d", node, output_port_ids[i]);
|
||||
|
||||
np = pinos_port_new (node, PINOS_DIRECTION_OUTPUT, output_port_ids[i]);
|
||||
np->io = &node->transport->outputs[np->port_id];
|
||||
if ((res = spa_node_port_set_io (node->node, SPA_DIRECTION_OUTPUT, np->port_id, np->io)) < 0)
|
||||
pinos_log_warn ("node %p: can't set output IO %d", node, res);
|
||||
|
||||
spa_list_insert (ports, &np->link);
|
||||
ports = np->link.next;
|
||||
node->output_port_map[np->port_id] = np;
|
||||
|
|
@ -143,17 +161,6 @@ update_port_ids (PinosNode *node, bool create)
|
|||
}
|
||||
}
|
||||
|
||||
node->transport = pinos_transport_new (max_input_ports,
|
||||
max_output_ports);
|
||||
|
||||
node->transport->area->n_inputs = n_input_ports;
|
||||
node->transport->area->n_outputs = n_output_ports;
|
||||
|
||||
for (i = 0; i < max_input_ports; i++)
|
||||
spa_node_port_set_io (node->node, SPA_DIRECTION_INPUT, i, &node->transport->inputs[i]);
|
||||
for (i = 0; i < max_output_ports; i++)
|
||||
spa_node_port_set_io (node->node, SPA_DIRECTION_OUTPUT, i, &node->transport->outputs[i]);
|
||||
|
||||
pinos_signal_emit (&node->transport_changed, node);
|
||||
}
|
||||
|
||||
|
|
@ -162,9 +169,6 @@ pause_node (PinosNode *this)
|
|||
{
|
||||
SpaResult res;
|
||||
|
||||
if (this->node->state <= SPA_NODE_STATE_PAUSED)
|
||||
return SPA_RESULT_OK;
|
||||
|
||||
pinos_log_debug ("node %p: pause node", this);
|
||||
{
|
||||
SpaCommand cmd = SPA_COMMAND_INIT (this->core->type.command_node.Pause);
|
||||
|
|
@ -267,7 +271,8 @@ on_node_event (SpaNode *node, SpaEvent *event, void *user_data)
|
|||
else if (SPA_EVENT_TYPE (event) == this->core->type.event_node.NeedInput) {
|
||||
SpaResult res;
|
||||
int i;
|
||||
bool processed = false;
|
||||
|
||||
this->sched_state = STATE_IN;
|
||||
|
||||
for (i = 0; i < this->transport->area->n_inputs; i++) {
|
||||
PinosLink *link;
|
||||
|
|
@ -276,8 +281,7 @@ on_node_event (SpaNode *node, SpaEvent *event, void *user_data)
|
|||
SpaPortIO *po;
|
||||
|
||||
pi = &this->transport->inputs[i];
|
||||
if (pi->buffer_id != SPA_ID_INVALID)
|
||||
continue;
|
||||
pinos_log_trace ("node %p: need input port %d, %d", this, i, pi->buffer_id);
|
||||
|
||||
inport = this->input_port_map[i];
|
||||
spa_list_for_each (link, &inport->rt.links, rt.input_link) {
|
||||
|
|
@ -287,23 +291,58 @@ on_node_event (SpaNode *node, SpaEvent *event, void *user_data)
|
|||
outport = link->rt.output;
|
||||
po = &outport->node->transport->outputs[outport->port_id];
|
||||
|
||||
if (po->buffer_id != SPA_ID_INVALID) {
|
||||
processed = true;
|
||||
if (outport->node->sched_state == STATE_IN) {
|
||||
/* pull */
|
||||
*po = *pi;
|
||||
pi->buffer_id = SPA_ID_INVALID;
|
||||
|
||||
pinos_log_trace ("node %p: process output %p %d", outport->node, po, po->buffer_id);
|
||||
|
||||
res = spa_node_process_output (outport->node->node);
|
||||
|
||||
if (res == SPA_RESULT_NEED_INPUT) {
|
||||
on_node_event (outport->node->node, event, outport->node);
|
||||
if (outport->node->sched_state == STATE_OUT)
|
||||
goto push;
|
||||
}
|
||||
else if (res == SPA_RESULT_HAVE_OUTPUT) {
|
||||
outport->node->sched_state = STATE_OUT;
|
||||
}
|
||||
else
|
||||
pinos_log_warn ("node %p: got process output %d", outport->node, res);
|
||||
} else {
|
||||
/* push */
|
||||
push:
|
||||
*pi = *po;
|
||||
|
||||
pinos_log_trace ("node %p: process output %p %d", outport->node, po, po->buffer_id);
|
||||
|
||||
res = spa_node_process_output (outport->node->node);
|
||||
|
||||
if (res == SPA_RESULT_HAVE_OUTPUT)
|
||||
outport->node->sched_state = STATE_OUT;
|
||||
else if (res == SPA_RESULT_NEED_INPUT)
|
||||
outport->node->sched_state = STATE_IN;
|
||||
else if (res < 0)
|
||||
pinos_log_warn ("node %p: got process output %d", this, res);
|
||||
}
|
||||
if ((res = spa_node_process_output (outport->node->node)) < 0)
|
||||
pinos_log_warn ("node %p: got process output %d", outport->node, res);
|
||||
}
|
||||
}
|
||||
if (processed) {
|
||||
if ((res = spa_node_process_input (this->node)) < 0)
|
||||
pinos_log_warn ("node %p: got process input %d", this, res);
|
||||
if (pi->buffer_id != SPA_ID_INVALID) {
|
||||
pinos_log_trace ("node %p: process input", this);
|
||||
res = spa_node_process_input (this->node);
|
||||
|
||||
if (res == SPA_RESULT_HAVE_OUTPUT)
|
||||
this->sched_state = STATE_OUT;
|
||||
else if (res == SPA_RESULT_NEED_INPUT)
|
||||
this->sched_state = STATE_IN;
|
||||
else if (res < 0)
|
||||
pinos_log_warn ("node %p: got process input %d", this, res);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (SPA_EVENT_TYPE (event) == this->core->type.event_node.HaveOutput) {
|
||||
SpaResult res;
|
||||
int i;
|
||||
bool processed = false;
|
||||
|
||||
for (i = 0; i < this->transport->area->n_outputs; i++) {
|
||||
PinosLink *link;
|
||||
|
|
@ -327,13 +366,36 @@ on_node_event (SpaNode *node, SpaEvent *event, void *user_data)
|
|||
if ((res = spa_node_process_input (inport->node->node)) < 0)
|
||||
pinos_log_warn ("node %p: got process input %d", inport->node, res);
|
||||
}
|
||||
processed = true;
|
||||
}
|
||||
if (processed) {
|
||||
if ((res = spa_node_process_output (this->node)) < 0)
|
||||
pinos_log_warn ("node %p: got process output %d", this, res);
|
||||
if ((res = spa_node_process_output (this->node)) < 0)
|
||||
pinos_log_warn ("node %p: got process output %d", this, res);
|
||||
|
||||
}
|
||||
#if 0
|
||||
else if (SPA_EVENT_TYPE (event) == this->core->type.event_node.ReuseBuffer) {
|
||||
SpaEventNodeReuseBuffer *rb = (SpaEventNodeReuseBuffer *) event;
|
||||
int i;
|
||||
|
||||
pinos_log_trace ("node %p: reuse buffer %u", this, rb->body.buffer_id.value);
|
||||
|
||||
for (i = 0; i < this->transport->area->n_inputs; i++) {
|
||||
PinosLink *link;
|
||||
PinosPort *inport, *outport;
|
||||
SpaPortIO *po;
|
||||
|
||||
inport = this->input_port_map[i];
|
||||
spa_list_for_each (link, &inport->rt.links, rt.input_link) {
|
||||
if (link->rt.input == NULL || link->rt.output == NULL)
|
||||
continue;
|
||||
|
||||
outport = link->rt.output;
|
||||
po = &outport->node->transport->outputs[outport->port_id];
|
||||
|
||||
po->buffer_id = rb->body.buffer_id.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else if (SPA_EVENT_TYPE (event) == this->core->type.event_node.RequestClockUpdate) {
|
||||
send_clock_update (this);
|
||||
}
|
||||
|
|
@ -440,7 +502,7 @@ init_complete (PinosNode *this)
|
|||
{
|
||||
PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, this);
|
||||
|
||||
update_port_ids (this, false);
|
||||
update_port_ids (this);
|
||||
pinos_log_debug ("node %p: init completed", this);
|
||||
impl->async_init = false;
|
||||
|
||||
|
|
@ -466,6 +528,7 @@ pinos_node_set_data_loop (PinosNode *node,
|
|||
PinosNode *
|
||||
pinos_node_new (PinosCore *core,
|
||||
const char *name,
|
||||
bool async,
|
||||
SpaNode *node,
|
||||
SpaClock *clock,
|
||||
PinosProperties *properties)
|
||||
|
|
@ -525,15 +588,15 @@ pinos_node_new (PinosCore *core,
|
|||
this->node->info->items[i].value);
|
||||
}
|
||||
|
||||
if (this->node->state > SPA_NODE_STATE_INIT) {
|
||||
init_complete (this);
|
||||
} else {
|
||||
impl->async_init = true;
|
||||
impl->async_init = async;
|
||||
if (async) {
|
||||
pinos_work_queue_add (impl->work,
|
||||
this,
|
||||
SPA_RESULT_RETURN_ASYNC (0),
|
||||
(PinosWorkFunc) init_complete,
|
||||
NULL);
|
||||
} else {
|
||||
init_complete (this);
|
||||
}
|
||||
|
||||
return this;
|
||||
|
|
@ -668,21 +731,27 @@ PinosPort *
|
|||
pinos_node_get_free_port (PinosNode *node,
|
||||
PinosDirection direction)
|
||||
{
|
||||
uint32_t n_ports, max_ports;
|
||||
uint32_t *n_ports, max_ports;
|
||||
SpaList *ports;
|
||||
PinosPort *port = NULL, *p;
|
||||
PinosPort *port = NULL, *p, **portmap;
|
||||
SpaPortIO *io;
|
||||
int i;
|
||||
|
||||
if (direction == PINOS_DIRECTION_INPUT) {
|
||||
max_ports = node->transport->area->max_inputs;
|
||||
n_ports = node->transport->area->n_inputs;
|
||||
n_ports = &node->transport->area->n_inputs;
|
||||
ports = &node->input_ports;
|
||||
portmap = node->input_port_map;
|
||||
io = node->transport->inputs;
|
||||
} else {
|
||||
max_ports = node->transport->area->max_outputs;
|
||||
n_ports = node->transport->area->n_outputs;
|
||||
n_ports = &node->transport->area->n_outputs;
|
||||
ports = &node->output_ports;
|
||||
portmap = node->output_port_map;
|
||||
io = node->transport->outputs;
|
||||
}
|
||||
|
||||
pinos_log_debug ("node %p: direction %d max %u, n %u", node, direction, max_ports, n_ports);
|
||||
pinos_log_debug ("node %p: direction %d max %u, n %u", node, direction, max_ports, *n_ports);
|
||||
|
||||
spa_list_for_each (p, ports, link) {
|
||||
if (spa_list_is_empty (&p->links)) {
|
||||
|
|
@ -691,9 +760,26 @@ pinos_node_get_free_port (PinosNode *node,
|
|||
}
|
||||
}
|
||||
|
||||
if (port == NULL && !spa_list_is_empty (ports))
|
||||
port = spa_list_first (ports, PinosPort, link);
|
||||
|
||||
if (port == NULL) {
|
||||
/* no port, can we create one ? */
|
||||
if (*n_ports < max_ports) {
|
||||
for (i = 0; i < max_ports && port == NULL; i++) {
|
||||
if (portmap[i] == NULL) {
|
||||
pinos_log_debug ("node %p: creating port direction %d %u", node, direction, i);
|
||||
port = portmap[i] = pinos_port_new (node, direction, i);
|
||||
port->io = &io[i];
|
||||
(*n_ports)++;
|
||||
spa_node_add_port (node->node, direction, i);
|
||||
spa_node_port_set_io (node->node, direction, i, port->io);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* for output we can reuse an existing port */
|
||||
if (direction == PINOS_DIRECTION_OUTPUT && !spa_list_is_empty (ports)) {
|
||||
port = spa_list_first (ports, PinosPort, link);
|
||||
}
|
||||
}
|
||||
}
|
||||
return port;
|
||||
|
||||
}
|
||||
|
|
@ -714,6 +800,22 @@ on_state_complete (PinosNode *node,
|
|||
pinos_node_update_state (node, state, error);
|
||||
}
|
||||
|
||||
static void
|
||||
node_activate (PinosNode *this)
|
||||
{
|
||||
PinosPort *port;
|
||||
|
||||
spa_list_for_each (port, &this->input_ports, link) {
|
||||
PinosLink *link;
|
||||
spa_list_for_each (link, &port->links, input_link)
|
||||
pinos_link_activate (link);
|
||||
}
|
||||
spa_list_for_each (port, &this->output_ports, link) {
|
||||
PinosLink *link;
|
||||
spa_list_for_each (link, &port->links, output_link)
|
||||
pinos_link_activate (link);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* pinos_node_set_state:
|
||||
* @node: a #PinosNode
|
||||
|
|
@ -747,6 +849,7 @@ pinos_node_set_state (PinosNode *node,
|
|||
break;
|
||||
|
||||
case PINOS_NODE_STATE_RUNNING:
|
||||
node_activate (node);
|
||||
send_clock_update (node);
|
||||
res = start_node (node);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ struct _PinosNode {
|
|||
SpaNode *node;
|
||||
bool live;
|
||||
SpaClock *clock;
|
||||
int sched_state;
|
||||
|
||||
SpaList resource_list;
|
||||
|
||||
|
|
@ -107,6 +108,7 @@ struct _PinosNode {
|
|||
|
||||
PinosNode * pinos_node_new (PinosCore *core,
|
||||
const char *name,
|
||||
bool async,
|
||||
SpaNode *node,
|
||||
SpaClock *clock,
|
||||
PinosProperties *properties);
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ pinos_port_new (PinosNode *node,
|
|||
this->node = node;
|
||||
this->direction = direction;
|
||||
this->port_id = port_id;
|
||||
this->state = SPA_PORT_STATE_CONFIGURE;
|
||||
|
||||
spa_list_init (&this->links);
|
||||
spa_list_init (&this->rt.links);
|
||||
|
|
@ -200,6 +201,7 @@ static SpaResult
|
|||
pinos_port_pause (PinosPort *port)
|
||||
{
|
||||
SpaCommand cmd = SPA_COMMAND_INIT (port->node->core->type.command_node.Pause);
|
||||
port->state = SPA_PORT_STATE_PAUSED;
|
||||
return spa_node_port_send_command (port->node->node,
|
||||
port->direction,
|
||||
port->port_id,
|
||||
|
|
@ -239,6 +241,7 @@ do_remove_link_done (SpaLoop *loop,
|
|||
port->direction,
|
||||
port->port_id,
|
||||
NULL, 0);
|
||||
port->state = SPA_PORT_STATE_READY;
|
||||
port->buffers = NULL;
|
||||
port->n_buffers = 0;
|
||||
}
|
||||
|
|
@ -315,6 +318,7 @@ do_clear_buffers_done (SpaLoop *loop,
|
|||
port->direction,
|
||||
port->port_id,
|
||||
NULL, 0);
|
||||
port->state = SPA_PORT_STATE_READY;
|
||||
port->buffers = NULL;
|
||||
port->n_buffers = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -45,6 +45,8 @@ struct _PinosPort {
|
|||
PinosNode *node;
|
||||
PinosDirection direction;
|
||||
uint32_t port_id;
|
||||
uint32_t state;
|
||||
SpaPortIO *io;
|
||||
|
||||
bool allocated;
|
||||
PinosMemblock buffer_mem;
|
||||
|
|
|
|||
|
|
@ -898,23 +898,6 @@ client_node_demarshal_port_update (void *object,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
client_node_demarshal_state_change (void *object,
|
||||
void *data,
|
||||
size_t size)
|
||||
{
|
||||
PinosResource *resource = object;
|
||||
SpaPODIter it;
|
||||
uint32_t state;
|
||||
|
||||
if (!spa_pod_iter_struct (&it, data, size) ||
|
||||
!spa_pod_iter_get (&it, SPA_POD_TYPE_INT, &state, 0))
|
||||
return false;
|
||||
|
||||
((PinosClientNodeMethods*)resource->implementation)->state_change (resource, state);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
client_node_demarshal_event (void *object,
|
||||
void *data,
|
||||
|
|
@ -1035,7 +1018,6 @@ const PinosInterface pinos_protocol_native_server_client_interface = {
|
|||
static const PinosDemarshalFunc pinos_protocol_native_server_client_node_demarshal[] = {
|
||||
&client_node_demarshal_update,
|
||||
&client_node_demarshal_port_update,
|
||||
&client_node_demarshal_state_change,
|
||||
&client_node_demarshal_event,
|
||||
&client_node_demarshal_destroy,
|
||||
};
|
||||
|
|
@ -1055,7 +1037,7 @@ static const PinosClientNodeEvents pinos_protocol_native_server_client_node_even
|
|||
};
|
||||
|
||||
const PinosInterface pinos_protocol_native_server_client_node_interface = {
|
||||
5, &pinos_protocol_native_server_client_node_demarshal,
|
||||
4, &pinos_protocol_native_server_client_node_demarshal,
|
||||
11, &pinos_protocol_native_server_client_node_events,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -29,25 +29,6 @@ typedef struct _SpaNode SpaNode;
|
|||
#define SPA_TYPE__Node SPA_TYPE_INTERFACE_BASE "Node"
|
||||
#define SPA_TYPE_NODE_BASE SPA_TYPE__Node ":"
|
||||
|
||||
/**
|
||||
* SpaNodeState:
|
||||
* @SPA_NODE_STATE_INIT: the node is initializing
|
||||
* @SPA_NODE_STATE_CONFIGURE: the node needs at least one port format
|
||||
* @SPA_NODE_STATE_READY: the node is ready for memory allocation
|
||||
* @SPA_NODE_STATE_PAUSED: the node is paused
|
||||
* @SPA_NODE_STATE_STREAMING: the node is streaming
|
||||
* @SPA_NODE_STATE_ERROR: the node is in error
|
||||
*/
|
||||
typedef enum {
|
||||
SPA_NODE_STATE_ERROR = -1,
|
||||
SPA_NODE_STATE_INIT = 0,
|
||||
SPA_NODE_STATE_CONFIGURE,
|
||||
SPA_NODE_STATE_READY,
|
||||
SPA_NODE_STATE_PAUSED,
|
||||
SPA_NODE_STATE_STREAMING,
|
||||
} SpaNodeState;
|
||||
|
||||
|
||||
#include <spa/defs.h>
|
||||
#include <spa/plugin.h>
|
||||
#include <spa/props.h>
|
||||
|
|
@ -72,10 +53,6 @@ typedef enum {
|
|||
SPA_PORT_FORMAT_FLAG_NEAREST = (1 << 2),
|
||||
} SpaPortFormatFlags;
|
||||
|
||||
#define SPA_PORT_STATE_FLAG_NONE 0
|
||||
#define SPA_PORT_STATE_FLAG_HAVE_FORMAT (1 << 0)
|
||||
#define SPA_PORT_STATE_FLAG_HAVE_BUFFERS (1 << 1)
|
||||
|
||||
typedef struct {
|
||||
uint64_t offset;
|
||||
uint32_t min_size;
|
||||
|
|
@ -86,24 +63,20 @@ typedef struct {
|
|||
* SpaPortIO:
|
||||
* @state: the port state
|
||||
* @flags: extra flags
|
||||
* @buffer_id: a buffer id will be set
|
||||
* @buffer_id: a buffer id
|
||||
* @status: the status
|
||||
* @range: requested output range
|
||||
* @event: output event
|
||||
* @range: requested range
|
||||
* @event: event
|
||||
*
|
||||
* Output information for a port on a node. This is allocated
|
||||
* by the host and configured on all output ports for which output is
|
||||
* requested.
|
||||
* IO information for a port on a node. This is allocated
|
||||
* by the host and configured on all ports for which IO is requested.
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t state;
|
||||
#define SPA_PORT_IO_FLAG_NONE 0
|
||||
#define SPA_PORT_IO_FLAG_RANGE (1 << 0)
|
||||
#define SPA_PORT_IO_FLAG_RANGE (1 << 0) /* a range is present */
|
||||
uint32_t flags;
|
||||
uint32_t buffer_id;
|
||||
uint32_t status;
|
||||
SpaRange range;
|
||||
SpaEvent *event;
|
||||
} SpaPortIO;
|
||||
|
||||
/**
|
||||
|
|
@ -142,6 +115,13 @@ typedef enum {
|
|||
*
|
||||
*/
|
||||
typedef struct {
|
||||
#define SPA_PORT_STATE_ERROR -1
|
||||
#define SPA_PORT_STATE_INIT 0
|
||||
#define SPA_PORT_STATE_CONFIGURE 1
|
||||
#define SPA_PORT_STATE_READY 2
|
||||
#define SPA_PORT_STATE_PAUSED 3
|
||||
#define SPA_PORT_STATE_STREAMING 4
|
||||
uint32_t state;
|
||||
SpaPortInfoFlags flags;
|
||||
uint32_t n_params;
|
||||
SpaAllocParam **params;
|
||||
|
|
@ -181,12 +161,6 @@ struct _SpaNode {
|
|||
* Extra information about the node
|
||||
*/
|
||||
const SpaDict * info;
|
||||
/**
|
||||
* SpaNode::state:
|
||||
*
|
||||
* The current state of the node
|
||||
*/
|
||||
SpaNodeState state;
|
||||
/**
|
||||
* SpaNode::get_props:
|
||||
* @node: a #SpaNode
|
||||
|
|
|
|||
|
|
@ -41,13 +41,6 @@ reset_alsa_sink_props (SpaALSAProps *props)
|
|||
props->min_latency = default_min_latency;
|
||||
}
|
||||
|
||||
static void
|
||||
update_state (SpaALSASink *this, SpaNodeState state)
|
||||
{
|
||||
spa_log_info (this->log, "update state %d", state);
|
||||
this->node.state = state;
|
||||
}
|
||||
|
||||
static SpaResult
|
||||
spa_alsa_sink_node_get_props (SpaNode *node,
|
||||
SpaProps **props)
|
||||
|
|
@ -348,11 +341,7 @@ spa_alsa_sink_node_port_set_format (SpaNode *node,
|
|||
PROP (&f[1], this->type.alloc_param_meta_enable.ringbufferAlign, SPA_POD_TYPE_INT, 16));
|
||||
this->params[2] = SPA_POD_BUILDER_DEREF (&b, f[0].ref, SpaAllocParam);
|
||||
this->info.extra = NULL;
|
||||
|
||||
update_state (this, SPA_NODE_STATE_READY);
|
||||
}
|
||||
else
|
||||
update_state (this, SPA_NODE_STATE_CONFIGURE);
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
|
@ -451,7 +440,6 @@ spa_alsa_sink_node_port_use_buffers (SpaNode *node,
|
|||
if (n_buffers == 0) {
|
||||
spa_alsa_pause (this, false);
|
||||
spa_alsa_clear_buffers (this);
|
||||
update_state (this, SPA_NODE_STATE_READY);
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
|
|
@ -480,8 +468,6 @@ spa_alsa_sink_node_port_use_buffers (SpaNode *node,
|
|||
}
|
||||
this->n_buffers = n_buffers;
|
||||
|
||||
update_state (this, SPA_NODE_STATE_PAUSED);
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
|
|
@ -552,14 +538,10 @@ spa_alsa_sink_node_port_send_command (SpaNode *node,
|
|||
spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT);
|
||||
|
||||
if (SPA_COMMAND_TYPE (command) == this->type.command_node.Pause) {
|
||||
if (SPA_RESULT_IS_OK (res = spa_alsa_pause (this, false))) {
|
||||
update_state (this, SPA_NODE_STATE_PAUSED);
|
||||
}
|
||||
res = spa_alsa_pause (this, false);
|
||||
}
|
||||
else if (SPA_COMMAND_TYPE (command) == this->type.command_node.Start) {
|
||||
if (SPA_RESULT_IS_OK (res = spa_alsa_start (this, false))) {
|
||||
update_state (this, SPA_NODE_STATE_STREAMING);
|
||||
}
|
||||
res = spa_alsa_start (this, false);
|
||||
}
|
||||
else
|
||||
res = SPA_RESULT_NOT_IMPLEMENTED;
|
||||
|
|
@ -578,21 +560,25 @@ spa_alsa_sink_node_process_input (SpaNode *node)
|
|||
|
||||
this = SPA_CONTAINER_OF (node, SpaALSASink, node);
|
||||
|
||||
if ((input = this->io) == NULL)
|
||||
if ((input = this->io) == NULL) {
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
if (!this->have_format) {
|
||||
spa_log_error (this->log, "alsa-sink %p: no format", this);
|
||||
input->status = SPA_RESULT_NO_FORMAT;
|
||||
return SPA_RESULT_ERROR;
|
||||
}
|
||||
|
||||
if (input->buffer_id >= this->n_buffers) {
|
||||
spa_log_error (this->log, "alsa-sink %p: invalid buffer %u", this, input->buffer_id);
|
||||
input->status = SPA_RESULT_INVALID_BUFFER_ID;
|
||||
return SPA_RESULT_ERROR;
|
||||
}
|
||||
|
||||
b = &this->buffers[input->buffer_id];
|
||||
if (!b->outstanding) {
|
||||
spa_log_error (this->log, "alsa-sink %p: buffer %u in use", this, input->buffer_id);
|
||||
input->buffer_id = SPA_ID_INVALID;
|
||||
input->status = SPA_RESULT_INVALID_BUFFER_ID;
|
||||
return SPA_RESULT_ERROR;
|
||||
|
|
@ -621,7 +607,6 @@ spa_alsa_sink_node_process_output (SpaNode *node)
|
|||
static const SpaNode alsasink_node = {
|
||||
sizeof (SpaNode),
|
||||
NULL,
|
||||
SPA_NODE_STATE_INIT,
|
||||
spa_alsa_sink_node_get_props,
|
||||
spa_alsa_sink_node_set_props,
|
||||
spa_alsa_sink_node_send_command,
|
||||
|
|
@ -725,8 +710,6 @@ alsa_sink_init (const SpaHandleFactory *factory,
|
|||
}
|
||||
}
|
||||
|
||||
update_state (this, SPA_NODE_STATE_CONFIGURE);
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,12 +32,6 @@
|
|||
|
||||
typedef struct _SpaALSAState SpaALSASource;
|
||||
|
||||
static void
|
||||
update_state (SpaALSASource *this, SpaNodeState state)
|
||||
{
|
||||
this->node.state = state;
|
||||
}
|
||||
|
||||
static const char default_device[] = "hw:0";
|
||||
static const uint32_t default_min_latency = 1024;
|
||||
|
||||
|
|
@ -123,9 +117,7 @@ do_start (SpaLoop *loop,
|
|||
SpaALSASource *this = user_data;
|
||||
SpaResult res;
|
||||
|
||||
if (SPA_RESULT_IS_OK (res = spa_alsa_start (this, false))) {
|
||||
update_state (this, SPA_NODE_STATE_STREAMING);
|
||||
}
|
||||
res = spa_alsa_start (this, false);
|
||||
|
||||
if (async) {
|
||||
SpaEventNodeAsyncComplete ac = SPA_EVENT_NODE_ASYNC_COMPLETE_INIT (this->type.event_node.AsyncComplete,
|
||||
|
|
@ -151,9 +143,7 @@ do_pause (SpaLoop *loop,
|
|||
SpaALSASource *this = user_data;
|
||||
SpaResult res;
|
||||
|
||||
if (SPA_RESULT_IS_OK (res = spa_alsa_pause (this, false))) {
|
||||
update_state (this, SPA_NODE_STATE_PAUSED);
|
||||
}
|
||||
res = spa_alsa_pause (this, false);
|
||||
|
||||
if (async) {
|
||||
SpaEventNodeAsyncComplete ac = SPA_EVENT_NODE_ASYNC_COMPLETE_INIT (this->type.event_node.AsyncComplete,
|
||||
|
|
@ -390,10 +380,6 @@ spa_alsa_source_node_port_set_format (SpaNode *node,
|
|||
this->params[1] = SPA_POD_BUILDER_DEREF (&b, f[0].ref, SpaAllocParam);
|
||||
|
||||
this->info.extra = NULL;
|
||||
|
||||
update_state (this, SPA_NODE_STATE_READY);
|
||||
} else {
|
||||
update_state (this, SPA_NODE_STATE_CONFIGURE);
|
||||
}
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
|
|
@ -517,11 +503,6 @@ spa_alsa_source_node_port_use_buffers (SpaNode *node,
|
|||
}
|
||||
this->n_buffers = n_buffers;
|
||||
|
||||
if (this->n_buffers > 0)
|
||||
update_state (this, SPA_NODE_STATE_PAUSED);
|
||||
else
|
||||
update_state (this, SPA_NODE_STATE_READY);
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
|
|
@ -609,13 +590,9 @@ spa_alsa_source_node_port_send_command (SpaNode *node,
|
|||
spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT);
|
||||
|
||||
if (SPA_COMMAND_TYPE (command) == this->type.command_node.Pause) {
|
||||
if (SPA_RESULT_IS_OK (res = spa_alsa_pause (this, false))) {
|
||||
update_state (this, SPA_NODE_STATE_PAUSED);
|
||||
}
|
||||
res = spa_alsa_pause (this, false);
|
||||
} else if (SPA_COMMAND_TYPE (command) == this->type.command_node.Start) {
|
||||
if (SPA_RESULT_IS_OK (res = spa_alsa_start (this, false))) {
|
||||
update_state (this, SPA_NODE_STATE_STREAMING);
|
||||
}
|
||||
res = spa_alsa_start (this, false);
|
||||
} else
|
||||
res = SPA_RESULT_NOT_IMPLEMENTED;
|
||||
|
||||
|
|
@ -648,7 +625,6 @@ spa_alsa_source_node_process_output (SpaNode *node)
|
|||
static const SpaNode alsasource_node = {
|
||||
sizeof (SpaNode),
|
||||
NULL,
|
||||
SPA_NODE_STATE_INIT,
|
||||
spa_alsa_source_node_get_props,
|
||||
spa_alsa_source_node_set_props,
|
||||
spa_alsa_source_node_send_command,
|
||||
|
|
@ -800,9 +776,6 @@ alsa_source_init (const SpaHandleFactory *factory,
|
|||
snprintf (this->props.device, 63, "%s", info->items[i].value);
|
||||
}
|
||||
}
|
||||
|
||||
update_state (this, SPA_NODE_STATE_CONFIGURE);
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -332,18 +332,16 @@ pull_frames_queue (SpaALSAState *state,
|
|||
snd_pcm_uframes_t frames)
|
||||
{
|
||||
snd_pcm_uframes_t total_frames = 0, to_write = frames;
|
||||
SpaPortIO *io = state->io;
|
||||
|
||||
if (spa_list_is_empty (&state->ready)) {
|
||||
SpaEvent event = SPA_EVENT_INIT (state->type.event_node.NeedInput);
|
||||
SpaPortIO *io;
|
||||
|
||||
if ((io = state->io)) {
|
||||
io->flags = SPA_PORT_IO_FLAG_RANGE;
|
||||
io->status = SPA_RESULT_OK;
|
||||
io->range.offset = state->sample_count * state->frame_size;
|
||||
io->range.min_size = state->threshold * state->frame_size;
|
||||
io->range.max_size = frames * state->frame_size;
|
||||
}
|
||||
io->flags = SPA_PORT_IO_FLAG_RANGE;
|
||||
io->status = SPA_RESULT_OK;
|
||||
io->range.offset = state->sample_count * state->frame_size;
|
||||
io->range.min_size = state->threshold * state->frame_size;
|
||||
io->range.max_size = frames * state->frame_size;
|
||||
state->event_cb (&state->node, &event, state->user_data);
|
||||
}
|
||||
while (!spa_list_is_empty (&state->ready) && to_write > 0) {
|
||||
|
|
@ -375,7 +373,6 @@ pull_frames_queue (SpaALSAState *state,
|
|||
|
||||
spa_log_trace (state->log, "alsa-util %p: reuse buffer %u", state, b->outbuf->id);
|
||||
state->event_cb (&state->node, (SpaEvent *)&rb, state->user_data);
|
||||
|
||||
state->ready_offset = 0;
|
||||
}
|
||||
total_frames += n_frames;
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include <spa/type-map.h>
|
||||
#include <spa/node.h>
|
||||
#include <spa/audio/format-utils.h>
|
||||
#include <spa/format-builder.h>
|
||||
#include <lib/props.h>
|
||||
|
||||
#define MAX_BUFFERS 64
|
||||
|
|
@ -40,14 +41,14 @@ typedef struct {
|
|||
} MixerBuffer;
|
||||
|
||||
typedef struct {
|
||||
bool valid;
|
||||
SpaPortIO *io;
|
||||
|
||||
bool have_format;
|
||||
SpaAudioInfo format;
|
||||
SpaPortInfo info;
|
||||
|
||||
SpaPortIO *io;
|
||||
MixerBuffer buffers[MAX_BUFFERS];
|
||||
uint32_t n_buffers;
|
||||
|
||||
SpaList queue;
|
||||
size_t queued_offset;
|
||||
size_t queued_bytes;
|
||||
|
|
@ -55,9 +56,11 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
uint32_t node;
|
||||
uint32_t format;
|
||||
SpaTypeMediaType media_type;
|
||||
SpaTypeMediaSubtype media_subtype;
|
||||
SpaTypeFormatAudio format_audio;
|
||||
SpaTypeAudioFormat audio_format;
|
||||
SpaTypeCommandNode command_node;
|
||||
} Type;
|
||||
|
||||
|
|
@ -65,9 +68,11 @@ static inline void
|
|||
init_type (Type *type, SpaTypeMap *map)
|
||||
{
|
||||
type->node = spa_type_map_get_id (map, SPA_TYPE__Node);
|
||||
type->format = spa_type_map_get_id (map, SPA_TYPE__Format);
|
||||
spa_type_media_type_map (map, &type->media_type);
|
||||
spa_type_media_subtype_map (map, &type->media_subtype);
|
||||
spa_type_format_audio_map (map, &type->format_audio);
|
||||
spa_type_audio_format_map (map, &type->audio_format);
|
||||
spa_type_command_node_map (map, &type->command_node);
|
||||
}
|
||||
|
||||
|
|
@ -87,20 +92,36 @@ struct _SpaAudioMixer {
|
|||
SpaAudioMixerPort in_ports[MAX_PORTS];
|
||||
SpaAudioMixerPort out_ports[1];
|
||||
|
||||
bool have_format;
|
||||
SpaAudioInfo format;
|
||||
uint8_t format_buffer[4096];
|
||||
|
||||
bool started;
|
||||
#define STATE_ERROR 0
|
||||
#define STATE_IN 1
|
||||
#define STATE_OUT 2
|
||||
int state;
|
||||
};
|
||||
|
||||
#define CHECK_FREE_IN_PORT(this,d,p) ((d) == SPA_DIRECTION_INPUT && (p) < MAX_PORTS && !this->in_ports[(p)].valid)
|
||||
#define CHECK_IN_PORT(this,d,p) ((d) == SPA_DIRECTION_INPUT && (p) < MAX_PORTS && this->in_ports[(p)].valid)
|
||||
#define CHECK_PORT_NUM(this,d,p) (((d) == SPA_DIRECTION_INPUT && (p) < MAX_PORTS) || \
|
||||
((d) == SPA_DIRECTION_OUTPUT && (p) == 0))
|
||||
#define CHECK_FREE_IN_PORT(this,d,p) ((d) == SPA_DIRECTION_INPUT && (p) < MAX_PORTS && !this->in_ports[(p)].io)
|
||||
#define CHECK_IN_PORT(this,d,p) ((d) == SPA_DIRECTION_INPUT && (p) < MAX_PORTS && this->in_ports[(p)].io)
|
||||
#define CHECK_OUT_PORT(this,d,p) ((d) == SPA_DIRECTION_OUTPUT && (p) == 0)
|
||||
#define CHECK_PORT(this,d,p) (CHECK_OUT_PORT(this,d,p) || CHECK_IN_PORT (this,d,p))
|
||||
|
||||
enum {
|
||||
PROP_ID_LAST,
|
||||
};
|
||||
#define PROP(f,key,type,...) \
|
||||
SPA_POD_PROP (f,key,0,type,1,__VA_ARGS__)
|
||||
#define PROP_MM(f,key,type,...) \
|
||||
SPA_POD_PROP (f,key,SPA_POD_PROP_RANGE_MIN_MAX,type,3,__VA_ARGS__)
|
||||
#define PROP_U_MM(f,key,type,...) \
|
||||
SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \
|
||||
SPA_POD_PROP_RANGE_MIN_MAX,type,3,__VA_ARGS__)
|
||||
#define PROP_EN(f,key,type,n,...) \
|
||||
SPA_POD_PROP (f,key,SPA_POD_PROP_RANGE_ENUM,type,n,__VA_ARGS__)
|
||||
#define PROP_U_EN(f,key,type,n,...) \
|
||||
SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \
|
||||
SPA_POD_PROP_RANGE_ENUM,type,n,__VA_ARGS__)
|
||||
|
||||
static SpaResult
|
||||
spa_audiomixer_node_get_props (SpaNode *node,
|
||||
|
|
@ -116,12 +137,6 @@ spa_audiomixer_node_set_props (SpaNode *node,
|
|||
return SPA_RESULT_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
static void
|
||||
update_state (SpaAudioMixer *this, SpaNodeState state)
|
||||
{
|
||||
this->node.state = state;
|
||||
}
|
||||
|
||||
static SpaResult
|
||||
spa_audiomixer_node_send_command (SpaNode *node,
|
||||
SpaCommand *command)
|
||||
|
|
@ -134,10 +149,10 @@ spa_audiomixer_node_send_command (SpaNode *node,
|
|||
this = SPA_CONTAINER_OF (node, SpaAudioMixer, node);
|
||||
|
||||
if (SPA_COMMAND_TYPE (command) == this->type.command_node.Start) {
|
||||
update_state (this, SPA_NODE_STATE_STREAMING);
|
||||
this->started = true;
|
||||
}
|
||||
else if (SPA_COMMAND_TYPE (command) == this->type.command_node.Pause) {
|
||||
update_state (this, SPA_NODE_STATE_PAUSED);
|
||||
this->started = false;
|
||||
}
|
||||
else
|
||||
return SPA_RESULT_NOT_IMPLEMENTED;
|
||||
|
|
@ -199,7 +214,7 @@ spa_audiomixer_node_get_port_ids (SpaNode *node,
|
|||
|
||||
if (input_ids) {
|
||||
for (i = 0, idx = 0; i < MAX_PORTS && idx < n_input_ports; i++) {
|
||||
if (this->in_ports[i].valid)
|
||||
if (this->in_ports[i].io)
|
||||
input_ids[idx++] = i;
|
||||
}
|
||||
}
|
||||
|
|
@ -222,7 +237,6 @@ spa_audiomixer_node_add_port (SpaNode *node,
|
|||
|
||||
spa_return_val_if_fail (CHECK_FREE_IN_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT);
|
||||
|
||||
this->in_ports[port_id].valid = true;
|
||||
this->port_count++;
|
||||
spa_list_init (&this->in_ports[port_id].queue);
|
||||
|
||||
|
|
@ -247,13 +261,12 @@ spa_audiomixer_node_remove_port (SpaNode *node,
|
|||
|
||||
spa_return_val_if_fail (CHECK_IN_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT);
|
||||
|
||||
this->in_ports[port_id].valid = false;
|
||||
this->port_count--;
|
||||
|
||||
io = this->in_ports[port_id].io;
|
||||
if (io && io->buffer_id) {
|
||||
if (io && io->buffer_id)
|
||||
this->port_queued--;
|
||||
}
|
||||
|
||||
this->in_ports[port_id].io = NULL;
|
||||
this->port_count--;
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
|
@ -268,6 +281,12 @@ spa_audiomixer_node_port_enum_formats (SpaNode *node,
|
|||
uint32_t index)
|
||||
{
|
||||
SpaAudioMixer *this;
|
||||
SpaResult res;
|
||||
SpaFormat *fmt;
|
||||
uint8_t buffer[256];
|
||||
SpaPODBuilder b = { NULL, };
|
||||
SpaPODFrame f[2];
|
||||
uint32_t count, match;
|
||||
|
||||
spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
|
||||
spa_return_val_if_fail (format != NULL, SPA_RESULT_INVALID_ARGUMENTS);
|
||||
|
|
@ -276,13 +295,30 @@ spa_audiomixer_node_port_enum_formats (SpaNode *node,
|
|||
|
||||
spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT);
|
||||
|
||||
switch (index) {
|
||||
count = match = filter ? 0 : index;
|
||||
|
||||
next:
|
||||
spa_pod_builder_init (&b, buffer, sizeof (buffer));
|
||||
|
||||
switch (count++) {
|
||||
case 0:
|
||||
spa_pod_builder_format (&b, &f[0], this->type.format,
|
||||
this->type.media_type.audio, this->type.media_subtype.raw,
|
||||
PROP (&f[1], this->type.format_audio.format, SPA_POD_TYPE_ID, this->type.audio_format.S16),
|
||||
PROP_U_MM (&f[1], this->type.format_audio.rate, SPA_POD_TYPE_INT, 44100, 1, INT32_MAX),
|
||||
PROP_U_MM (&f[1], this->type.format_audio.channels, SPA_POD_TYPE_INT, 2, 1, INT32_MAX));
|
||||
break;
|
||||
default:
|
||||
return SPA_RESULT_ENUM_END;
|
||||
}
|
||||
*format = NULL;
|
||||
fmt = SPA_POD_BUILDER_DEREF (&b, f[0].ref, SpaFormat);
|
||||
|
||||
spa_pod_builder_init (&b, this->format_buffer, sizeof (this->format_buffer));
|
||||
|
||||
if ((res = spa_format_filter (fmt, filter, &b)) != SPA_RESULT_OK || match++ != index)
|
||||
goto next;
|
||||
|
||||
*format = SPA_POD_BUILDER_DEREF (&b, 0, SpaFormat);
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
|
@ -330,16 +366,10 @@ spa_audiomixer_node_port_set_format (SpaNode *node,
|
|||
if (!spa_format_audio_raw_parse (format, &info.info.raw, &this->type.format_audio))
|
||||
return SPA_RESULT_INVALID_MEDIA_TYPE;
|
||||
|
||||
port->format = info;
|
||||
this->format = info;
|
||||
port->have_format = true;
|
||||
}
|
||||
|
||||
if (port->have_format) {
|
||||
update_state (this, SPA_NODE_STATE_READY);
|
||||
}
|
||||
else
|
||||
update_state (this, SPA_NODE_STATE_CONFIGURE);
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
|
|
@ -351,6 +381,8 @@ spa_audiomixer_node_port_get_format (SpaNode *node,
|
|||
{
|
||||
SpaAudioMixer *this;
|
||||
SpaAudioMixerPort *port;
|
||||
SpaPODBuilder b = { NULL, };
|
||||
SpaPODFrame f[2];
|
||||
|
||||
spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
|
||||
spa_return_val_if_fail (format != NULL, SPA_RESULT_INVALID_ARGUMENTS);
|
||||
|
|
@ -364,7 +396,13 @@ spa_audiomixer_node_port_get_format (SpaNode *node,
|
|||
if (!port->have_format)
|
||||
return SPA_RESULT_NO_FORMAT;
|
||||
|
||||
*format = NULL;
|
||||
spa_pod_builder_init (&b, this->format_buffer, sizeof (this->format_buffer));
|
||||
spa_pod_builder_format (&b, &f[0], this->type.format,
|
||||
this->type.media_type.audio, this->type.media_subtype.raw,
|
||||
PROP (&f[1], this->type.format_audio.format, SPA_POD_TYPE_ID, this->format.info.raw.format),
|
||||
PROP (&f[1], this->type.format_audio.rate, SPA_POD_TYPE_INT, this->format.info.raw.rate),
|
||||
PROP (&f[1], this->type.format_audio.channels, SPA_POD_TYPE_INT, this->format.info.raw.channels));
|
||||
*format = SPA_POD_BUILDER_DEREF (&b, f[0].ref, SpaFormat);
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
|
@ -453,15 +491,11 @@ spa_audiomixer_node_port_use_buffers (SpaNode *node,
|
|||
default:
|
||||
break;
|
||||
}
|
||||
spa_list_insert (port->queue.prev, &b->link);
|
||||
if (!b->outstanding)
|
||||
spa_list_insert (port->queue.prev, &b->link);
|
||||
}
|
||||
port->n_buffers = n_buffers;
|
||||
|
||||
if (port->n_buffers > 0) {
|
||||
update_state (this, SPA_NODE_STATE_PAUSED);
|
||||
} else {
|
||||
update_state (this, SPA_NODE_STATE_READY);
|
||||
}
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
|
|
@ -490,7 +524,7 @@ spa_audiomixer_node_port_set_io (SpaNode *node,
|
|||
|
||||
this = SPA_CONTAINER_OF (node, SpaAudioMixer, node);
|
||||
|
||||
spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT);
|
||||
spa_return_val_if_fail (CHECK_PORT_NUM (this, direction, port_id), SPA_RESULT_INVALID_PORT);
|
||||
|
||||
port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id];
|
||||
port->io = io;
|
||||
|
|
@ -504,11 +538,15 @@ recycle_buffer (SpaAudioMixer *this, uint32_t id)
|
|||
SpaAudioMixerPort *port = &this->out_ports[0];
|
||||
|
||||
MixerBuffer *b = &port->buffers[id];
|
||||
if (b->outstanding) {
|
||||
spa_list_insert (port->queue.prev, &b->link);
|
||||
b->outstanding = false;
|
||||
spa_log_trace (this->log, "audiomixer %p: recycle buffer %d", this, id);
|
||||
|
||||
if (!b->outstanding) {
|
||||
spa_log_warn (this->log, "audiomixer %p: buffer %d not outstanding", this, id);
|
||||
return;
|
||||
}
|
||||
|
||||
spa_list_insert (port->queue.prev, &b->link);
|
||||
b->outstanding = false;
|
||||
spa_log_trace (this->log, "audiomixer %p: recycle buffer %d", this, id);
|
||||
}
|
||||
|
||||
static SpaResult
|
||||
|
|
@ -542,7 +580,7 @@ static void
|
|||
add_port_data (SpaAudioMixer *this, MixerBuffer *out, SpaAudioMixerPort *port, int layer)
|
||||
{
|
||||
int i;
|
||||
uint16_t *op, *ip;
|
||||
int16_t *op, *ip;
|
||||
size_t os, is, chunk;
|
||||
MixerBuffer *b = spa_list_first (&port->queue, MixerBuffer, link);
|
||||
|
||||
|
|
@ -559,7 +597,7 @@ add_port_data (SpaAudioMixer *this, MixerBuffer *out, SpaAudioMixerPort *port, i
|
|||
}
|
||||
else {
|
||||
for (i = 0; i < chunk / 2; i++)
|
||||
op[i] += ip[i];
|
||||
op[i] = SPA_CLAMP (op[i] + ip[i], INT16_MIN, INT16_MAX);
|
||||
}
|
||||
|
||||
port->queued_offset += chunk;
|
||||
|
|
@ -596,56 +634,66 @@ spa_audiomixer_node_process_input (SpaNode *node)
|
|||
SpaAudioMixerPort *port = &this->in_ports[i];
|
||||
SpaPortIO *input;
|
||||
|
||||
if (!port->valid || (input = port->io) == NULL)
|
||||
if ((input = port->io) == NULL)
|
||||
continue;
|
||||
|
||||
if (input->buffer_id != SPA_ID_INVALID) {
|
||||
MixerBuffer *b = &port->buffers[input->buffer_id];
|
||||
|
||||
if (!b->outstanding) {
|
||||
spa_log_warn (this->log, "audiomixer %p: buffer was not outstanding %d", this, input->buffer_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (spa_list_is_empty (&port->queue)) {
|
||||
port->queued_bytes = 0;
|
||||
port->queued_offset = 0;
|
||||
}
|
||||
spa_log_trace (this->log, "audiomixer %p: queue buffer %d on port %p", this, b->outbuf->id, port);
|
||||
spa_list_insert (port->queue.prev, &b->link);
|
||||
b->outstanding = false;
|
||||
port->queued_bytes += b->outbuf->datas[0].chunk->size;
|
||||
spa_log_trace (this->log, "audiomixer %p: queue buffer %d on port %p %zd %zd",
|
||||
this, b->outbuf->id, port, port->queued_bytes, min_queued);
|
||||
input->buffer_id = SPA_ID_INVALID;
|
||||
}
|
||||
if (min_queued == -1 || port->queued_bytes < min_queued)
|
||||
if (min_queued == -1 || (port->queued_bytes > 0 && port->queued_bytes < min_queued))
|
||||
min_queued = port->queued_bytes;
|
||||
|
||||
input->status = SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
if (min_queued != -1) {
|
||||
if (min_queued > 0) {
|
||||
MixerBuffer *outbuf;
|
||||
SpaPortIO *output;
|
||||
int j;
|
||||
int layer;
|
||||
|
||||
if (spa_list_is_empty (&outport->queue))
|
||||
return SPA_RESULT_OUT_OF_BUFFERS;
|
||||
|
||||
outbuf = spa_list_first (&outport->queue, MixerBuffer, link);
|
||||
spa_list_remove (&outbuf->link);
|
||||
spa_log_trace (this->log, "audiomixer %p: dequeue output buffer %d", this, outbuf->outbuf->id);
|
||||
spa_log_trace (this->log, "audiomixer %p: dequeue output buffer %d %zd", this, outbuf->outbuf->id, min_queued);
|
||||
outbuf->outstanding = true;
|
||||
outbuf->outbuf->datas[0].chunk->offset = 0;
|
||||
outbuf->outbuf->datas[0].chunk->size = min_queued;
|
||||
outbuf->outbuf->datas[0].chunk->stride = 0;
|
||||
|
||||
for (j = 0, i = 0; i < MAX_PORTS; i++) {
|
||||
for (layer = 0, i = 0; i < MAX_PORTS; i++) {
|
||||
SpaAudioMixerPort *port = &this->in_ports[i];
|
||||
|
||||
if (!port->valid || port->io == NULL ||
|
||||
spa_list_is_empty (&port->queue))
|
||||
if (port->io == NULL)
|
||||
continue;
|
||||
|
||||
add_port_data (this, outbuf, port, j++);
|
||||
if (spa_list_is_empty (&port->queue)) {
|
||||
spa_log_warn (this->log, "audiomixer %p: underrun stream %d", this, i);
|
||||
continue;
|
||||
}
|
||||
|
||||
add_port_data (this, outbuf, port, layer++);
|
||||
}
|
||||
output = outport->io;
|
||||
output->buffer_id = outbuf->outbuf->id;
|
||||
output->state = SPA_RESULT_OK;
|
||||
output->status = SPA_RESULT_OK;
|
||||
this->state = STATE_OUT;
|
||||
}
|
||||
return this->state == STATE_IN ? SPA_RESULT_NEED_INPUT : SPA_RESULT_HAVE_OUTPUT;
|
||||
|
|
@ -672,7 +720,7 @@ spa_audiomixer_node_process_output (SpaNode *node)
|
|||
for (i = 0; i < MAX_PORTS; i++) {
|
||||
SpaPortIO *input;
|
||||
|
||||
if (!this->in_ports[i].valid || (input = this->in_ports[i].io) == NULL)
|
||||
if ((input = this->in_ports[i].io) == NULL)
|
||||
continue;
|
||||
|
||||
input->flags = output->flags;
|
||||
|
|
@ -690,7 +738,6 @@ spa_audiomixer_node_process_output (SpaNode *node)
|
|||
static const SpaNode audiomixer_node = {
|
||||
sizeof (SpaNode),
|
||||
NULL,
|
||||
SPA_NODE_STATE_INIT,
|
||||
spa_audiomixer_node_get_props,
|
||||
spa_audiomixer_node_set_props,
|
||||
spa_audiomixer_node_send_command,
|
||||
|
|
@ -772,7 +819,7 @@ spa_audiomixer_init (const SpaHandleFactory *factory,
|
|||
|
||||
this->node = audiomixer_node;
|
||||
|
||||
this->out_ports[0].valid = true;
|
||||
this->out_ports[0].io = NULL;
|
||||
this->out_ports[0].info.flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS |
|
||||
SPA_PORT_INFO_FLAG_NO_REF;
|
||||
spa_list_init (&this->out_ports[0].queue);
|
||||
|
|
|
|||
|
|
@ -336,12 +336,6 @@ audiotestsrc_on_output (SpaSource *source)
|
|||
send_have_output (this);
|
||||
}
|
||||
|
||||
static void
|
||||
update_state (SpaAudioTestSrc *this, SpaNodeState state)
|
||||
{
|
||||
this->node.state = state;
|
||||
}
|
||||
|
||||
static SpaResult
|
||||
spa_audiotestsrc_node_send_command (SpaNode *node,
|
||||
SpaCommand *command)
|
||||
|
|
@ -375,7 +369,6 @@ spa_audiotestsrc_node_send_command (SpaNode *node,
|
|||
|
||||
this->started = true;
|
||||
set_timer (this, true);
|
||||
update_state (this, SPA_NODE_STATE_STREAMING);
|
||||
}
|
||||
else if (SPA_COMMAND_TYPE (command) == this->type.command_node.Pause) {
|
||||
if (!this->have_format)
|
||||
|
|
@ -389,7 +382,6 @@ spa_audiotestsrc_node_send_command (SpaNode *node,
|
|||
|
||||
this->started = false;
|
||||
set_timer (this, false);
|
||||
update_state (this, SPA_NODE_STATE_PAUSED);
|
||||
}
|
||||
else
|
||||
return SPA_RESULT_NOT_IMPLEMENTED;
|
||||
|
|
@ -605,10 +597,7 @@ spa_audiotestsrc_node_port_set_format (SpaNode *node,
|
|||
this->params[1] = SPA_POD_BUILDER_DEREF (&b, f[0].ref, SpaAllocParam);
|
||||
|
||||
this->info.extra = NULL;
|
||||
update_state (this, SPA_NODE_STATE_READY);
|
||||
}
|
||||
else
|
||||
update_state (this, SPA_NODE_STATE_CONFIGURE);
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
|
@ -729,12 +718,6 @@ spa_audiotestsrc_node_port_use_buffers (SpaNode *node,
|
|||
}
|
||||
this->n_buffers = n_buffers;
|
||||
|
||||
if (this->n_buffers > 0) {
|
||||
update_state (this, SPA_NODE_STATE_PAUSED);
|
||||
} else {
|
||||
update_state (this, SPA_NODE_STATE_READY);
|
||||
}
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
|
|
@ -853,7 +836,6 @@ spa_audiotestsrc_node_process_output (SpaNode *node)
|
|||
static const SpaNode audiotestsrc_node = {
|
||||
sizeof (SpaNode),
|
||||
NULL,
|
||||
SPA_NODE_STATE_INIT,
|
||||
spa_audiotestsrc_node_get_props,
|
||||
spa_audiotestsrc_node_set_props,
|
||||
spa_audiotestsrc_node_send_command,
|
||||
|
|
@ -1029,8 +1011,6 @@ audiotestsrc_init (const SpaHandleFactory *factory,
|
|||
if (this->props.live)
|
||||
this->info.flags |= SPA_PORT_INFO_FLAG_LIVE;
|
||||
|
||||
this->node.state = SPA_NODE_STATE_CONFIGURE;
|
||||
|
||||
spa_log_info (this->log, "audiotestsrc %p: initialized, async=%d", this, this->async);
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ typedef struct {
|
|||
bool have_buffers;
|
||||
FFMpegBuffer buffers[MAX_BUFFERS];
|
||||
SpaPortInfo info;
|
||||
void *io;
|
||||
SpaPortIO *io;
|
||||
} SpaFFMpegPort;
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -81,6 +81,8 @@ struct _SpaFFMpegDec {
|
|||
|
||||
SpaFFMpegPort in_ports[1];
|
||||
SpaFFMpegPort out_ports[1];
|
||||
|
||||
bool started;
|
||||
};
|
||||
|
||||
enum {
|
||||
|
|
@ -101,12 +103,6 @@ spa_ffmpeg_dec_node_set_props (SpaNode *node,
|
|||
return SPA_RESULT_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
static void
|
||||
update_state (SpaFFMpegDec *this, SpaNodeState state)
|
||||
{
|
||||
this->node.state = state;
|
||||
}
|
||||
|
||||
static SpaResult
|
||||
spa_ffmpeg_dec_node_send_command (SpaNode *node,
|
||||
SpaCommand *command)
|
||||
|
|
@ -119,10 +115,10 @@ spa_ffmpeg_dec_node_send_command (SpaNode *node,
|
|||
this = SPA_CONTAINER_OF (node, SpaFFMpegDec, node);
|
||||
|
||||
if (SPA_COMMAND_TYPE (command) == this->type.command_node.Start) {
|
||||
update_state (this, SPA_NODE_STATE_STREAMING);
|
||||
this->started = true;
|
||||
}
|
||||
else if (SPA_COMMAND_TYPE (command) == this->type.command_node.Pause) {
|
||||
update_state (this, SPA_NODE_STATE_PAUSED);
|
||||
this->started = false;
|
||||
}
|
||||
else
|
||||
return SPA_RESULT_NOT_IMPLEMENTED;
|
||||
|
|
@ -454,7 +450,6 @@ spa_ffmpeg_dec_node_port_send_command (SpaNode *node,
|
|||
static const SpaNode ffmpeg_dec_node = {
|
||||
sizeof (SpaNode),
|
||||
NULL,
|
||||
SPA_NODE_STATE_INIT,
|
||||
spa_ffmpeg_dec_node_get_props,
|
||||
spa_ffmpeg_dec_node_set_props,
|
||||
spa_ffmpeg_dec_node_send_command,
|
||||
|
|
|
|||
|
|
@ -86,18 +86,10 @@ struct _SpaFFMpegEnc {
|
|||
|
||||
SpaFFMpegPort in_ports[1];
|
||||
SpaFFMpegPort out_ports[1];
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_ID_LAST,
|
||||
bool started;
|
||||
};
|
||||
|
||||
static void
|
||||
update_state (SpaFFMpegEnc *this, SpaNodeState state)
|
||||
{
|
||||
this->node.state = state;
|
||||
}
|
||||
|
||||
static SpaResult
|
||||
spa_ffmpeg_enc_node_get_props (SpaNode *node,
|
||||
SpaProps **props)
|
||||
|
|
@ -124,10 +116,10 @@ spa_ffmpeg_enc_node_send_command (SpaNode *node,
|
|||
this = SPA_CONTAINER_OF (node, SpaFFMpegEnc, node);
|
||||
|
||||
if (SPA_COMMAND_TYPE (command) == this->type.command_node.Start) {
|
||||
update_state (this, SPA_NODE_STATE_STREAMING);
|
||||
this->started = true;
|
||||
}
|
||||
else if (SPA_COMMAND_TYPE (command) == this->type.command_node.Pause) {
|
||||
update_state (this, SPA_NODE_STATE_PAUSED);
|
||||
this->started = false;
|
||||
}
|
||||
else
|
||||
return SPA_RESULT_NOT_IMPLEMENTED;
|
||||
|
|
@ -461,7 +453,6 @@ spa_ffmpeg_enc_node_process_output (SpaNode *node)
|
|||
static const SpaNode ffmpeg_enc_node = {
|
||||
sizeof (SpaNode),
|
||||
NULL,
|
||||
SPA_NODE_STATE_INIT,
|
||||
spa_ffmpeg_enc_node_get_props,
|
||||
spa_ffmpeg_enc_node_set_props,
|
||||
spa_ffmpeg_enc_node_send_command,
|
||||
|
|
@ -534,7 +525,5 @@ spa_ffmpeg_enc_init (SpaHandle *handle,
|
|||
this->in_ports[0].info.flags = SPA_PORT_INFO_FLAG_NONE;
|
||||
this->out_ports[0].info.flags = SPA_PORT_INFO_FLAG_NONE;
|
||||
|
||||
this->node.state = SPA_NODE_STATE_CONFIGURE;
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ typedef struct {
|
|||
SpaPortInfo info;
|
||||
SpaAllocParam *params[2];
|
||||
uint8_t params_buffer[1024];
|
||||
void *io;
|
||||
SpaPortIO *io;
|
||||
|
||||
int64_t last_ticks;
|
||||
int64_t last_monotonic;
|
||||
|
|
@ -163,14 +163,8 @@ struct _SpaV4l2Source {
|
|||
SpaV4l2State state[1];
|
||||
};
|
||||
|
||||
#define CHECK_PORT(this, direction, port_id) ((direction) == SPA_DIRECTION_OUTPUT && (port_id) == 0)
|
||||
#define CHECK_PORT(this,direction,port_id) ((direction) == SPA_DIRECTION_OUTPUT && (port_id) == 0)
|
||||
|
||||
static void
|
||||
update_state (SpaV4l2Source *this, SpaNodeState state)
|
||||
{
|
||||
spa_log_info (this->log, "state: %d", state);
|
||||
this->node.state = state;
|
||||
}
|
||||
|
||||
#define PROP(f,key,type,...) \
|
||||
SPA_POD_PROP (f,key,0,type,1,__VA_ARGS__)
|
||||
|
|
@ -249,7 +243,6 @@ do_pause_done (SpaLoop *loop,
|
|||
|
||||
if (SPA_RESULT_IS_OK (ac->body.res.value)) {
|
||||
state->started = false;
|
||||
update_state (this, SPA_NODE_STATE_PAUSED);
|
||||
}
|
||||
this->event_cb (&this->node, (SpaEvent *)ac, this->user_data);
|
||||
|
||||
|
|
@ -300,7 +293,6 @@ do_start_done (SpaLoop *loop,
|
|||
|
||||
if (SPA_RESULT_IS_OK (ac->body.res.value)) {
|
||||
state->started = true;
|
||||
update_state (this, SPA_NODE_STATE_STREAMING);
|
||||
}
|
||||
this->event_cb (&this->node, (SpaEvent *)ac, this->user_data);
|
||||
|
||||
|
|
@ -515,7 +507,6 @@ spa_v4l2_source_node_port_set_format (SpaNode *node,
|
|||
spa_v4l2_clear_buffers (this);
|
||||
spa_v4l2_close (this);
|
||||
state->have_format = false;
|
||||
update_state (this, SPA_NODE_STATE_CONFIGURE);
|
||||
return SPA_RESULT_OK;
|
||||
} else {
|
||||
info.media_type = SPA_FORMAT_MEDIA_TYPE (format);
|
||||
|
|
@ -572,7 +563,6 @@ spa_v4l2_source_node_port_set_format (SpaNode *node,
|
|||
if (!(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) {
|
||||
state->current_format = info;
|
||||
state->have_format = true;
|
||||
update_state (this, SPA_NODE_STATE_READY);
|
||||
}
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
|
|
@ -706,12 +696,6 @@ spa_v4l2_source_node_port_use_buffers (SpaNode *node,
|
|||
if ((res = spa_v4l2_use_buffers (this, buffers, n_buffers)) < 0)
|
||||
return res;
|
||||
}
|
||||
|
||||
if (state->n_buffers)
|
||||
update_state (this, SPA_NODE_STATE_PAUSED);
|
||||
else
|
||||
update_state (this, SPA_NODE_STATE_READY);
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
|
|
@ -742,13 +726,6 @@ spa_v4l2_source_node_port_alloc_buffers (SpaNode *node,
|
|||
|
||||
res = spa_v4l2_alloc_buffers (this, params, n_params, buffers, n_buffers);
|
||||
|
||||
if (state->n_buffers) {
|
||||
if (state->started)
|
||||
update_state (this, SPA_NODE_STATE_STREAMING);
|
||||
else
|
||||
update_state (this, SPA_NODE_STATE_PAUSED);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
@ -850,7 +827,6 @@ spa_v4l2_source_node_process_output (SpaNode *node)
|
|||
static const SpaNode v4l2source_node = {
|
||||
sizeof (SpaNode),
|
||||
NULL,
|
||||
SPA_NODE_STATE_INIT,
|
||||
spa_v4l2_source_node_get_props,
|
||||
spa_v4l2_source_node_set_props,
|
||||
spa_v4l2_source_node_send_command,
|
||||
|
|
@ -1006,8 +982,6 @@ v4l2_source_init (const SpaHandleFactory *factory,
|
|||
strncpy (this->props.device, str, 63);
|
||||
}
|
||||
|
||||
update_state (this, SPA_NODE_STATE_CONFIGURE);
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ typedef struct {
|
|||
} SpaVideoTestSrcProps;
|
||||
|
||||
#define MAX_BUFFERS 16
|
||||
#define MAX_PORTS 1
|
||||
|
||||
typedef struct _VTSBuffer VTSBuffer;
|
||||
|
||||
|
|
@ -137,7 +138,8 @@ struct _SpaVideoTestSrc {
|
|||
SpaList empty;
|
||||
};
|
||||
|
||||
#define CHECK_PORT(this,d,p) ((d) == SPA_DIRECTION_OUTPUT && (p) == 0)
|
||||
#define CHECK_PORT_NUM(this,d,p) ((d) == SPA_DIRECTION_OUTPUT && (p) < MAX_PORTS)
|
||||
#define CHECK_PORT(this,d,p) (CHECK_PORT_NUM(this,d,p) && this->io)
|
||||
|
||||
#define DEFAULT_LIVE true
|
||||
#define DEFAULT_PATTERN pattern_smpte_snow
|
||||
|
|
@ -276,6 +278,7 @@ videotestsrc_make_buffer (SpaVideoTestSrc *this)
|
|||
|
||||
if (spa_list_is_empty (&this->empty)) {
|
||||
set_timer (this, false);
|
||||
spa_log_error (this->log, "videotestsrc %p: out of buffers", this);
|
||||
return SPA_RESULT_OUT_OF_BUFFERS;
|
||||
}
|
||||
b = spa_list_first (&this->empty, VTSBuffer, link);
|
||||
|
|
@ -321,13 +324,6 @@ videotestsrc_on_output (SpaSource *source)
|
|||
send_have_output (this);
|
||||
}
|
||||
|
||||
static void
|
||||
update_state (SpaVideoTestSrc *this, SpaNodeState state)
|
||||
{
|
||||
this->node.state = state;
|
||||
spa_log_info (this->log, "videotestsrc %p: update state %d", this, state);
|
||||
}
|
||||
|
||||
static SpaResult
|
||||
spa_videotestsrc_node_send_command (SpaNode *node,
|
||||
SpaCommand *command)
|
||||
|
|
@ -361,7 +357,6 @@ spa_videotestsrc_node_send_command (SpaNode *node,
|
|||
|
||||
this->started = true;
|
||||
set_timer (this, true);
|
||||
update_state (this, SPA_NODE_STATE_STREAMING);
|
||||
}
|
||||
else if (SPA_COMMAND_TYPE (command) == this->type.command_node.Pause) {
|
||||
if (!this->have_format)
|
||||
|
|
@ -375,7 +370,6 @@ spa_videotestsrc_node_send_command (SpaNode *node,
|
|||
|
||||
this->started = false;
|
||||
set_timer (this, false);
|
||||
update_state (this, SPA_NODE_STATE_PAUSED);
|
||||
}
|
||||
else
|
||||
return SPA_RESULT_NOT_IMPLEMENTED;
|
||||
|
|
@ -592,10 +586,7 @@ spa_videotestsrc_node_port_set_format (SpaNode *node,
|
|||
this->params[1] = SPA_POD_BUILDER_DEREF (&b, f[0].ref, SpaAllocParam);
|
||||
|
||||
this->info.extra = NULL;
|
||||
update_state (this, SPA_NODE_STATE_READY);
|
||||
}
|
||||
else
|
||||
update_state (this, SPA_NODE_STATE_CONFIGURE);
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
|
@ -715,12 +706,6 @@ spa_videotestsrc_node_port_use_buffers (SpaNode *node,
|
|||
}
|
||||
this->n_buffers = n_buffers;
|
||||
|
||||
if (this->n_buffers > 0) {
|
||||
update_state (this, SPA_NODE_STATE_PAUSED);
|
||||
} else {
|
||||
update_state (this, SPA_NODE_STATE_READY);
|
||||
}
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
|
|
@ -759,7 +744,7 @@ spa_videotestsrc_node_port_set_io (SpaNode *node,
|
|||
|
||||
this = SPA_CONTAINER_OF (node, SpaVideoTestSrc, node);
|
||||
|
||||
spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT);
|
||||
spa_return_val_if_fail (CHECK_PORT_NUM (this, direction, port_id), SPA_RESULT_INVALID_PORT);
|
||||
|
||||
this->io = io;
|
||||
|
||||
|
|
@ -839,7 +824,6 @@ spa_videotestsrc_node_process_output (SpaNode *node)
|
|||
static const SpaNode videotestsrc_node = {
|
||||
sizeof (SpaNode),
|
||||
NULL,
|
||||
SPA_NODE_STATE_INIT,
|
||||
spa_videotestsrc_node_get_props,
|
||||
spa_videotestsrc_node_set_props,
|
||||
spa_videotestsrc_node_send_command,
|
||||
|
|
@ -1015,8 +999,6 @@ videotestsrc_init (const SpaHandleFactory *factory,
|
|||
if (this->props.live)
|
||||
this->info.flags |= SPA_PORT_INFO_FLAG_LIVE;
|
||||
|
||||
this->node.state = SPA_NODE_STATE_CONFIGURE;
|
||||
|
||||
spa_log_info (this->log, "videotestsrc %p: initialized, async=%d", this, this->async);
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ typedef struct {
|
|||
|
||||
SpaVolumeBuffer buffers[MAX_BUFFERS];
|
||||
uint32_t n_buffers;
|
||||
void *io;
|
||||
SpaPortIO *io;
|
||||
|
||||
SpaList empty;
|
||||
} SpaVolumePort;
|
||||
|
|
@ -113,6 +113,8 @@ struct _SpaVolume {
|
|||
|
||||
SpaVolumePort in_ports[1];
|
||||
SpaVolumePort out_ports[1];
|
||||
|
||||
bool started;
|
||||
};
|
||||
|
||||
#define CHECK_IN_PORT(this,d,p) ((d) == SPA_DIRECTION_INPUT && (p) == 0)
|
||||
|
|
@ -129,12 +131,6 @@ reset_volume_props (SpaVolumeProps *props)
|
|||
props->mute = DEFAULT_MUTE;
|
||||
}
|
||||
|
||||
static void
|
||||
update_state (SpaVolume *this, SpaNodeState state)
|
||||
{
|
||||
this->node.state = state;
|
||||
}
|
||||
|
||||
#define PROP(f,key,type,...) \
|
||||
SPA_POD_PROP (f,key,0,type,1,__VA_ARGS__)
|
||||
#define PROP_MM(f,key,type,...) \
|
||||
|
|
@ -203,10 +199,10 @@ spa_volume_node_send_command (SpaNode *node,
|
|||
this = SPA_CONTAINER_OF (node, SpaVolume, node);
|
||||
|
||||
if (SPA_COMMAND_TYPE (command) == this->type.command_node.Start) {
|
||||
update_state (this, SPA_NODE_STATE_STREAMING);
|
||||
this->started = true;
|
||||
}
|
||||
else if (SPA_COMMAND_TYPE (command) == this->type.command_node.Pause) {
|
||||
update_state (this, SPA_NODE_STATE_PAUSED);
|
||||
this->started = false;
|
||||
}
|
||||
else
|
||||
return SPA_RESULT_NOT_IMPLEMENTED;
|
||||
|
|
@ -410,10 +406,7 @@ spa_volume_node_port_set_format (SpaNode *node,
|
|||
port->params[1] = SPA_POD_BUILDER_DEREF (&b, f[0].ref, SpaAllocParam);
|
||||
|
||||
port->info.extra = NULL;
|
||||
update_state (this, SPA_NODE_STATE_READY);
|
||||
}
|
||||
else
|
||||
update_state (this, SPA_NODE_STATE_CONFIGURE);
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
|
@ -535,11 +528,6 @@ spa_volume_node_port_use_buffers (SpaNode *node,
|
|||
}
|
||||
port->n_buffers = n_buffers;
|
||||
|
||||
if (port->n_buffers > 0) {
|
||||
update_state (this, SPA_NODE_STATE_PAUSED);
|
||||
} else {
|
||||
update_state (this, SPA_NODE_STATE_READY);
|
||||
}
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
|
|
@ -747,7 +735,6 @@ spa_volume_node_process_output (SpaNode *node)
|
|||
static const SpaNode volume_node = {
|
||||
sizeof (SpaNode),
|
||||
NULL,
|
||||
SPA_NODE_STATE_INIT,
|
||||
spa_volume_node_get_props,
|
||||
spa_volume_node_set_props,
|
||||
spa_volume_node_send_command,
|
||||
|
|
|
|||
|
|
@ -123,12 +123,6 @@ struct _SpaXvSink {
|
|||
|
||||
#include "xv-utils.c"
|
||||
|
||||
static void
|
||||
update_state (SpaXvSink *this, SpaNodeState state)
|
||||
{
|
||||
this->node.state = state;
|
||||
}
|
||||
|
||||
#define PROP(f,key,type,...) \
|
||||
SPA_POD_PROP (f,key,0,type,1,__VA_ARGS__)
|
||||
#define PROP_R(f,key,type,...) \
|
||||
|
|
@ -191,13 +185,9 @@ spa_xv_sink_node_send_command (SpaNode *node,
|
|||
|
||||
if (SPA_COMMAND_TYPE (command) == this->type.command_node.Start) {
|
||||
spa_xv_start (this);
|
||||
|
||||
update_state (this, SPA_NODE_STATE_STREAMING);
|
||||
}
|
||||
else if (SPA_COMMAND_TYPE (command) == this->type.command_node.Pause) {
|
||||
spa_xv_stop (this);
|
||||
|
||||
update_state (this, SPA_NODE_STATE_PAUSED);
|
||||
}
|
||||
else
|
||||
return SPA_RESULT_NOT_IMPLEMENTED;
|
||||
|
|
@ -489,7 +479,6 @@ spa_xv_sink_node_process_output (SpaNode *node)
|
|||
static const SpaNode xvsink_node = {
|
||||
sizeof (SpaNode),
|
||||
NULL,
|
||||
SPA_NODE_STATE_INIT,
|
||||
spa_xv_sink_node_get_props,
|
||||
spa_xv_sink_node_set_props,
|
||||
spa_xv_sink_node_send_command,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue