mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	Add sync and async support in *testsrc
Make minumum alsa latency configurable.
This commit is contained in:
		
							parent
							
								
									01c13adab5
								
							
						
					
					
						commit
						5c32690cc8
					
				
					 13 changed files with 186 additions and 153 deletions
				
			
		| 
						 | 
				
			
			@ -500,7 +500,6 @@ handle_rtnode_event (PinosStream  *stream,
 | 
			
		|||
  }
 | 
			
		||||
  else if (SPA_EVENT_TYPE (event) == context->type.event_node.NeedInput) {
 | 
			
		||||
    int i;
 | 
			
		||||
    BufferId *bid;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < impl->trans->area->n_outputs; i++) {
 | 
			
		||||
      SpaPortIO *output = &impl->trans->outputs[i];
 | 
			
		||||
| 
						 | 
				
			
			@ -516,7 +515,6 @@ handle_rtnode_event (PinosStream  *stream,
 | 
			
		|||
  }
 | 
			
		||||
  else if (SPA_EVENT_TYPE (event) == context->type.event_node.ReuseBuffer) {
 | 
			
		||||
    SpaEventNodeReuseBuffer *p = (SpaEventNodeReuseBuffer *) event;
 | 
			
		||||
    BufferId *bid;
 | 
			
		||||
 | 
			
		||||
    if (p->body.port_id.value != impl->port_id)
 | 
			
		||||
      return;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -51,6 +51,8 @@ pinos_spa_node_load (PinosCore  *core,
 | 
			
		|||
  SpaEnumHandleFactoryFunc enum_func;
 | 
			
		||||
  const SpaHandleFactory *factory;
 | 
			
		||||
  void *iface;
 | 
			
		||||
  SpaDictItem items[1];
 | 
			
		||||
  SpaDict dict = SPA_DICT_INIT (1, items);
 | 
			
		||||
 | 
			
		||||
  if ((hnd = dlopen (lib, RTLD_NOW)) == NULL) {
 | 
			
		||||
    pinos_log_error ("can't load %s: %s", lib, dlerror());
 | 
			
		||||
| 
						 | 
				
			
			@ -71,10 +73,13 @@ pinos_spa_node_load (PinosCore  *core,
 | 
			
		|||
      break;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  items[0].key = "asynchronous";
 | 
			
		||||
  items[0].value = "1";
 | 
			
		||||
 | 
			
		||||
  handle = calloc (1, factory->size);
 | 
			
		||||
  if ((res = spa_handle_factory_init (factory,
 | 
			
		||||
                                      handle,
 | 
			
		||||
                                      NULL,
 | 
			
		||||
                                      &dict,
 | 
			
		||||
                                      core->support,
 | 
			
		||||
                                      core->n_support)) < 0) {
 | 
			
		||||
    pinos_log_error ("can't make factory instance: %d", res);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -798,14 +798,11 @@ static SpaResult
 | 
			
		|||
spa_proxy_node_process_output (SpaNode *node)
 | 
			
		||||
{
 | 
			
		||||
  SpaProxy *this;
 | 
			
		||||
  PinosNode *pnode;
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  if (node == NULL)
 | 
			
		||||
    return SPA_RESULT_INVALID_ARGUMENTS;
 | 
			
		||||
 | 
			
		||||
  this = SPA_CONTAINER_OF (node, SpaProxy, node);
 | 
			
		||||
  pnode = this->pnode;
 | 
			
		||||
 | 
			
		||||
  send_need_input (this);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -37,6 +37,7 @@ typedef SpaPODObject SpaProps;
 | 
			
		|||
#define SPA_TYPE_PROPS__deviceFd             SPA_TYPE_PROPS_BASE "deviceFd"
 | 
			
		||||
#define SPA_TYPE_PROPS__card                 SPA_TYPE_PROPS_BASE "card"
 | 
			
		||||
#define SPA_TYPE_PROPS__cardName             SPA_TYPE_PROPS_BASE "cardName"
 | 
			
		||||
#define SPA_TYPE_PROPS__minLatency           SPA_TYPE_PROPS_BASE "minLatency"
 | 
			
		||||
#define SPA_TYPE_PROPS__periods              SPA_TYPE_PROPS_BASE "periods"
 | 
			
		||||
#define SPA_TYPE_PROPS__periodSize           SPA_TYPE_PROPS_BASE "periodSize"
 | 
			
		||||
#define SPA_TYPE_PROPS__periodEvent          SPA_TYPE_PROPS_BASE "periodEvent"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -474,7 +474,7 @@ spa_debug_dict (const SpaDict *dict)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define DEFAULT_LOG_LEVEL SPA_LOG_LEVEL_TRACE
 | 
			
		||||
#define DEFAULT_LOG_LEVEL SPA_LOG_LEVEL_DEBUG
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
do_logv (SpaLog        *log,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -32,17 +32,13 @@
 | 
			
		|||
typedef struct _SpaALSAState SpaALSASink;
 | 
			
		||||
 | 
			
		||||
static const char default_device[] = "default";
 | 
			
		||||
static const uint32_t default_period_size = 128;
 | 
			
		||||
static const uint32_t default_periods = 2;
 | 
			
		||||
static const bool default_period_event = 0;
 | 
			
		||||
static const uint32_t default_min_latency = 1024;
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
reset_alsa_sink_props (SpaALSAProps *props)
 | 
			
		||||
{
 | 
			
		||||
  strncpy (props->device, default_device, 64);
 | 
			
		||||
  props->period_size = default_period_size;
 | 
			
		||||
  props->periods = default_periods;
 | 
			
		||||
  props->period_event = default_period_event;
 | 
			
		||||
  props->min_latency = default_min_latency;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
| 
						 | 
				
			
			@ -83,9 +79,7 @@ spa_alsa_sink_node_get_props (SpaNode       *node,
 | 
			
		|||
        PROP    (&f[1], this->type.prop_device,      -SPA_POD_TYPE_STRING, this->props.device, sizeof (this->props.device)),
 | 
			
		||||
        PROP    (&f[1], this->type.prop_device_name, -SPA_POD_TYPE_STRING, this->props.device_name, sizeof (this->props.device_name)),
 | 
			
		||||
        PROP    (&f[1], this->type.prop_card_name,   -SPA_POD_TYPE_STRING, this->props.card_name, sizeof (this->props.card_name)),
 | 
			
		||||
        PROP_MM (&f[1], this->type.prop_period_size,  SPA_POD_TYPE_INT,    this->props.period_size, 1, INT32_MAX),
 | 
			
		||||
        PROP_MM (&f[1], this->type.prop_periods,      SPA_POD_TYPE_INT,    this->props.periods, 1, INT32_MAX),
 | 
			
		||||
        PROP    (&f[1], this->type.prop_period_event, SPA_POD_TYPE_BOOL,   this->props.period_event));
 | 
			
		||||
        PROP_MM (&f[1], this->type.prop_min_latency,  SPA_POD_TYPE_INT,    this->props.min_latency, 1, INT32_MAX));
 | 
			
		||||
 | 
			
		||||
  *props = SPA_POD_BUILDER_DEREF (&b, f[0].ref, SpaProps);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -109,9 +103,7 @@ spa_alsa_sink_node_set_props (SpaNode         *node,
 | 
			
		|||
  } else {
 | 
			
		||||
    spa_props_query (props,
 | 
			
		||||
        this->type.prop_device,      -SPA_POD_TYPE_STRING, this->props.device, sizeof (this->props.device),
 | 
			
		||||
        this->type.prop_period_size,  SPA_POD_TYPE_INT,    &this->props.period_size,
 | 
			
		||||
        this->type.prop_periods,      SPA_POD_TYPE_INT,    &this->props.periods,
 | 
			
		||||
        this->type.prop_period_event, SPA_POD_TYPE_BOOL,   &this->props.period_event,
 | 
			
		||||
        this->type.prop_min_latency,  SPA_POD_TYPE_INT,    &this->props.min_latency,
 | 
			
		||||
        0);
 | 
			
		||||
  }
 | 
			
		||||
  return SPA_RESULT_OK;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -39,17 +39,13 @@ update_state (SpaALSASource *this, SpaNodeState state)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static const char default_device[] = "hw:0";
 | 
			
		||||
static const uint32_t default_period_size = 32;
 | 
			
		||||
static const uint32_t default_periods = 2;
 | 
			
		||||
static const bool default_period_event = 0;
 | 
			
		||||
static const uint32_t default_min_latency = 1024;
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
reset_alsa_props (SpaALSAProps *props)
 | 
			
		||||
{
 | 
			
		||||
  strncpy (props->device, default_device, 64);
 | 
			
		||||
  props->period_size = default_period_size;
 | 
			
		||||
  props->periods = default_periods;
 | 
			
		||||
  props->period_event = default_period_event;
 | 
			
		||||
  props->min_latency = default_min_latency;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define PROP(f,key,type,...)                                                    \
 | 
			
		||||
| 
						 | 
				
			
			@ -84,9 +80,7 @@ spa_alsa_source_node_get_props (SpaNode       *node,
 | 
			
		|||
    PROP    (&f[1], this->type.prop_device,      -SPA_POD_TYPE_STRING, this->props.device, sizeof (this->props.device)),
 | 
			
		||||
    PROP    (&f[1], this->type.prop_device_name, -SPA_POD_TYPE_STRING, this->props.device_name, sizeof (this->props.device_name)),
 | 
			
		||||
    PROP    (&f[1], this->type.prop_card_name,   -SPA_POD_TYPE_STRING, this->props.card_name, sizeof (this->props.card_name)),
 | 
			
		||||
    PROP_MM (&f[1], this->type.prop_period_size,  SPA_POD_TYPE_INT,    this->props.period_size, 1, INT32_MAX),
 | 
			
		||||
    PROP_MM (&f[1], this->type.prop_periods,      SPA_POD_TYPE_INT,    this->props.periods, 1, INT32_MAX),
 | 
			
		||||
    PROP    (&f[1], this->type.prop_period_event, SPA_POD_TYPE_BOOL,   this->props.period_event));
 | 
			
		||||
    PROP_MM (&f[1], this->type.prop_min_latency,  SPA_POD_TYPE_INT,    this->props.min_latency, 1, INT32_MAX));
 | 
			
		||||
 | 
			
		||||
  *props = SPA_POD_BUILDER_DEREF (&b, f[0].ref, SpaProps);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -110,9 +104,7 @@ spa_alsa_source_node_set_props (SpaNode         *node,
 | 
			
		|||
  } else {
 | 
			
		||||
    spa_props_query (props,
 | 
			
		||||
        this->type.prop_device,      -SPA_POD_TYPE_STRING, this->props.device, sizeof (this->props.device),
 | 
			
		||||
        this->type.prop_period_size,  SPA_POD_TYPE_INT,    &this->props.period_size,
 | 
			
		||||
        this->type.prop_periods,      SPA_POD_TYPE_INT,    &this->props.periods,
 | 
			
		||||
        this->type.prop_period_event, SPA_POD_TYPE_BOOL,   &this->props.period_event,
 | 
			
		||||
        this->type.prop_min_latency,  SPA_POD_TYPE_INT,    &this->props.min_latency,
 | 
			
		||||
        0);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -117,7 +117,6 @@ spa_alsa_set_format (SpaALSAState *state, SpaAudioInfo *fmt, SpaPortFormatFlags
 | 
			
		|||
  SpaAudioInfoRaw *info = &fmt->info.raw;
 | 
			
		||||
  snd_pcm_t *hndl;
 | 
			
		||||
  unsigned int periods;
 | 
			
		||||
  SpaALSAProps *props = &state->props;
 | 
			
		||||
 | 
			
		||||
  if ((err = spa_alsa_open (state)) < 0)
 | 
			
		||||
    return err;
 | 
			
		||||
| 
						 | 
				
			
			@ -195,8 +194,6 @@ set_swparams (SpaALSAState *state)
 | 
			
		|||
  snd_pcm_sw_params_t *params;
 | 
			
		||||
  snd_pcm_uframes_t boundary;
 | 
			
		||||
 | 
			
		||||
  SpaALSAProps *props = &state->props;
 | 
			
		||||
 | 
			
		||||
  snd_pcm_sw_params_alloca (¶ms);
 | 
			
		||||
 | 
			
		||||
  /* get the current params */
 | 
			
		||||
| 
						 | 
				
			
			@ -618,7 +615,7 @@ spa_alsa_start (SpaALSAState *state, bool xrun_recover)
 | 
			
		|||
  state->source.rmask = 0;
 | 
			
		||||
  spa_loop_add_source (state->data_loop, &state->source);
 | 
			
		||||
 | 
			
		||||
  state->threshold = 1024;
 | 
			
		||||
  state->threshold = state->props.min_latency;
 | 
			
		||||
 | 
			
		||||
  if (state->stream == SND_PCM_STREAM_PLAYBACK) {
 | 
			
		||||
    state->alsa_started = false;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -45,9 +45,7 @@ typedef struct {
 | 
			
		|||
  char device[64];
 | 
			
		||||
  char device_name[128];
 | 
			
		||||
  char card_name[128];
 | 
			
		||||
  uint32_t period_size;
 | 
			
		||||
  uint32_t periods;
 | 
			
		||||
  bool period_event;
 | 
			
		||||
  uint32_t min_latency;
 | 
			
		||||
} SpaALSAProps;
 | 
			
		||||
 | 
			
		||||
#define MAX_BUFFERS 64
 | 
			
		||||
| 
						 | 
				
			
			@ -68,9 +66,7 @@ typedef struct {
 | 
			
		|||
  uint32_t prop_device;
 | 
			
		||||
  uint32_t prop_device_name;
 | 
			
		||||
  uint32_t prop_card_name;
 | 
			
		||||
  uint32_t prop_period_size;
 | 
			
		||||
  uint32_t prop_periods;
 | 
			
		||||
  uint32_t prop_period_event;
 | 
			
		||||
  uint32_t prop_min_latency;
 | 
			
		||||
  SpaTypeMediaType media_type;
 | 
			
		||||
  SpaTypeMediaSubtype media_subtype;
 | 
			
		||||
  SpaTypeMediaSubtypeAudio media_subtype_audio;
 | 
			
		||||
| 
						 | 
				
			
			@ -92,9 +88,7 @@ init_type (Type *type, SpaTypeMap *map)
 | 
			
		|||
  type->prop_device = spa_type_map_get_id (map, SPA_TYPE_PROPS__device);
 | 
			
		||||
  type->prop_device_name = spa_type_map_get_id (map, SPA_TYPE_PROPS__deviceName);
 | 
			
		||||
  type->prop_card_name = spa_type_map_get_id (map, SPA_TYPE_PROPS__cardName);
 | 
			
		||||
  type->prop_period_size = spa_type_map_get_id (map, SPA_TYPE_PROPS__periodSize);
 | 
			
		||||
  type->prop_periods = spa_type_map_get_id (map, SPA_TYPE_PROPS__periods);
 | 
			
		||||
  type->prop_period_event = spa_type_map_get_id (map, SPA_TYPE_PROPS__periodEvent);
 | 
			
		||||
  type->prop_min_latency = spa_type_map_get_id (map, SPA_TYPE_PROPS__minLatency);
 | 
			
		||||
 | 
			
		||||
  spa_type_media_type_map (map, &type->media_type);
 | 
			
		||||
  spa_type_media_subtype_map (map, &type->media_subtype);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -452,7 +452,7 @@ spa_audiomixer_node_port_use_buffers (SpaNode         *node,
 | 
			
		|||
 | 
			
		||||
    b = &port->buffers[i];
 | 
			
		||||
    b->outbuf = buffers[i];
 | 
			
		||||
    b->outstanding = true;
 | 
			
		||||
    b->outstanding = direction == SPA_DIRECTION_INPUT ? true : false;
 | 
			
		||||
    b->h = spa_buffer_find_meta (buffers[i], SPA_META_TYPE_HEADER);
 | 
			
		||||
 | 
			
		||||
    switch (d[0].type) {
 | 
			
		||||
| 
						 | 
				
			
			@ -516,11 +516,34 @@ spa_audiomixer_node_port_set_io (SpaNode      *node,
 | 
			
		|||
  return SPA_RESULT_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
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);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static SpaResult
 | 
			
		||||
spa_audiomixer_node_port_reuse_buffer (SpaNode         *node,
 | 
			
		||||
                                       uint32_t         port_id,
 | 
			
		||||
                                       uint32_t         buffer_id)
 | 
			
		||||
{
 | 
			
		||||
  SpaAudioMixer *this;
 | 
			
		||||
 | 
			
		||||
  spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
 | 
			
		||||
 | 
			
		||||
  this = SPA_CONTAINER_OF (node, SpaAudioMixer, node);
 | 
			
		||||
 | 
			
		||||
  spa_return_val_if_fail (CHECK_PORT (this, SPA_DIRECTION_OUTPUT, port_id), SPA_RESULT_INVALID_PORT);
 | 
			
		||||
 | 
			
		||||
  recycle_buffer (this, buffer_id);
 | 
			
		||||
 | 
			
		||||
  return SPA_RESULT_NOT_IMPLEMENTED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -664,15 +687,11 @@ spa_audiomixer_node_process_output (SpaNode *node)
 | 
			
		|||
    input->range = output->range;
 | 
			
		||||
  }
 | 
			
		||||
  if (output->buffer_id != SPA_ID_INVALID) {
 | 
			
		||||
    MixerBuffer *b = &port->buffers[output->buffer_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, b->outbuf->id);
 | 
			
		||||
    }
 | 
			
		||||
    recycle_buffer (this, output->buffer_id);
 | 
			
		||||
    output->buffer_id = SPA_ID_INVALID;
 | 
			
		||||
  }
 | 
			
		||||
  this->state = STATE_IN;
 | 
			
		||||
 | 
			
		||||
  return SPA_RESULT_NEED_INPUT;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -112,6 +112,7 @@ struct _SpaAudioTestSrc {
 | 
			
		|||
  SpaTypeMap *map;
 | 
			
		||||
  SpaLog *log;
 | 
			
		||||
  SpaLoop *data_loop;
 | 
			
		||||
  bool async;
 | 
			
		||||
 | 
			
		||||
  uint8_t props_buffer[512];
 | 
			
		||||
  SpaAudioTestSrcProps props;
 | 
			
		||||
| 
						 | 
				
			
			@ -239,7 +240,6 @@ send_have_output (SpaAudioTestSrc *this)
 | 
			
		|||
    SpaEvent event = SPA_EVENT_INIT (this->type.event_node.HaveOutput);
 | 
			
		||||
    this->event_cb (&this->node, &event, this->user_data);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return SPA_RESULT_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -280,6 +280,10 @@ audiotestsrc_make_buffer (SpaAudioTestSrc *this)
 | 
			
		|||
{
 | 
			
		||||
  ATSBuffer *b;
 | 
			
		||||
  SpaPortIO *io;
 | 
			
		||||
  uint64_t expirations;
 | 
			
		||||
 | 
			
		||||
  if (read (this->timer_source.fd, &expirations, sizeof (uint64_t)) < sizeof (uint64_t))
 | 
			
		||||
    perror ("read timerfd");
 | 
			
		||||
 | 
			
		||||
  if (spa_list_is_empty (&this->empty)) {
 | 
			
		||||
    set_timer (this, false);
 | 
			
		||||
| 
						 | 
				
			
			@ -306,20 +310,18 @@ audiotestsrc_make_buffer (SpaAudioTestSrc *this)
 | 
			
		|||
    io->buffer_id = b->outbuf->id;
 | 
			
		||||
    io->status = SPA_RESULT_OK;
 | 
			
		||||
  }
 | 
			
		||||
  return SPA_RESULT_OK;
 | 
			
		||||
  return SPA_RESULT_HAVE_OUTPUT;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
audiotestsrc_on_output (SpaSource *source)
 | 
			
		||||
{
 | 
			
		||||
  SpaAudioTestSrc *this = source->data;
 | 
			
		||||
  uint64_t expirations;
 | 
			
		||||
  SpaResult res;
 | 
			
		||||
 | 
			
		||||
  if (read (this->timer_source.fd, &expirations, sizeof (uint64_t)) < sizeof (uint64_t))
 | 
			
		||||
    perror ("read timerfd");
 | 
			
		||||
 | 
			
		||||
  audiotestsrc_make_buffer (this);
 | 
			
		||||
  res = audiotestsrc_make_buffer (this);
 | 
			
		||||
 | 
			
		||||
  if (res == SPA_RESULT_HAVE_OUTPUT)
 | 
			
		||||
    send_have_output (this);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -396,15 +398,9 @@ spa_audiotestsrc_node_set_event_callback (SpaNode              *node,
 | 
			
		|||
 | 
			
		||||
  this = SPA_CONTAINER_OF (node, SpaAudioTestSrc, node);
 | 
			
		||||
 | 
			
		||||
  if (event_cb == NULL && this->event_cb)
 | 
			
		||||
    spa_loop_remove_source (this->data_loop, &this->timer_source);
 | 
			
		||||
 | 
			
		||||
  this->event_cb = event_cb;
 | 
			
		||||
  this->user_data = user_data;
 | 
			
		||||
 | 
			
		||||
  if (this->event_cb) {
 | 
			
		||||
    spa_loop_add_source (this->data_loop, &this->timer_source);
 | 
			
		||||
  }
 | 
			
		||||
  return SPA_RESULT_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -768,13 +764,27 @@ spa_audiotestsrc_node_port_set_io (SpaNode       *node,
 | 
			
		|||
  return SPA_RESULT_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void
 | 
			
		||||
reuse_buffer (SpaAudioTestSrc *this, uint32_t id)
 | 
			
		||||
{
 | 
			
		||||
  ATSBuffer *b = &this->buffers[id];
 | 
			
		||||
  spa_return_if_fail (b->outstanding);
 | 
			
		||||
 | 
			
		||||
  spa_log_trace (this->log, "audiotestsrc %p: reuse buffer %d", this, id);
 | 
			
		||||
 | 
			
		||||
  b->outstanding = false;
 | 
			
		||||
  spa_list_insert (this->empty.prev, &b->link);
 | 
			
		||||
 | 
			
		||||
  if (!this->props.live)
 | 
			
		||||
    set_timer (this, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static SpaResult
 | 
			
		||||
spa_audiotestsrc_node_port_reuse_buffer (SpaNode         *node,
 | 
			
		||||
                                         uint32_t         port_id,
 | 
			
		||||
                                         uint32_t         buffer_id)
 | 
			
		||||
{
 | 
			
		||||
  SpaAudioTestSrc *this;
 | 
			
		||||
  ATSBuffer *b;
 | 
			
		||||
 | 
			
		||||
  spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -784,16 +794,7 @@ spa_audiotestsrc_node_port_reuse_buffer (SpaNode         *node,
 | 
			
		|||
  spa_return_val_if_fail (this->n_buffers > 0, SPA_RESULT_NO_BUFFERS);
 | 
			
		||||
  spa_return_val_if_fail (buffer_id < this->n_buffers, SPA_RESULT_INVALID_BUFFER_ID);
 | 
			
		||||
 | 
			
		||||
  b = &this->buffers[buffer_id];
 | 
			
		||||
  spa_return_val_if_fail (b->outstanding, SPA_RESULT_INVALID_BUFFER_ID);
 | 
			
		||||
 | 
			
		||||
  spa_log_trace (this->log, "audiotestsrc %p: reuse buffer %d", this, b->outbuf->id);
 | 
			
		||||
 | 
			
		||||
  b->outstanding = false;
 | 
			
		||||
  spa_list_insert (this->empty.prev, &b->link);
 | 
			
		||||
 | 
			
		||||
  if (!this->props.live)
 | 
			
		||||
    set_timer (this, true);
 | 
			
		||||
  reuse_buffer (this, buffer_id);
 | 
			
		||||
 | 
			
		||||
  return SPA_RESULT_OK;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -816,29 +817,21 @@ spa_audiotestsrc_node_process_input (SpaNode *node)
 | 
			
		|||
static SpaResult
 | 
			
		||||
spa_audiotestsrc_node_process_output (SpaNode *node)
 | 
			
		||||
{
 | 
			
		||||
  SpaResult res;
 | 
			
		||||
  SpaAudioTestSrc *this;
 | 
			
		||||
  ATSBuffer *b;
 | 
			
		||||
 | 
			
		||||
  spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
 | 
			
		||||
 | 
			
		||||
  this = SPA_CONTAINER_OF (node, SpaAudioTestSrc, node);
 | 
			
		||||
 | 
			
		||||
  if (this->io && this->io->buffer_id != SPA_ID_INVALID) {
 | 
			
		||||
    b = &this->buffers[this->io->buffer_id];
 | 
			
		||||
    if (b->outstanding) {
 | 
			
		||||
      b->outstanding = false;
 | 
			
		||||
      spa_log_trace (this->log, "audiotestsrc %p: recycle buffer %d", this, b->outbuf->id);
 | 
			
		||||
      spa_list_insert (this->empty.prev, &b->link);
 | 
			
		||||
      if (!this->props.live)
 | 
			
		||||
        set_timer (this, true);
 | 
			
		||||
    }
 | 
			
		||||
    reuse_buffer (this, this->io->buffer_id);
 | 
			
		||||
    this->io->buffer_id = SPA_ID_INVALID;
 | 
			
		||||
  }
 | 
			
		||||
  if ((res = audiotestsrc_make_buffer (this)) < 0)
 | 
			
		||||
    return res;
 | 
			
		||||
 | 
			
		||||
  return SPA_RESULT_HAVE_OUTPUT;
 | 
			
		||||
  if (!this->async)
 | 
			
		||||
    return audiotestsrc_make_buffer (this);
 | 
			
		||||
  else
 | 
			
		||||
    return SPA_RESULT_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const SpaNode audiotestsrc_node = {
 | 
			
		||||
| 
						 | 
				
			
			@ -949,6 +942,7 @@ audiotestsrc_clear (SpaHandle *handle)
 | 
			
		|||
 | 
			
		||||
  this = (SpaAudioTestSrc *) handle;
 | 
			
		||||
 | 
			
		||||
  spa_loop_remove_source (this->data_loop, &this->timer_source);
 | 
			
		||||
  close (this->timer_source.fd);
 | 
			
		||||
 | 
			
		||||
  return SPA_RESULT_OK;
 | 
			
		||||
| 
						 | 
				
			
			@ -963,6 +957,7 @@ audiotestsrc_init (const SpaHandleFactory  *factory,
 | 
			
		|||
{
 | 
			
		||||
  SpaAudioTestSrc *this;
 | 
			
		||||
  uint32_t i;
 | 
			
		||||
  const char *str;
 | 
			
		||||
 | 
			
		||||
  if (factory == NULL || handle == NULL)
 | 
			
		||||
    return SPA_RESULT_INVALID_ARGUMENTS;
 | 
			
		||||
| 
						 | 
				
			
			@ -972,6 +967,11 @@ audiotestsrc_init (const SpaHandleFactory  *factory,
 | 
			
		|||
 | 
			
		||||
  this = (SpaAudioTestSrc *) handle;
 | 
			
		||||
 | 
			
		||||
  if (info && (str = spa_dict_lookup (info, "asynchronous")))
 | 
			
		||||
    this->async = atoi (str) == 1;
 | 
			
		||||
  else
 | 
			
		||||
    this->async = false;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < n_support; i++) {
 | 
			
		||||
    if (strcmp (support[i].type, SPA_TYPE__TypeMap) == 0)
 | 
			
		||||
      this->map = support[i].data;
 | 
			
		||||
| 
						 | 
				
			
			@ -984,7 +984,7 @@ audiotestsrc_init (const SpaHandleFactory  *factory,
 | 
			
		|||
    spa_log_error (this->log, "a type-map is needed");
 | 
			
		||||
    return SPA_RESULT_ERROR;
 | 
			
		||||
  }
 | 
			
		||||
  if (this->data_loop == NULL) {
 | 
			
		||||
  if (this->data_loop == NULL && this->async) {
 | 
			
		||||
    spa_log_error (this->log, "a data_loop is needed");
 | 
			
		||||
    return SPA_RESULT_ERROR;
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -998,7 +998,7 @@ audiotestsrc_init (const SpaHandleFactory  *factory,
 | 
			
		|||
 | 
			
		||||
  this->timer_source.func = audiotestsrc_on_output;
 | 
			
		||||
  this->timer_source.data = this;
 | 
			
		||||
  this->timer_source.fd = timerfd_create (CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
 | 
			
		||||
  this->timer_source.fd = timerfd_create (CLOCK_MONOTONIC, TFD_CLOEXEC);
 | 
			
		||||
  this->timer_source.mask = SPA_IO_IN;
 | 
			
		||||
  this->timer_source.rmask = 0;
 | 
			
		||||
  this->timerspec.it_value.tv_sec = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -1006,6 +1006,9 @@ audiotestsrc_init (const SpaHandleFactory  *factory,
 | 
			
		|||
  this->timerspec.it_interval.tv_sec = 0;
 | 
			
		||||
  this->timerspec.it_interval.tv_nsec = 0;
 | 
			
		||||
 | 
			
		||||
  if (this->data_loop && this->async)
 | 
			
		||||
    spa_loop_add_source (this->data_loop, &this->timer_source);
 | 
			
		||||
 | 
			
		||||
  this->info.flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS |
 | 
			
		||||
                     SPA_PORT_INFO_FLAG_NO_REF;
 | 
			
		||||
  if (this->props.live)
 | 
			
		||||
| 
						 | 
				
			
			@ -1013,6 +1016,8 @@ audiotestsrc_init (const SpaHandleFactory  *factory,
 | 
			
		|||
 | 
			
		||||
  this->node.state = SPA_NODE_STATE_CONFIGURE;
 | 
			
		||||
 | 
			
		||||
  spa_log_info (this->log, "audiotestsrc %p: initialized, async=%d", this, this->async);
 | 
			
		||||
 | 
			
		||||
  return SPA_RESULT_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -106,6 +106,7 @@ struct _SpaVideoTestSrc {
 | 
			
		|||
  SpaTypeMap *map;
 | 
			
		||||
  SpaLog *log;
 | 
			
		||||
  SpaLoop *data_loop;
 | 
			
		||||
  bool async;
 | 
			
		||||
 | 
			
		||||
  uint8_t props_buffer[512];
 | 
			
		||||
  SpaVideoTestSrcProps props;
 | 
			
		||||
| 
						 | 
				
			
			@ -177,7 +178,6 @@ spa_videotestsrc_node_get_props (SpaNode       *node,
 | 
			
		|||
  this = SPA_CONTAINER_OF (node, SpaVideoTestSrc, node);
 | 
			
		||||
 | 
			
		||||
  spa_pod_builder_init (&b, this->props_buffer, sizeof (this->props_buffer));
 | 
			
		||||
 | 
			
		||||
  spa_pod_builder_props (&b, &f[0], this->type.props,
 | 
			
		||||
    PROP    (&f[1], this->type.prop_live,      SPA_POD_TYPE_BOOL, this->props.live),
 | 
			
		||||
    PROP_EN (&f[1], this->type.prop_pattern,   SPA_POD_TYPE_ID,  3,
 | 
			
		||||
| 
						 | 
				
			
			@ -256,10 +256,9 @@ set_timer (SpaVideoTestSrc *this, bool enabled)
 | 
			
		|||
  timerfd_settime (this->timer_source.fd, TFD_TIMER_ABSTIME, &this->timerspec, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
videotestsrc_on_output (SpaSource *source)
 | 
			
		||||
static SpaResult
 | 
			
		||||
videotestsrc_make_buffer (SpaVideoTestSrc *this)
 | 
			
		||||
{
 | 
			
		||||
  SpaVideoTestSrc *this = source->data;
 | 
			
		||||
  VTSBuffer *b;
 | 
			
		||||
  SpaPortIO *io;
 | 
			
		||||
  uint64_t expirations;
 | 
			
		||||
| 
						 | 
				
			
			@ -269,10 +268,12 @@ videotestsrc_on_output (SpaSource *source)
 | 
			
		|||
 | 
			
		||||
  if (spa_list_is_empty (&this->empty)) {
 | 
			
		||||
    set_timer (this, false);
 | 
			
		||||
    return;
 | 
			
		||||
    return SPA_RESULT_OUT_OF_BUFFERS;
 | 
			
		||||
  }
 | 
			
		||||
  b = spa_list_first (&this->empty, VTSBuffer, link);
 | 
			
		||||
  spa_list_remove (&b->link);
 | 
			
		||||
  b->outstanding = true;
 | 
			
		||||
  spa_log_trace (this->log, "videotestsrc %p: dequeue buffer %d", this, b->outbuf->id);
 | 
			
		||||
 | 
			
		||||
  fill_buffer (this, b);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -287,11 +288,22 @@ videotestsrc_on_output (SpaSource *source)
 | 
			
		|||
  set_timer (this, true);
 | 
			
		||||
 | 
			
		||||
  if ((io = this->io)) {
 | 
			
		||||
    b->outstanding = true;
 | 
			
		||||
    io->buffer_id = b->outbuf->id;
 | 
			
		||||
    io->status = SPA_RESULT_OK;
 | 
			
		||||
    send_have_output (this);
 | 
			
		||||
  }
 | 
			
		||||
  return SPA_RESULT_HAVE_OUTPUT;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
videotestsrc_on_output (SpaSource *source)
 | 
			
		||||
{
 | 
			
		||||
  SpaVideoTestSrc *this = source->data;
 | 
			
		||||
  SpaResult res;
 | 
			
		||||
 | 
			
		||||
  res = videotestsrc_make_buffer (this);
 | 
			
		||||
 | 
			
		||||
  if (res == SPA_RESULT_HAVE_OUTPUT)
 | 
			
		||||
    send_have_output (this);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
| 
						 | 
				
			
			@ -367,15 +379,9 @@ spa_videotestsrc_node_set_event_callback (SpaNode              *node,
 | 
			
		|||
 | 
			
		||||
  this = SPA_CONTAINER_OF (node, SpaVideoTestSrc, node);
 | 
			
		||||
 | 
			
		||||
  if (event_cb == NULL && this->event_cb)
 | 
			
		||||
    spa_loop_remove_source (this->data_loop, &this->timer_source);
 | 
			
		||||
 | 
			
		||||
  this->event_cb = event_cb;
 | 
			
		||||
  this->user_data = user_data;
 | 
			
		||||
 | 
			
		||||
  if (this->event_cb) {
 | 
			
		||||
    spa_loop_add_source (this->data_loop, &this->timer_source);
 | 
			
		||||
  }
 | 
			
		||||
  return SPA_RESULT_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -479,7 +485,6 @@ next:
 | 
			
		|||
    default:
 | 
			
		||||
      return SPA_RESULT_ENUM_END;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  fmt = SPA_POD_BUILDER_DEREF (&b, f[0].ref, SpaFormat);
 | 
			
		||||
 | 
			
		||||
  spa_pod_builder_init (&b, this->format_buffer, sizeof (this->format_buffer));
 | 
			
		||||
| 
						 | 
				
			
			@ -605,7 +610,6 @@ spa_videotestsrc_node_port_get_format (SpaNode          *node,
 | 
			
		|||
    return SPA_RESULT_NO_FORMAT;
 | 
			
		||||
 | 
			
		||||
  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.video, this->type.media_subtype.raw,
 | 
			
		||||
     PROP (&f[1], this->type.format_video.format,     SPA_POD_TYPE_ID,        this->current_format.info.raw.format),
 | 
			
		||||
| 
						 | 
				
			
			@ -747,50 +751,48 @@ spa_videotestsrc_node_port_set_io (SpaNode       *node,
 | 
			
		|||
{
 | 
			
		||||
  SpaVideoTestSrc *this;
 | 
			
		||||
 | 
			
		||||
  if (node == NULL)
 | 
			
		||||
    return SPA_RESULT_INVALID_ARGUMENTS;
 | 
			
		||||
  spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
 | 
			
		||||
 | 
			
		||||
  this = SPA_CONTAINER_OF (node, SpaVideoTestSrc, node);
 | 
			
		||||
 | 
			
		||||
  if (!CHECK_PORT (this, direction, port_id))
 | 
			
		||||
    return SPA_RESULT_INVALID_PORT;
 | 
			
		||||
  spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT);
 | 
			
		||||
 | 
			
		||||
  this->io = io;
 | 
			
		||||
 | 
			
		||||
  return SPA_RESULT_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void
 | 
			
		||||
reuse_buffer (SpaVideoTestSrc *this, uint32_t id)
 | 
			
		||||
{
 | 
			
		||||
  VTSBuffer *b = &this->buffers[id];
 | 
			
		||||
  spa_return_if_fail (b->outstanding);
 | 
			
		||||
 | 
			
		||||
  spa_log_trace (this->log, "videotestsrc %p: reuse buffer %d", this, id);
 | 
			
		||||
 | 
			
		||||
  b->outstanding = false;
 | 
			
		||||
  spa_list_insert (this->empty.prev, &b->link);
 | 
			
		||||
 | 
			
		||||
  if (!this->props.live)
 | 
			
		||||
    set_timer (this, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static SpaResult
 | 
			
		||||
spa_videotestsrc_node_port_reuse_buffer (SpaNode         *node,
 | 
			
		||||
                                         uint32_t         port_id,
 | 
			
		||||
                                         uint32_t         buffer_id)
 | 
			
		||||
{
 | 
			
		||||
  SpaVideoTestSrc *this;
 | 
			
		||||
  VTSBuffer *b;
 | 
			
		||||
 | 
			
		||||
  if (node == NULL)
 | 
			
		||||
    return SPA_RESULT_INVALID_ARGUMENTS;
 | 
			
		||||
  spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
 | 
			
		||||
 | 
			
		||||
  this = SPA_CONTAINER_OF (node, SpaVideoTestSrc, node);
 | 
			
		||||
 | 
			
		||||
  if (port_id != 0)
 | 
			
		||||
    return SPA_RESULT_INVALID_PORT;
 | 
			
		||||
  spa_return_val_if_fail (port_id == 0, SPA_RESULT_INVALID_PORT);
 | 
			
		||||
  spa_return_val_if_fail (this->n_buffers > 0, SPA_RESULT_NO_BUFFERS);
 | 
			
		||||
  spa_return_val_if_fail (buffer_id < this->n_buffers, SPA_RESULT_INVALID_BUFFER_ID);
 | 
			
		||||
 | 
			
		||||
  if (this->n_buffers == 0)
 | 
			
		||||
    return SPA_RESULT_NO_BUFFERS;
 | 
			
		||||
 | 
			
		||||
  if (buffer_id >= this->n_buffers)
 | 
			
		||||
    return SPA_RESULT_INVALID_BUFFER_ID;
 | 
			
		||||
 | 
			
		||||
  b = &this->buffers[buffer_id];
 | 
			
		||||
  if (!b->outstanding)
 | 
			
		||||
    return SPA_RESULT_OK;
 | 
			
		||||
 | 
			
		||||
  b->outstanding = false;
 | 
			
		||||
  spa_list_insert (this->empty.prev, &b->link);
 | 
			
		||||
 | 
			
		||||
  if (!this->props.live)
 | 
			
		||||
    set_timer (this, true);
 | 
			
		||||
  reuse_buffer (this, buffer_id);
 | 
			
		||||
 | 
			
		||||
  return SPA_RESULT_OK;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -814,23 +816,19 @@ static SpaResult
 | 
			
		|||
spa_videotestsrc_node_process_output (SpaNode *node)
 | 
			
		||||
{
 | 
			
		||||
  SpaVideoTestSrc *this;
 | 
			
		||||
  VTSBuffer *b;
 | 
			
		||||
 | 
			
		||||
  if (node == NULL)
 | 
			
		||||
    return SPA_RESULT_INVALID_ARGUMENTS;
 | 
			
		||||
  spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
 | 
			
		||||
 | 
			
		||||
  this = SPA_CONTAINER_OF (node, SpaVideoTestSrc, node);
 | 
			
		||||
 | 
			
		||||
  if (this->io && this->io->buffer_id != SPA_ID_INVALID) {
 | 
			
		||||
    b = &this->buffers[this->io->buffer_id];
 | 
			
		||||
    if (b->outstanding) {
 | 
			
		||||
      b->outstanding = false;
 | 
			
		||||
      spa_list_insert (this->empty.prev, &b->link);
 | 
			
		||||
      if (!this->props.live)
 | 
			
		||||
        set_timer (this, true);
 | 
			
		||||
    }
 | 
			
		||||
    reuse_buffer (this, this->io->buffer_id);
 | 
			
		||||
    this->io->buffer_id = SPA_ID_INVALID;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (!this->async)
 | 
			
		||||
    return videotestsrc_make_buffer (this);
 | 
			
		||||
  else
 | 
			
		||||
    return SPA_RESULT_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -942,6 +940,7 @@ videotestsrc_clear (SpaHandle *handle)
 | 
			
		|||
 | 
			
		||||
  this = (SpaVideoTestSrc *) handle;
 | 
			
		||||
 | 
			
		||||
  spa_loop_remove_source (this->data_loop, &this->timer_source);
 | 
			
		||||
  close (this->timer_source.fd);
 | 
			
		||||
 | 
			
		||||
  return SPA_RESULT_OK;
 | 
			
		||||
| 
						 | 
				
			
			@ -956,6 +955,7 @@ videotestsrc_init (const SpaHandleFactory  *factory,
 | 
			
		|||
{
 | 
			
		||||
  SpaVideoTestSrc *this;
 | 
			
		||||
  uint32_t i;
 | 
			
		||||
  const char *str;
 | 
			
		||||
 | 
			
		||||
  if (factory == NULL || handle == NULL)
 | 
			
		||||
    return SPA_RESULT_INVALID_ARGUMENTS;
 | 
			
		||||
| 
						 | 
				
			
			@ -965,6 +965,11 @@ videotestsrc_init (const SpaHandleFactory  *factory,
 | 
			
		|||
 | 
			
		||||
  this = (SpaVideoTestSrc *) handle;
 | 
			
		||||
 | 
			
		||||
  if (info && (str = spa_dict_lookup (info, "asynchronous")))
 | 
			
		||||
    this->async = atoi (str) == 1;
 | 
			
		||||
  else
 | 
			
		||||
    this->async = false;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < n_support; i++) {
 | 
			
		||||
    if (strcmp (support[i].type, SPA_TYPE__TypeMap) == 0)
 | 
			
		||||
      this->map = support[i].data;
 | 
			
		||||
| 
						 | 
				
			
			@ -974,10 +979,10 @@ videotestsrc_init (const SpaHandleFactory  *factory,
 | 
			
		|||
      this->data_loop = support[i].data;
 | 
			
		||||
  }
 | 
			
		||||
  if (this->map == NULL) {
 | 
			
		||||
    spa_log_error (this->log, "an id-map is needed");
 | 
			
		||||
    spa_log_error (this->log, "a type-map is needed");
 | 
			
		||||
    return SPA_RESULT_ERROR;
 | 
			
		||||
  }
 | 
			
		||||
  if (this->data_loop == NULL) {
 | 
			
		||||
  if (this->data_loop == NULL && this->async) {
 | 
			
		||||
    spa_log_error (this->log, "a data_loop is needed");
 | 
			
		||||
    return SPA_RESULT_ERROR;
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -991,7 +996,7 @@ videotestsrc_init (const SpaHandleFactory  *factory,
 | 
			
		|||
 | 
			
		||||
  this->timer_source.func = videotestsrc_on_output;
 | 
			
		||||
  this->timer_source.data = this;
 | 
			
		||||
  this->timer_source.fd = timerfd_create (CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
 | 
			
		||||
  this->timer_source.fd = timerfd_create (CLOCK_MONOTONIC, TFD_CLOEXEC);
 | 
			
		||||
  this->timer_source.mask = SPA_IO_IN;
 | 
			
		||||
  this->timer_source.rmask = 0;
 | 
			
		||||
  this->timerspec.it_value.tv_sec = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -999,6 +1004,9 @@ videotestsrc_init (const SpaHandleFactory  *factory,
 | 
			
		|||
  this->timerspec.it_interval.tv_sec = 0;
 | 
			
		||||
  this->timerspec.it_interval.tv_nsec = 0;
 | 
			
		||||
 | 
			
		||||
  if (this->data_loop && this->async)
 | 
			
		||||
    spa_loop_add_source (this->data_loop, &this->timer_source);
 | 
			
		||||
 | 
			
		||||
  this->info.flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS |
 | 
			
		||||
                     SPA_PORT_INFO_FLAG_NO_REF;
 | 
			
		||||
  if (this->props.live)
 | 
			
		||||
| 
						 | 
				
			
			@ -1006,6 +1014,8 @@ videotestsrc_init (const SpaHandleFactory  *factory,
 | 
			
		|||
 | 
			
		||||
  this->node.state = SPA_NODE_STATE_CONFIGURE;
 | 
			
		||||
 | 
			
		||||
  spa_log_info (this->log, "videotestsrc %p: initialized, async=%d", this, this->async);
 | 
			
		||||
 | 
			
		||||
  return SPA_RESULT_OK;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -141,7 +141,7 @@ init_buffer (AppData *data, Buffer *b, void *ptr, size_t size)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static SpaResult
 | 
			
		||||
make_node (AppData *data, SpaNode **node, const char *lib, const char *name)
 | 
			
		||||
make_node (AppData *data, SpaNode **node, const char *lib, const char *name, bool async)
 | 
			
		||||
{
 | 
			
		||||
  SpaHandle *handle;
 | 
			
		||||
  SpaResult res;
 | 
			
		||||
| 
						 | 
				
			
			@ -149,6 +149,8 @@ make_node (AppData *data, SpaNode **node, const char *lib, const char *name)
 | 
			
		|||
  SpaEnumHandleFactoryFunc enum_func;
 | 
			
		||||
  unsigned int i;
 | 
			
		||||
  uint32_t state = 0;
 | 
			
		||||
  SpaDictItem items[1];
 | 
			
		||||
  SpaDict dict = SPA_DICT_INIT (1, items);
 | 
			
		||||
 | 
			
		||||
  if ((hnd = dlopen (lib, RTLD_NOW)) == NULL) {
 | 
			
		||||
    printf ("can't load %s: %s\n", lib, dlerror());
 | 
			
		||||
| 
						 | 
				
			
			@ -159,6 +161,9 @@ make_node (AppData *data, SpaNode **node, const char *lib, const char *name)
 | 
			
		|||
    return SPA_RESULT_ERROR;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  items[0].key = "asynchronous";
 | 
			
		||||
  items[0].value = async ? "1" : "0";
 | 
			
		||||
 | 
			
		||||
  for (i = 0; ;i++) {
 | 
			
		||||
    const SpaHandleFactory *factory;
 | 
			
		||||
    void *iface;
 | 
			
		||||
| 
						 | 
				
			
			@ -172,7 +177,7 @@ make_node (AppData *data, SpaNode **node, const char *lib, const char *name)
 | 
			
		|||
      continue;
 | 
			
		||||
 | 
			
		||||
    handle = calloc (1, factory->size);
 | 
			
		||||
    if ((res = spa_handle_factory_init (factory, handle, NULL, data->support, data->n_support)) < 0) {
 | 
			
		||||
    if ((res = spa_handle_factory_init (factory, handle, &dict, data->support, data->n_support)) < 0) {
 | 
			
		||||
      printf ("can't make factory instance: %d\n", res);
 | 
			
		||||
      return res;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -194,7 +199,6 @@ on_sink_event (SpaNode *node, SpaEvent *event, void *user_data)
 | 
			
		|||
 | 
			
		||||
  if (SPA_EVENT_TYPE (event) == data->type.event_node.NeedInput) {
 | 
			
		||||
 | 
			
		||||
    printf ("need input event\n");
 | 
			
		||||
    res = spa_node_process_output (data->mix);
 | 
			
		||||
 | 
			
		||||
    if (res == SPA_RESULT_NEED_INPUT) {
 | 
			
		||||
| 
						 | 
				
			
			@ -226,7 +230,6 @@ push:
 | 
			
		|||
  else if (SPA_EVENT_TYPE (event) == data->type.event_node.ReuseBuffer) {
 | 
			
		||||
    SpaEventNodeReuseBuffer *rb = (SpaEventNodeReuseBuffer *) event;
 | 
			
		||||
 | 
			
		||||
    printf ("got recycle event %d\n", rb->body.buffer_id.value);
 | 
			
		||||
    data->mix_sink_io[0].buffer_id = rb->body.buffer_id.value;
 | 
			
		||||
  }
 | 
			
		||||
  else {
 | 
			
		||||
| 
						 | 
				
			
			@ -278,7 +281,9 @@ make_nodes (AppData *data)
 | 
			
		|||
  SpaPODFrame f[2];
 | 
			
		||||
  uint8_t buffer[128];
 | 
			
		||||
 | 
			
		||||
  if ((res = make_node (data, &data->sink, "build/spa/plugins/alsa/libspa-alsa.so", "alsa-sink")) < 0) {
 | 
			
		||||
  if ((res = make_node (data, &data->sink,
 | 
			
		||||
                        "build/spa/plugins/alsa/libspa-alsa.so",
 | 
			
		||||
                        "alsa-sink", true)) < 0) {
 | 
			
		||||
    printf ("can't create alsa-sink: %d\n", res);
 | 
			
		||||
    return res;
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -293,15 +298,21 @@ make_nodes (AppData *data)
 | 
			
		|||
  if ((res = spa_node_set_props (data->sink, props)) < 0)
 | 
			
		||||
    printf ("got set_props error %d\n", res);
 | 
			
		||||
 | 
			
		||||
  if ((res = make_node (data, &data->mix, "build/spa/plugins/audiomixer/libspa-audiomixer.so", "audiomixer")) < 0) {
 | 
			
		||||
  if ((res = make_node (data, &data->mix,
 | 
			
		||||
                        "build/spa/plugins/audiomixer/libspa-audiomixer.so",
 | 
			
		||||
                        "audiomixer", false)) < 0) {
 | 
			
		||||
    printf ("can't create audiomixer: %d\n", res);
 | 
			
		||||
    return res;
 | 
			
		||||
  }
 | 
			
		||||
  if ((res = make_node (data, &data->source1, "build/spa/plugins/audiotestsrc/libspa-audiotestsrc.so", "audiotestsrc")) < 0) {
 | 
			
		||||
  if ((res = make_node (data, &data->source1,
 | 
			
		||||
                        "build/spa/plugins/audiotestsrc/libspa-audiotestsrc.so",
 | 
			
		||||
                        "audiotestsrc", false)) < 0) {
 | 
			
		||||
    printf ("can't create audiotestsrc: %d\n", res);
 | 
			
		||||
    return res;
 | 
			
		||||
  }
 | 
			
		||||
  if ((res = make_node (data, &data->source2, "build/spa/plugins/audiotestsrc/libspa-audiotestsrc.so", "audiotestsrc")) < 0) {
 | 
			
		||||
  if ((res = make_node (data, &data->source2,
 | 
			
		||||
                        "build/spa/plugins/audiotestsrc/libspa-audiotestsrc.so",
 | 
			
		||||
                        "audiotestsrc", false)) < 0) {
 | 
			
		||||
    printf ("can't create audiotestsrc: %d\n", res);
 | 
			
		||||
    return res;
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -462,8 +473,14 @@ run_async_sink (AppData *data)
 | 
			
		|||
 | 
			
		||||
  {
 | 
			
		||||
    SpaCommand cmd = SPA_COMMAND_INIT (data->type.command_node.Start);
 | 
			
		||||
    if ((res = spa_node_send_command (data->source1, &cmd)) < 0)
 | 
			
		||||
      printf ("got source1 error %d\n", res);
 | 
			
		||||
    if ((res = spa_node_send_command (data->source2, &cmd)) < 0)
 | 
			
		||||
      printf ("got source2 error %d\n", res);
 | 
			
		||||
    if ((res = spa_node_send_command (data->mix, &cmd)) < 0)
 | 
			
		||||
      printf ("got mix error %d\n", res);
 | 
			
		||||
    if ((res = spa_node_send_command (data->sink, &cmd)) < 0)
 | 
			
		||||
      printf ("got error %d\n", res);
 | 
			
		||||
      printf ("got sink error %d\n", res);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  data->running = true;
 | 
			
		||||
| 
						 | 
				
			
			@ -484,6 +501,12 @@ run_async_sink (AppData *data)
 | 
			
		|||
    SpaCommand cmd = SPA_COMMAND_INIT (data->type.command_node.Pause);
 | 
			
		||||
    if ((res = spa_node_send_command (data->sink, &cmd)) < 0)
 | 
			
		||||
      printf ("got error %d\n", res);
 | 
			
		||||
    if ((res = spa_node_send_command (data->mix, &cmd)) < 0)
 | 
			
		||||
      printf ("got mix error %d\n", res);
 | 
			
		||||
    if ((res = spa_node_send_command (data->source1, &cmd)) < 0)
 | 
			
		||||
      printf ("got source1 error %d\n", res);
 | 
			
		||||
    if ((res = spa_node_send_command (data->source2, &cmd)) < 0)
 | 
			
		||||
      printf ("got source2 error %d\n", res);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue