command: make commands dynamic

Ensure format object type.
This commit is contained in:
Wim Taymans 2017-03-22 10:04:24 +01:00
parent 4d9f2c5161
commit c44a7c9735
36 changed files with 549 additions and 604 deletions

View file

@ -211,10 +211,10 @@ typedef struct {
PinosClientNodeBuffer *buffers); PinosClientNodeBuffer *buffers);
void (*node_command) (void *object, void (*node_command) (void *object,
uint32_t seq, uint32_t seq,
const SpaNodeCommand *command); const SpaCommand *command);
void (*port_command) (void *object, void (*port_command) (void *object,
uint32_t port_id, uint32_t port_id,
const SpaNodeCommand *command); const SpaCommand *command);
void (*transport) (void *object, void (*transport) (void *object,
int memfd, int memfd,
uint32_t offset, uint32_t offset,

View file

@ -836,7 +836,7 @@ client_node_demarshal_node_command (void *object,
{ {
PinosProxy *proxy = object; PinosProxy *proxy = object;
SpaPODIter it; SpaPODIter it;
const SpaNodeCommand *command; const SpaCommand *command;
uint32_t seq; uint32_t seq;
if (!spa_pod_iter_struct (&it, data, size) || if (!spa_pod_iter_struct (&it, data, size) ||
@ -857,7 +857,7 @@ client_node_demarshal_port_command (void *object,
{ {
PinosProxy *proxy = object; PinosProxy *proxy = object;
SpaPODIter it; SpaPODIter it;
const SpaNodeCommand *command; const SpaCommand *command;
uint32_t port_id; uint32_t port_id;
if (!spa_pod_iter_struct (&it, data, size) || if (!spa_pod_iter_struct (&it, data, size) ||

View file

@ -573,58 +573,45 @@ handle_node_event (PinosStream *stream,
} }
static bool static bool
handle_node_command (PinosStream *stream, handle_node_command (PinosStream *stream,
uint32_t seq, uint32_t seq,
const SpaNodeCommand *command) const SpaCommand *command)
{ {
PinosStreamImpl *impl = SPA_CONTAINER_OF (stream, PinosStreamImpl, this); PinosStreamImpl *impl = SPA_CONTAINER_OF (stream, PinosStreamImpl, this);
PinosContext *context = stream->context;
switch (SPA_NODE_COMMAND_TYPE (command)) { if (SPA_COMMAND_TYPE (command) == context->uri.node_commands.Pause) {
case SPA_NODE_COMMAND_INVALID: pinos_log_debug ("stream %p: pause %d", stream, seq);
break;
case SPA_NODE_COMMAND_PAUSE:
{
pinos_log_debug ("stream %p: pause %d", stream, seq);
add_state_change (stream, SPA_NODE_STATE_PAUSED, false); 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, true);
stream_set_state (stream, PINOS_STREAM_STATE_PAUSED, NULL); stream_set_state (stream, PINOS_STREAM_STATE_PAUSED, NULL);
break; }
} else if (SPA_COMMAND_TYPE (command) == context->uri.node_commands.Start) {
case SPA_NODE_COMMAND_START: pinos_log_debug ("stream %p: start %d", stream, seq);
{ add_state_change (stream, SPA_NODE_STATE_STREAMING, false);
pinos_log_debug ("stream %p: start %d", stream, seq); add_async_complete (stream, seq, SPA_RESULT_OK, true);
add_state_change (stream, SPA_NODE_STATE_STREAMING, false);
add_async_complete (stream, seq, SPA_RESULT_OK, true);
if (impl->direction == SPA_DIRECTION_INPUT) if (impl->direction == SPA_DIRECTION_INPUT)
send_need_input (stream); send_need_input (stream);
stream_set_state (stream, PINOS_STREAM_STATE_STREAMING, NULL); stream_set_state (stream, PINOS_STREAM_STATE_STREAMING, NULL);
break; }
} else if (SPA_COMMAND_TYPE (command) == context->uri.node_commands.ClockUpdate) {
case SPA_NODE_COMMAND_FLUSH: SpaNodeCommandClockUpdate *cu = (SpaNodeCommandClockUpdate *) command;
case SPA_NODE_COMMAND_DRAIN: if (cu->body.flags.value & SPA_NODE_COMMAND_CLOCK_UPDATE_FLAG_LIVE) {
case SPA_NODE_COMMAND_MARKER: pinos_properties_set (stream->properties,
{ "pinos.latency.is-live", "1");
pinos_log_warn ("unhandled node command %d", SPA_NODE_COMMAND_TYPE (command)); pinos_properties_setf (stream->properties,
add_async_complete (stream, seq, SPA_RESULT_NOT_IMPLEMENTED, true); "pinos.latency.min", "%"PRId64, cu->body.latency.value);
break;
}
case SPA_NODE_COMMAND_CLOCK_UPDATE:
{
SpaNodeCommandClockUpdate *cu = (SpaNodeCommandClockUpdate *) command;
if (cu->body.flags.value & SPA_NODE_COMMAND_CLOCK_UPDATE_FLAG_LIVE) {
pinos_properties_set (stream->properties,
"pinos.latency.is-live", "1");
pinos_properties_setf (stream->properties,
"pinos.latency.min", "%"PRId64, cu->body.latency.value);
}
impl->last_ticks = cu->body.ticks.value;
impl->last_rate = cu->body.rate.value;
impl->last_monotonic = cu->body.monotonic_time.value;
break;
} }
impl->last_ticks = cu->body.ticks.value;
impl->last_rate = cu->body.rate.value;
impl->last_monotonic = cu->body.monotonic_time.value;
}
else {
pinos_log_warn ("unhandled node command %d", SPA_COMMAND_TYPE (command));
add_async_complete (stream, seq, SPA_RESULT_NOT_IMPLEMENTED, true);
} }
return true; return true;
} }
@ -853,9 +840,9 @@ client_node_use_buffers (void *object,
} }
static void static void
client_node_node_command (void *object, client_node_node_command (void *object,
uint32_t seq, uint32_t seq,
const SpaNodeCommand *command) const SpaCommand *command)
{ {
PinosProxy *proxy = object; PinosProxy *proxy = object;
PinosStream *stream = proxy->user_data; PinosStream *stream = proxy->user_data;
@ -863,9 +850,9 @@ client_node_node_command (void *object,
} }
static void static void
client_node_port_command (void *object, client_node_port_command (void *object,
uint32_t port_id, uint32_t port_id,
const SpaNodeCommand *command) const SpaCommand *command)
{ {
pinos_log_warn ("port command not supported"); pinos_log_warn ("port command not supported");
} }

View file

@ -50,4 +50,5 @@ pinos_uri_init (PinosURI *uri)
uri->spa_monitor = spa_id_map_get_id (uri->map, SPA_MONITOR_URI); uri->spa_monitor = spa_id_map_get_id (uri->map, SPA_MONITOR_URI);
spa_node_events_map (uri->map, &uri->node_events); spa_node_events_map (uri->map, &uri->node_events);
spa_node_commands_map (uri->map, &uri->node_commands);
} }

View file

@ -55,6 +55,7 @@ struct _PinosURI {
uint32_t spa_monitor; uint32_t spa_monitor;
SpaNodeEvents node_events; SpaNodeEvents node_events;
SpaNodeCommands node_commands;
}; };
void pinos_uri_init (PinosURI *uri); void pinos_uri_init (PinosURI *uri);

View file

@ -37,6 +37,7 @@ typedef struct {
uint32_t *media_subtype; uint32_t *media_subtype;
} MediaType; } MediaType;
static uint32_t format_type;
static SpaMediaTypes media_types = { 0, }; static SpaMediaTypes media_types = { 0, };
static SpaMediaSubtypes media_subtypes = { 0, }; static SpaMediaSubtypes media_subtypes = { 0, };
static SpaMediaSubtypesVideo media_subtypes_video = { 0, }; static SpaMediaSubtypesVideo media_subtypes_video = { 0, };
@ -49,14 +50,17 @@ static SpaAudioFormats audio_formats = { 0, };
static void static void
ensure_types (void) ensure_types (void)
{ {
spa_media_types_fill (&media_types, spa_id_map_get_default ()); SpaIDMap *map = spa_id_map_get_default ();
spa_media_subtypes_map (spa_id_map_get_default (), &media_subtypes);
spa_media_subtypes_video_map (spa_id_map_get_default (), &media_subtypes_video); format_type = spa_id_map_get_id (map, SPA_FORMAT_URI);
spa_media_subtypes_audio_map (spa_id_map_get_default (), &media_subtypes_audio); spa_media_types_fill (&media_types, map);
spa_prop_video_map (spa_id_map_get_default (), &prop_video); spa_media_subtypes_map (map, &media_subtypes);
spa_prop_audio_map (spa_id_map_get_default (), &prop_audio); spa_media_subtypes_video_map (map, &media_subtypes_video);
spa_video_formats_map (spa_id_map_get_default (), &video_formats); spa_media_subtypes_audio_map (map, &media_subtypes_audio);
spa_audio_formats_map (spa_id_map_get_default (), &audio_formats); spa_prop_video_map (map, &prop_video);
spa_prop_audio_map (map, &prop_audio);
spa_video_formats_map (map, &video_formats);
spa_audio_formats_map (map, &audio_formats);
} }
static const MediaType media_type_map[] = { static const MediaType media_type_map[] = {
@ -516,7 +520,7 @@ convert_1 (GstCapsFeatures *cf, GstStructure *cs)
d.b.write = write_pod; d.b.write = write_pod;
spa_pod_builder_push_format (&d.b, &f, spa_pod_builder_push_format (&d.b, &f, format_type,
*d.type->media_type, *d.type->media_type,
*d.type->media_subtype); *d.type->media_subtype);

View file

@ -185,11 +185,12 @@ send_have_output (SpaProxy *this)
} }
static SpaResult static SpaResult
spa_proxy_node_send_command (SpaNode *node, spa_proxy_node_send_command (SpaNode *node,
SpaNodeCommand *command) SpaCommand *command)
{ {
SpaProxy *this; SpaProxy *this;
SpaResult res = SPA_RESULT_OK; SpaResult res = SPA_RESULT_OK;
PinosCore *core;
if (node == NULL || command == NULL) if (node == NULL || command == NULL)
return SPA_RESULT_INVALID_ARGUMENTS; return SPA_RESULT_INVALID_ARGUMENTS;
@ -199,30 +200,22 @@ spa_proxy_node_send_command (SpaNode *node,
if (this->resource == NULL) if (this->resource == NULL)
return SPA_RESULT_OK; return SPA_RESULT_OK;
switch (SPA_NODE_COMMAND_TYPE (command)) { core = this->pnode->core;
case SPA_NODE_COMMAND_INVALID:
return SPA_RESULT_INVALID_COMMAND;
case SPA_NODE_COMMAND_START: if (SPA_COMMAND_TYPE (command) == core->uri.node_commands.ClockUpdate) {
case SPA_NODE_COMMAND_PAUSE: pinos_client_node_notify_node_command (this->resource,
case SPA_NODE_COMMAND_FLUSH: this->seq++,
case SPA_NODE_COMMAND_DRAIN: command);
case SPA_NODE_COMMAND_MARKER: }
/* send start */ else {
pinos_client_node_notify_node_command (this->resource, /* send start */
this->seq, pinos_client_node_notify_node_command (this->resource,
command); this->seq,
if (SPA_NODE_COMMAND_TYPE (command) == SPA_NODE_COMMAND_START) command);
send_need_input (this); if (SPA_COMMAND_TYPE (command) == core->uri.node_commands.Start)
send_need_input (this);
res = SPA_RESULT_RETURN_ASYNC (this->seq++); res = SPA_RESULT_RETURN_ASYNC (this->seq++);
break;
case SPA_NODE_COMMAND_CLOCK_UPDATE:
pinos_client_node_notify_node_command (this->resource,
this->seq++,
command);
break;
} }
return res; return res;
} }
@ -790,33 +783,17 @@ static SpaResult
spa_proxy_node_port_send_command (SpaNode *node, spa_proxy_node_port_send_command (SpaNode *node,
SpaDirection direction, SpaDirection direction,
uint32_t port_id, uint32_t port_id,
SpaNodeCommand *command) SpaCommand *command)
{ {
SpaProxy *this; SpaProxy *this;
SpaResult res = SPA_RESULT_OK;
if (node == NULL || command == NULL) if (node == NULL || command == NULL)
return SPA_RESULT_INVALID_ARGUMENTS; return SPA_RESULT_INVALID_ARGUMENTS;
this = SPA_CONTAINER_OF (node, SpaProxy, node); this = SPA_CONTAINER_OF (node, SpaProxy, node);
switch (SPA_NODE_COMMAND_TYPE (command)) { spa_log_warn (this->log, "unhandled command %d", SPA_COMMAND_TYPE (command));
case SPA_NODE_COMMAND_INVALID: return SPA_RESULT_NOT_IMPLEMENTED;
return SPA_RESULT_INVALID_COMMAND;
case SPA_NODE_COMMAND_START:
case SPA_NODE_COMMAND_PAUSE:
case SPA_NODE_COMMAND_FLUSH:
case SPA_NODE_COMMAND_DRAIN:
case SPA_NODE_COMMAND_MARKER:
break;
default:
spa_log_warn (this->log, "unhandled command %d", SPA_NODE_COMMAND_TYPE (command));
res = SPA_RESULT_NOT_IMPLEMENTED;
break;
}
return res;
} }
static SpaResult static SpaResult

View file

@ -21,6 +21,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <errno.h> #include <errno.h>
#include "spa/include/spa/node-command.h"
#include "pinos/client/pinos.h" #include "pinos/client/pinos.h"
#include "pinos/client/interfaces.h" #include "pinos/client/interfaces.h"
@ -167,7 +169,7 @@ pause_node (PinosNode *this)
pinos_log_debug ("node %p: pause node", this); pinos_log_debug ("node %p: pause node", this);
{ {
SpaNodeCommand cmd = SPA_NODE_COMMAND_INIT (SPA_NODE_COMMAND_PAUSE); SpaCommand cmd = SPA_COMMAND_INIT (this->core->uri.node_commands.Pause);
if ((res = spa_node_send_command (this->node, &cmd)) < 0) if ((res = spa_node_send_command (this->node, &cmd)) < 0)
pinos_log_debug ("got error %d", res); pinos_log_debug ("got error %d", res);
} }
@ -181,7 +183,7 @@ start_node (PinosNode *this)
pinos_log_debug ("node %p: start node", this); pinos_log_debug ("node %p: start node", this);
{ {
SpaNodeCommand cmd = SPA_NODE_COMMAND_INIT (SPA_NODE_COMMAND_START); SpaCommand cmd = SPA_COMMAND_INIT (this->core->uri.node_commands.Start);
if ((res = spa_node_send_command (this->node, &cmd)) < 0) if ((res = spa_node_send_command (this->node, &cmd)) < 0)
pinos_log_debug ("got error %d", res); pinos_log_debug ("got error %d", res);
} }
@ -224,6 +226,7 @@ send_clock_update (PinosNode *this)
SpaResult res; SpaResult res;
SpaNodeCommandClockUpdate cu = SpaNodeCommandClockUpdate cu =
SPA_NODE_COMMAND_CLOCK_UPDATE_INIT( SPA_NODE_COMMAND_CLOCK_UPDATE_INIT(
this->core->uri.node_commands.ClockUpdate,
SPA_NODE_COMMAND_CLOCK_UPDATE_TIME | SPA_NODE_COMMAND_CLOCK_UPDATE_TIME |
SPA_NODE_COMMAND_CLOCK_UPDATE_SCALE | SPA_NODE_COMMAND_CLOCK_UPDATE_SCALE |
SPA_NODE_COMMAND_CLOCK_UPDATE_STATE | SPA_NODE_COMMAND_CLOCK_UPDATE_STATE |
@ -245,7 +248,7 @@ send_clock_update (PinosNode *this)
&cu.body.monotonic_time.value); &cu.body.monotonic_time.value);
} }
if ((res = spa_node_send_command (this->node, (SpaNodeCommand *)&cu)) < 0) if ((res = spa_node_send_command (this->node, (SpaCommand *)&cu)) < 0)
pinos_log_debug ("got error %d", res); pinos_log_debug ("got error %d", res);
} }

View file

@ -29,6 +29,7 @@ extern "C" {
typedef struct _PinosNode PinosNode; typedef struct _PinosNode PinosNode;
#include <spa/include/spa/clock.h>
#include <spa/include/spa/node.h> #include <spa/include/spa/node.h>
#include <pinos/client/mem.h> #include <pinos/client/mem.h>

View file

@ -206,7 +206,7 @@ no_mem:
static SpaResult static SpaResult
pinos_port_pause (PinosPort *port) pinos_port_pause (PinosPort *port)
{ {
SpaNodeCommand cmd = SPA_NODE_COMMAND_INIT (SPA_NODE_COMMAND_PAUSE); SpaCommand cmd = SPA_COMMAND_INIT (port->node->core->uri.node_commands.Pause);
return spa_node_port_send_command (port->node->node, return spa_node_port_send_command (port->node->node,
port->direction, port->direction,
port->port_id, port->port_id,

View file

@ -742,9 +742,9 @@ client_node_marshal_use_buffers (void *object,
} }
static void static void
client_node_marshal_node_command (void *object, client_node_marshal_node_command (void *object,
uint32_t seq, uint32_t seq,
const SpaNodeCommand *command) const SpaCommand *command)
{ {
PinosResource *resource = object; PinosResource *resource = object;
PinosConnection *connection = resource->client->protocol_private; PinosConnection *connection = resource->client->protocol_private;
@ -761,9 +761,9 @@ client_node_marshal_node_command (void *object,
} }
static void static void
client_node_marshal_port_command (void *object, client_node_marshal_port_command (void *object,
uint32_t port_id, uint32_t port_id,
const SpaNodeCommand *command) const SpaCommand *command)
{ {
PinosResource *resource = object; PinosResource *resource = object;
PinosConnection *connection = resource->client->protocol_private; PinosConnection *connection = resource->client->protocol_private;

58
spa/include/spa/command.h Normal file
View file

@ -0,0 +1,58 @@
/* Simple Plugin API
* Copyright (C) 2016 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.
*/
#ifndef __SPA_COMMAND_H__
#define __SPA_COMMAND_H__
#ifdef __cplusplus
extern "C" {
#endif
typedef struct _SpaCommand SpaCommand;
#include <spa/defs.h>
#include <spa/pod.h>
#define SPA_COMMAND_URI "http://spaplug.in/ns/command"
#define SPA_COMMAND_PREFIX SPA_COMMAND_URI "#"
typedef struct {
SpaPODObjectBody body;
} SpaCommandBody;
struct _SpaCommand {
SpaPOD pod;
SpaCommandBody body;
};
#define SPA_COMMAND_TYPE(cmd) ((cmd)->body.body.type)
#define SPA_COMMAND_INIT(type) \
{ { sizeof (SpaCommandBody), SPA_POD_TYPE_OBJECT }, \
{ { 0, type } } } \
#define SPA_COMMAND_INIT_COMPLEX(size,type,...) \
{ { size, SPA_POD_TYPE_OBJECT }, \
{ { 0, type }, __VA_ARGS__ } } \
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* __SPA_COMMAND_H__ */

View file

@ -27,9 +27,10 @@ extern "C" {
typedef struct _SpaEvent SpaEvent; typedef struct _SpaEvent SpaEvent;
#include <spa/defs.h> #include <spa/defs.h>
#include <spa/pod-utils.h> #include <spa/pod.h>
#define SPA_EVENT_TYPE(ev) ((ev)->body.body.type) #define SPA_EVENT_URI "http://spaplug.in/ns/event"
#define SPA_EVENT_PREFIX SPA_EVENT_URI "#"
typedef struct { typedef struct {
SpaPODObjectBody body; SpaPODObjectBody body;
@ -40,6 +41,8 @@ struct _SpaEvent {
SpaEventBody body; SpaEventBody body;
}; };
#define SPA_EVENT_TYPE(ev) ((ev)->body.body.type)
#define SPA_EVENT_INIT(type) \ #define SPA_EVENT_INIT(type) \
{ { sizeof (SpaEventBody), SPA_POD_TYPE_OBJECT }, \ { { sizeof (SpaEventBody), SPA_POD_TYPE_OBJECT }, \
{ { 0, type } } } \ { { 0, type } } } \

View file

@ -32,21 +32,22 @@ extern "C" {
static inline uint32_t static inline uint32_t
spa_pod_builder_push_format (SpaPODBuilder *builder, spa_pod_builder_push_format (SpaPODBuilder *builder,
SpaPODFrame *frame, SpaPODFrame *frame,
uint32_t format_type,
uint32_t media_type, uint32_t media_type,
uint32_t media_subtype) uint32_t media_subtype)
{ {
const SpaFormat p = { { sizeof (SpaFormatBody), SPA_POD_TYPE_OBJECT }, const SpaFormat p = { { sizeof (SpaFormatBody), SPA_POD_TYPE_OBJECT },
{ { 0, 0 }, { { 0, format_type },
{ { sizeof (uint32_t), SPA_POD_TYPE_URI }, media_type }, { { sizeof (uint32_t), SPA_POD_TYPE_URI }, media_type },
{ { sizeof (uint32_t), SPA_POD_TYPE_URI }, media_subtype } } }; { { sizeof (uint32_t), SPA_POD_TYPE_URI }, media_subtype } } };
return spa_pod_builder_push (builder, frame, &p.pod, return spa_pod_builder_push (builder, frame, &p.pod,
spa_pod_builder_raw (builder, &p, sizeof(p))); spa_pod_builder_raw (builder, &p, sizeof(p)));
} }
#define spa_pod_builder_format(b,f,media_type,media_subtype,...) \ #define spa_pod_builder_format(b,f,format_type,media_type,media_subtype,...) \
spa_pod_builder_object(b, f, 0, 0, \ spa_pod_builder_object(b, f, 0, format_type, \
SPA_POD_TYPE_URI,media_type, \ SPA_POD_TYPE_URI,media_type, \
SPA_POD_TYPE_URI,media_subtype, \ SPA_POD_TYPE_URI,media_subtype, \
__VA_ARGS__) __VA_ARGS__)
SpaResult SpaResult

View file

@ -27,6 +27,7 @@ extern "C" {
#include <stdarg.h> #include <stdarg.h>
#include <spa/format.h> #include <spa/format.h>
#include <spa/pod-utils.h>
#include <spa/id-map.h> #include <spa/id-map.h>
typedef struct { typedef struct {

View file

@ -30,7 +30,7 @@ extern "C" {
typedef struct _SpaFormat SpaFormat; typedef struct _SpaFormat SpaFormat;
#include <spa/defs.h> #include <spa/defs.h>
#include <spa/pod-utils.h> #include <spa/pod.h>
#define SPA_MEDIA_TYPE_URI "http://spaplug.in/ns/media-type" #define SPA_MEDIA_TYPE_URI "http://spaplug.in/ns/media-type"
#define SPA_MEDIA_TYPE_PREFIX SPA_MEDIA_TYPE_URI "#" #define SPA_MEDIA_TYPE_PREFIX SPA_MEDIA_TYPE_URI "#"

View file

@ -2,6 +2,7 @@ spa_headers = [
'barrier.h', 'barrier.h',
'buffer.h', 'buffer.h',
'clock.h', 'clock.h',
'command.h',
'defs.h', 'defs.h',
'dict.h', 'dict.h',
'event.h', 'event.h',

View file

@ -24,10 +24,8 @@
extern "C" { extern "C" {
#endif #endif
typedef struct _SpaNodeCommand SpaNodeCommand; #include <spa/id-map.h>
#include <spa/command.h>
#include <spa/defs.h>
#include <spa/clock.h>
#define SPA_NODE_COMMAND_URI "http://spaplug.in/ns/node-command" #define SPA_NODE_COMMAND_URI "http://spaplug.in/ns/node-command"
#define SPA_NODE_COMMAND_PREFIX SPA_NODE_COMMAND_URI "#" #define SPA_NODE_COMMAND_PREFIX SPA_NODE_COMMAND_URI "#"
@ -39,34 +37,27 @@ typedef struct _SpaNodeCommand SpaNodeCommand;
#define SPA_NODE_COMMAND__Marker SPA_NODE_COMMAND_PREFIX "Marker" #define SPA_NODE_COMMAND__Marker SPA_NODE_COMMAND_PREFIX "Marker"
#define SPA_NODE_COMMAND__ClockUpdate SPA_NODE_COMMAND_PREFIX "ClockUpdate" #define SPA_NODE_COMMAND__ClockUpdate SPA_NODE_COMMAND_PREFIX "ClockUpdate"
typedef enum {
SPA_NODE_COMMAND_INVALID = 0,
SPA_NODE_COMMAND_PAUSE,
SPA_NODE_COMMAND_START,
SPA_NODE_COMMAND_FLUSH,
SPA_NODE_COMMAND_DRAIN,
SPA_NODE_COMMAND_MARKER,
SPA_NODE_COMMAND_CLOCK_UPDATE
} SpaNodeCommandType;
#define SPA_NODE_COMMAND_TYPE(cmd) ((cmd)->body.body.type)
typedef struct { typedef struct {
SpaPODObjectBody body; uint32_t Pause;
} SpaNodeCommandBody; uint32_t Start;
uint32_t Flush;
uint32_t Drain;
uint32_t Marker;
uint32_t ClockUpdate;
} SpaNodeCommands;
struct _SpaNodeCommand { static inline void
SpaPOD pod; spa_node_commands_map (SpaIDMap *map, SpaNodeCommands *types)
SpaNodeCommandBody body; {
}; if (types->Pause == 0) {
types->Pause = spa_id_map_get_id (map, SPA_NODE_COMMAND__Pause);
#define SPA_NODE_COMMAND_INIT(type) \ types->Start = spa_id_map_get_id (map, SPA_NODE_COMMAND__Start);
{ { sizeof (SpaNodeCommandBody), SPA_POD_TYPE_OBJECT }, \ types->Flush = spa_id_map_get_id (map, SPA_NODE_COMMAND__Flush);
{ { 0, type } } } \ types->Drain = spa_id_map_get_id (map, SPA_NODE_COMMAND__Drain);
types->Marker = spa_id_map_get_id (map, SPA_NODE_COMMAND__Marker);
#define SPA_NODE_COMMAND_INIT_COMPLEX(size,type,...) \ types->ClockUpdate = spa_id_map_get_id (map, SPA_NODE_COMMAND__ClockUpdate);
{ { size, SPA_POD_TYPE_OBJECT }, \ }
{ { 0, type }, __VA_ARGS__ } } \ }
/** /**
* SpaNodeCommandClockUpdate: * SpaNodeCommandClockUpdate:
@ -103,18 +94,17 @@ typedef struct {
SpaNodeCommandClockUpdateBody body; SpaNodeCommandClockUpdateBody body;
} SpaNodeCommandClockUpdate; } SpaNodeCommandClockUpdate;
#define SPA_NODE_COMMAND_CLOCK_UPDATE_INIT(change_mask,rate,ticks,monotonic_time,offset,scale,state,flags,latency) \ #define SPA_NODE_COMMAND_CLOCK_UPDATE_INIT(type,change_mask,rate,ticks,monotonic_time,offset,scale,state,flags,latency) \
SPA_NODE_COMMAND_INIT_COMPLEX (sizeof (SpaNodeCommandClockUpdateBody), \ SPA_COMMAND_INIT_COMPLEX (sizeof (SpaNodeCommandClockUpdateBody), type, \
SPA_NODE_COMMAND_CLOCK_UPDATE, \ SPA_POD_INT_INIT (change_mask), \
SPA_POD_INT_INIT (change_mask), \ SPA_POD_INT_INIT (rate), \
SPA_POD_INT_INIT (rate), \ SPA_POD_LONG_INIT (ticks), \
SPA_POD_LONG_INIT (ticks), \ SPA_POD_LONG_INIT (monotonic_time), \
SPA_POD_LONG_INIT (monotonic_time), \ SPA_POD_LONG_INIT (offset), \
SPA_POD_LONG_INIT (offset), \ SPA_POD_INT_INIT (scale), \
SPA_POD_INT_INIT (scale), \ SPA_POD_INT_INIT (state), \
SPA_POD_INT_INIT (state), \ SPA_POD_INT_INIT (flags), \
SPA_POD_INT_INIT (flags), \ SPA_POD_LONG_INIT (latency))
SPA_POD_LONG_INIT (latency))
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */

View file

@ -202,7 +202,7 @@ struct _SpaNode {
/** /**
* SpaNode::send_command: * SpaNode::send_command:
* @node: a #SpaNode * @node: a #SpaNode
* @command: a #SpaNodeCommand * @command: a #SpaCommand
* *
* Send a command to @node. * Send a command to @node.
* *
@ -216,8 +216,8 @@ struct _SpaNode {
* #SPA_RESULT_INVALID_COMMAND @command is an invalid command * #SPA_RESULT_INVALID_COMMAND @command is an invalid command
* #SPA_RESULT_ASYNC @command is executed asynchronously * #SPA_RESULT_ASYNC @command is executed asynchronously
*/ */
SpaResult (*send_command) (SpaNode *node, SpaResult (*send_command) (SpaNode *node,
SpaNodeCommand *command); SpaCommand *command);
/** /**
* SpaNode::set_event_callback: * SpaNode::set_event_callback:
* @node: a #SpaNode * @node: a #SpaNode
@ -542,7 +542,7 @@ struct _SpaNode {
SpaResult (*port_send_command) (SpaNode *node, SpaResult (*port_send_command) (SpaNode *node,
SpaDirection direction, SpaDirection direction,
uint32_t port_id, uint32_t port_id,
SpaNodeCommand *command); SpaCommand *command);
/** /**
* SpaNode::process_input: * SpaNode::process_input:
* @node: a #SpaNode * @node: a #SpaNode

View file

@ -269,7 +269,8 @@ print_pod_value (uint32_t size, uint32_t type, void *body, int prefix)
SpaPODObjectBody *b = body; SpaPODObjectBody *b = body;
SpaPOD *p; SpaPOD *p;
printf ("%-*sObject: size %d, id %d, type %d\n", prefix, "", size, b->id, b->type); printf ("%-*sObject: size %d, id %d, type %s\n", prefix, "", size, b->id,
spa_id_map_get_uri (spa_id_map_get_default(), b->type));
SPA_POD_OBJECT_BODY_FOREACH (b, size, p) SPA_POD_OBJECT_BODY_FOREACH (b, size, p)
print_pod_value (p->size, p->type, SPA_POD_BODY (p), prefix + 2); print_pod_value (p->size, p->type, SPA_POD_BODY (p), prefix + 2);
break; break;

View file

@ -45,7 +45,6 @@ id_map_get_id (SpaIDMap *map, const char *uri)
if (strcmp (this->uris[i], uri) == 0) if (strcmp (this->uris[i], uri) == 0)
return i; return i;
} }
printf ("spa adding %d %s\n", i, uri);
this->uris[i] = (char *)uri; this->uris[i] = (char *)uri;
this->n_uris++; this->n_uris++;
} }
@ -57,8 +56,6 @@ id_map_get_uri (SpaIDMap *map, uint32_t id)
{ {
IDMap *this = SPA_CONTAINER_OF (map, IDMap, map); IDMap *this = SPA_CONTAINER_OF (map, IDMap, map);
printf ("spa get %d\n", id);
if (id < this->n_uris) if (id < this->n_uris)
return this->uris[id]; return this->uris[id];

View file

@ -102,7 +102,7 @@ spa_format_filter (const SpaFormat *format,
filter->body.media_subtype.value != format->body.media_subtype.value) filter->body.media_subtype.value != format->body.media_subtype.value)
return SPA_RESULT_INVALID_MEDIA_TYPE; return SPA_RESULT_INVALID_MEDIA_TYPE;
spa_pod_builder_push_format (result, &f, spa_pod_builder_push_format (result, &f, filter->body.obj_body.type,
filter->body.media_type.value, filter->body.media_type.value,
filter->body.media_subtype.value); filter->body.media_subtype.value);
res = spa_props_filter (result, res = spa_props_filter (result,

View file

@ -155,20 +155,17 @@ do_command (SpaLoop *loop,
{ {
SpaALSASink *this = user_data; SpaALSASink *this = user_data;
SpaResult res; SpaResult res;
SpaNodeCommand *cmd = data; SpaCommand *cmd = data;
switch (SPA_NODE_COMMAND_TYPE (cmd)) { if (SPA_COMMAND_TYPE (cmd) == this->uri.node_commands.Start ||
case SPA_NODE_COMMAND_START: SPA_COMMAND_TYPE (cmd) == this->uri.node_commands.Pause) {
case SPA_NODE_COMMAND_PAUSE: res = spa_node_port_send_command (&this->node,
res = spa_node_port_send_command (&this->node, SPA_DIRECTION_INPUT,
SPA_DIRECTION_INPUT, 0,
0, cmd);
cmd);
break;
default:
res = SPA_RESULT_NOT_IMPLEMENTED;
break;
} }
else
res = SPA_RESULT_NOT_IMPLEMENTED;
if (async) { if (async) {
SpaNodeEventAsyncComplete ac = SPA_NODE_EVENT_ASYNC_COMPLETE_INIT (this->uri.node_events.AsyncComplete, SpaNodeEventAsyncComplete ac = SPA_NODE_EVENT_ASYNC_COMPLETE_INIT (this->uri.node_events.AsyncComplete,
@ -184,8 +181,8 @@ do_command (SpaLoop *loop,
} }
static SpaResult static SpaResult
spa_alsa_sink_node_send_command (SpaNode *node, spa_alsa_sink_node_send_command (SpaNode *node,
SpaNodeCommand *command) SpaCommand *command)
{ {
SpaALSASink *this; SpaALSASink *this;
@ -194,34 +191,24 @@ spa_alsa_sink_node_send_command (SpaNode *node,
this = SPA_CONTAINER_OF (node, SpaALSASink, node); this = SPA_CONTAINER_OF (node, SpaALSASink, node);
switch (SPA_NODE_COMMAND_TYPE (command)) { if (SPA_COMMAND_TYPE (command) == this->uri.node_commands.Start ||
case SPA_NODE_COMMAND_INVALID: SPA_COMMAND_TYPE (command) == this->uri.node_commands.Pause) {
return SPA_RESULT_INVALID_COMMAND; if (!this->have_format)
return SPA_RESULT_NO_FORMAT;
case SPA_NODE_COMMAND_START: if (this->n_buffers == 0)
case SPA_NODE_COMMAND_PAUSE: return SPA_RESULT_NO_BUFFERS;
{
if (!this->have_format)
return SPA_RESULT_NO_FORMAT;
if (this->n_buffers == 0) return spa_loop_invoke (this->data_loop,
return SPA_RESULT_NO_BUFFERS; do_command,
++this->seq,
SPA_POD_SIZE (command),
command,
this);
return spa_loop_invoke (this->data_loop,
do_command,
++this->seq,
SPA_POD_SIZE (command),
command,
this);
}
case SPA_NODE_COMMAND_FLUSH:
case SPA_NODE_COMMAND_DRAIN:
case SPA_NODE_COMMAND_MARKER:
case SPA_NODE_COMMAND_CLOCK_UPDATE:
return SPA_RESULT_NOT_IMPLEMENTED;
} }
return SPA_RESULT_OK; else
return SPA_RESULT_NOT_IMPLEMENTED;
} }
static SpaResult static SpaResult
@ -325,18 +312,18 @@ next:
switch (index++) { switch (index++) {
case 0: case 0:
spa_pod_builder_format (&b, &f[0], spa_pod_builder_format (&b, &f[0], this->uri.format,
this->uri.media_types.audio, this->uri.media_subtypes.raw, this->uri.media_types.audio, this->uri.media_subtypes.raw,
PROP_U_EN (&f[1], this->uri.prop_audio.format, SPA_POD_TYPE_URI, 3, this->uri.audio_formats.S16, PROP_U_EN (&f[1], this->uri.prop_audio.format, SPA_POD_TYPE_URI, 3, this->uri.audio_formats.S16,
this->uri.audio_formats.S16, this->uri.audio_formats.S16,
this->uri.audio_formats.S32), this->uri.audio_formats.S32),
PROP_U_MM (&f[1], this->uri.prop_audio.rate, SPA_POD_TYPE_INT, 44100, 1, INT32_MAX), PROP_U_MM (&f[1], this->uri.prop_audio.rate, SPA_POD_TYPE_INT, 44100, 1, INT32_MAX),
PROP_U_MM (&f[1], this->uri.prop_audio.channels, SPA_POD_TYPE_INT, 2, 1, INT32_MAX)); PROP_U_MM (&f[1], this->uri.prop_audio.channels, SPA_POD_TYPE_INT, 2, 1, INT32_MAX));
break; break;
case 1: case 1:
spa_pod_builder_format (&b, &f[0], spa_pod_builder_format (&b, &f[0], this->uri.format,
this->uri.media_types.audio, this->uri.media_subtypes_audio.aac, this->uri.media_types.audio, this->uri.media_subtypes_audio.aac,
SPA_POD_TYPE_NONE); SPA_POD_TYPE_NONE);
break; break;
default: default:
return SPA_RESULT_ENUM_END; return SPA_RESULT_ENUM_END;
@ -622,7 +609,7 @@ static SpaResult
spa_alsa_sink_node_port_send_command (SpaNode *node, spa_alsa_sink_node_port_send_command (SpaNode *node,
SpaDirection direction, SpaDirection direction,
uint32_t port_id, uint32_t port_id,
SpaNodeCommand *command) SpaCommand *command)
{ {
SpaALSASink *this; SpaALSASink *this;
SpaResult res; SpaResult res;
@ -635,25 +622,19 @@ spa_alsa_sink_node_port_send_command (SpaNode *node,
if (port_id != 0) if (port_id != 0)
return SPA_RESULT_INVALID_PORT; return SPA_RESULT_INVALID_PORT;
switch (SPA_NODE_COMMAND_TYPE (command)) { if (SPA_COMMAND_TYPE (command) == this->uri.node_commands.Pause) {
case SPA_NODE_COMMAND_PAUSE: if (SPA_RESULT_IS_OK (res = spa_alsa_pause (this, false))) {
{ update_state (this, SPA_NODE_STATE_PAUSED);
if (SPA_RESULT_IS_OK (res = spa_alsa_pause (this, false))) {
update_state (this, SPA_NODE_STATE_PAUSED);
}
break;
} }
case SPA_NODE_COMMAND_START:
{
if (SPA_RESULT_IS_OK (res = spa_alsa_start (this, false))) {
update_state (this, SPA_NODE_STATE_STREAMING);
}
break;
}
default:
res = SPA_RESULT_NOT_IMPLEMENTED;
break;
} }
else if (SPA_COMMAND_TYPE (command) == this->uri.node_commands.Start) {
if (SPA_RESULT_IS_OK (res = spa_alsa_start (this, false))) {
update_state (this, SPA_NODE_STATE_STREAMING);
}
}
else
res = SPA_RESULT_NOT_IMPLEMENTED;
return res; return res;
} }
@ -796,12 +777,15 @@ alsa_sink_init (const SpaHandleFactory *factory,
return SPA_RESULT_ERROR; return SPA_RESULT_ERROR;
} }
this->uri.node = spa_id_map_get_id (this->map, SPA_NODE_URI); this->uri.node = spa_id_map_get_id (this->map, SPA_NODE_URI);
this->uri.clock = spa_id_map_get_id (this->map, SPA_CLOCK_URI);
this->uri.format = spa_id_map_get_id (this->map, SPA_FORMAT_URI);
spa_media_types_fill (&this->uri.media_types, this->map); spa_media_types_fill (&this->uri.media_types, this->map);
spa_media_subtypes_map (this->map, &this->uri.media_subtypes); spa_media_subtypes_map (this->map, &this->uri.media_subtypes);
spa_media_subtypes_audio_map (this->map, &this->uri.media_subtypes_audio); spa_media_subtypes_audio_map (this->map, &this->uri.media_subtypes_audio);
spa_prop_audio_map (this->map, &this->uri.prop_audio); spa_prop_audio_map (this->map, &this->uri.prop_audio);
spa_audio_formats_map (this->map, &this->uri.audio_formats); spa_audio_formats_map (this->map, &this->uri.audio_formats);
spa_node_events_map (this->map, &this->uri.node_events); spa_node_events_map (this->map, &this->uri.node_events);
spa_node_commands_map (this->map, &this->uri.node_commands);
this->node = alsasink_node; this->node = alsasink_node;
this->stream = SND_PCM_STREAM_PLAYBACK; this->stream = SND_PCM_STREAM_PLAYBACK;

View file

@ -205,8 +205,8 @@ do_pause (SpaLoop *loop,
} }
static SpaResult static SpaResult
spa_alsa_source_node_send_command (SpaNode *node, spa_alsa_source_node_send_command (SpaNode *node,
SpaNodeCommand *command) SpaCommand *command)
{ {
SpaALSASource *this; SpaALSASource *this;
@ -215,47 +215,37 @@ spa_alsa_source_node_send_command (SpaNode *node,
this = SPA_CONTAINER_OF (node, SpaALSASource, node); this = SPA_CONTAINER_OF (node, SpaALSASource, node);
switch (SPA_NODE_COMMAND_TYPE (command)) { if (SPA_COMMAND_TYPE (command) == this->uri.node_commands.Start) {
case SPA_NODE_COMMAND_INVALID: if (!this->have_format)
return SPA_RESULT_INVALID_COMMAND; return SPA_RESULT_NO_FORMAT;
case SPA_NODE_COMMAND_START: if (this->n_buffers == 0)
{ return SPA_RESULT_NO_BUFFERS;
if (!this->have_format)
return SPA_RESULT_NO_FORMAT;
if (this->n_buffers == 0) return spa_loop_invoke (this->data_loop,
return SPA_RESULT_NO_BUFFERS; do_start,
++this->seq,
return spa_loop_invoke (this->data_loop, 0,
do_start, NULL,
++this->seq, this);
0,
NULL,
this);
}
case SPA_NODE_COMMAND_PAUSE:
{
if (!this->have_format)
return SPA_RESULT_NO_FORMAT;
if (this->n_buffers == 0)
return SPA_RESULT_NO_BUFFERS;
return spa_loop_invoke (this->data_loop,
do_pause,
++this->seq,
0,
NULL,
this);
}
case SPA_NODE_COMMAND_FLUSH:
case SPA_NODE_COMMAND_DRAIN:
case SPA_NODE_COMMAND_MARKER:
case SPA_NODE_COMMAND_CLOCK_UPDATE:
return SPA_RESULT_NOT_IMPLEMENTED;
} }
else if (SPA_COMMAND_TYPE (command) == this->uri.node_commands.Pause) {
if (!this->have_format)
return SPA_RESULT_NO_FORMAT;
if (this->n_buffers == 0)
return SPA_RESULT_NO_BUFFERS;
return spa_loop_invoke (this->data_loop,
do_pause,
++this->seq,
0,
NULL,
this);
}
else
return SPA_RESULT_NOT_IMPLEMENTED;
return SPA_RESULT_OK; return SPA_RESULT_OK;
} }
@ -360,18 +350,18 @@ next:
switch (index++) { switch (index++) {
case 0: case 0:
spa_pod_builder_format (&b, &f[0], spa_pod_builder_format (&b, &f[0], this->uri.format,
this->uri.media_types.audio, this->uri.media_subtypes.raw, this->uri.media_types.audio, this->uri.media_subtypes.raw,
PROP_U_EN (&f[1], this->uri.prop_audio.format, SPA_POD_TYPE_URI, 3, this->uri.audio_formats.S16, PROP_U_EN (&f[1], this->uri.prop_audio.format, SPA_POD_TYPE_URI, 3, this->uri.audio_formats.S16,
this->uri.audio_formats.S16, this->uri.audio_formats.S16,
this->uri.audio_formats.S32), this->uri.audio_formats.S32),
PROP_U_MM (&f[1], this->uri.prop_audio.rate, SPA_POD_TYPE_INT, 44100, 1, INT32_MAX), PROP_U_MM (&f[1], this->uri.prop_audio.rate, SPA_POD_TYPE_INT, 44100, 1, INT32_MAX),
PROP_U_MM (&f[1], this->uri.prop_audio.channels, SPA_POD_TYPE_INT, 2, 1, INT32_MAX)); PROP_U_MM (&f[1], this->uri.prop_audio.channels, SPA_POD_TYPE_INT, 2, 1, INT32_MAX));
break; break;
case 1: case 1:
spa_pod_builder_format (&b, &f[0], spa_pod_builder_format (&b, &f[0], this->uri.format,
this->uri.media_types.audio, this->uri.media_subtypes_audio.aac, this->uri.media_types.audio, this->uri.media_subtypes_audio.aac,
SPA_POD_TYPE_NONE); SPA_POD_TYPE_NONE);
default: default:
return SPA_RESULT_ENUM_END; return SPA_RESULT_ENUM_END;
} }
@ -679,7 +669,7 @@ static SpaResult
spa_alsa_source_node_port_send_command (SpaNode *node, spa_alsa_source_node_port_send_command (SpaNode *node,
SpaDirection direction, SpaDirection direction,
uint32_t port_id, uint32_t port_id,
SpaNodeCommand *command) SpaCommand *command)
{ {
SpaALSASource *this; SpaALSASource *this;
SpaResult res; SpaResult res;
@ -692,25 +682,17 @@ spa_alsa_source_node_port_send_command (SpaNode *node,
if (port_id != 0) if (port_id != 0)
return SPA_RESULT_INVALID_PORT; return SPA_RESULT_INVALID_PORT;
switch (SPA_NODE_COMMAND_TYPE (command)) { if (SPA_COMMAND_TYPE (command) == this->uri.node_commands.Pause) {
case SPA_NODE_COMMAND_PAUSE: if (SPA_RESULT_IS_OK (res = spa_alsa_pause (this, false))) {
{ update_state (this, SPA_NODE_STATE_PAUSED);
if (SPA_RESULT_IS_OK (res = spa_alsa_pause (this, false))) {
update_state (this, SPA_NODE_STATE_PAUSED);
}
break;
} }
case SPA_NODE_COMMAND_START: } else if (SPA_COMMAND_TYPE (command) == this->uri.node_commands.Start) {
{ if (SPA_RESULT_IS_OK (res = spa_alsa_start (this, false))) {
if (SPA_RESULT_IS_OK (res = spa_alsa_start (this, false))) { update_state (this, SPA_NODE_STATE_STREAMING);
update_state (this, SPA_NODE_STATE_STREAMING);
}
break;
} }
default: } else
res = SPA_RESULT_NOT_IMPLEMENTED; res = SPA_RESULT_NOT_IMPLEMENTED;
break;
}
return res; return res;
} }
@ -862,6 +844,7 @@ alsa_source_init (const SpaHandleFactory *factory,
} }
this->uri.node = spa_id_map_get_id (this->map, SPA_NODE_URI); this->uri.node = spa_id_map_get_id (this->map, SPA_NODE_URI);
this->uri.clock = spa_id_map_get_id (this->map, SPA_CLOCK_URI); this->uri.clock = spa_id_map_get_id (this->map, SPA_CLOCK_URI);
this->uri.format = spa_id_map_get_id (this->map, SPA_FORMAT_URI);
spa_media_types_fill (&this->uri.media_types, this->map); spa_media_types_fill (&this->uri.media_types, this->map);
spa_media_subtypes_map (this->map, &this->uri.media_subtypes); spa_media_subtypes_map (this->map, &this->uri.media_subtypes);
@ -869,6 +852,7 @@ alsa_source_init (const SpaHandleFactory *factory,
spa_prop_audio_map (this->map, &this->uri.prop_audio); spa_prop_audio_map (this->map, &this->uri.prop_audio);
spa_audio_formats_map (this->map, &this->uri.audio_formats); spa_audio_formats_map (this->map, &this->uri.audio_formats);
spa_node_events_map (this->map, &this->uri.node_events); spa_node_events_map (this->map, &this->uri.node_events);
spa_node_commands_map (this->map, &this->uri.node_commands);
this->node = alsasource_node; this->node = alsasource_node;
this->clock = alsasource_clock; this->clock = alsasource_clock;

View file

@ -29,6 +29,7 @@ extern "C" {
#include <asoundlib.h> #include <asoundlib.h>
#include <spa/id-map.h> #include <spa/id-map.h>
#include <spa/clock.h>
#include <spa/log.h> #include <spa/log.h>
#include <spa/list.h> #include <spa/list.h>
#include <spa/node.h> #include <spa/node.h>
@ -62,12 +63,14 @@ struct _SpaALSABuffer {
typedef struct { typedef struct {
uint32_t node; uint32_t node;
uint32_t clock; uint32_t clock;
uint32_t format;
SpaMediaTypes media_types; SpaMediaTypes media_types;
SpaMediaSubtypes media_subtypes; SpaMediaSubtypes media_subtypes;
SpaMediaSubtypesAudio media_subtypes_audio; SpaMediaSubtypesAudio media_subtypes_audio;
SpaPropAudio prop_audio; SpaPropAudio prop_audio;
SpaAudioFormats audio_formats; SpaAudioFormats audio_formats;
SpaNodeEvents node_events; SpaNodeEvents node_events;
SpaNodeCommands node_commands;
} URI; } URI;
struct _SpaALSAState { struct _SpaALSAState {

View file

@ -58,6 +58,7 @@ typedef struct {
typedef struct { typedef struct {
uint32_t node; uint32_t node;
SpaNodeCommands node_commands;
} URI; } URI;
struct _SpaAudioMixer { struct _SpaAudioMixer {
@ -107,8 +108,8 @@ update_state (SpaAudioMixer *this, SpaNodeState state)
} }
static SpaResult static SpaResult
spa_audiomixer_node_send_command (SpaNode *node, spa_audiomixer_node_send_command (SpaNode *node,
SpaNodeCommand *command) SpaCommand *command)
{ {
SpaAudioMixer *this; SpaAudioMixer *this;
@ -117,24 +118,15 @@ spa_audiomixer_node_send_command (SpaNode *node,
this = SPA_CONTAINER_OF (node, SpaAudioMixer, node); this = SPA_CONTAINER_OF (node, SpaAudioMixer, node);
switch (SPA_NODE_COMMAND_TYPE (command)) { if (SPA_COMMAND_TYPE (command) == this->uri.node_commands.Start) {
case SPA_NODE_COMMAND_INVALID: update_state (this, SPA_NODE_STATE_STREAMING);
return SPA_RESULT_INVALID_COMMAND;
case SPA_NODE_COMMAND_START:
update_state (this, SPA_NODE_STATE_STREAMING);
break;
case SPA_NODE_COMMAND_PAUSE:
update_state (this, SPA_NODE_STATE_PAUSED);
break;
case SPA_NODE_COMMAND_FLUSH:
case SPA_NODE_COMMAND_DRAIN:
case SPA_NODE_COMMAND_MARKER:
case SPA_NODE_COMMAND_CLOCK_UPDATE:
return SPA_RESULT_NOT_IMPLEMENTED;
} }
else if (SPA_COMMAND_TYPE (command) == this->uri.node_commands.Pause) {
update_state (this, SPA_NODE_STATE_PAUSED);
}
else
return SPA_RESULT_NOT_IMPLEMENTED;
return SPA_RESULT_OK; return SPA_RESULT_OK;
} }
@ -463,7 +455,7 @@ static SpaResult
spa_audiomixer_node_port_send_command (SpaNode *node, spa_audiomixer_node_port_send_command (SpaNode *node,
SpaDirection direction, SpaDirection direction,
uint32_t port_id, uint32_t port_id,
SpaNodeCommand *command) SpaCommand *command)
{ {
return SPA_RESULT_NOT_IMPLEMENTED; return SPA_RESULT_NOT_IMPLEMENTED;
} }
@ -703,6 +695,7 @@ spa_audiomixer_init (const SpaHandleFactory *factory,
return SPA_RESULT_ERROR; return SPA_RESULT_ERROR;
} }
this->uri.node = spa_id_map_get_id (this->map, SPA_NODE_URI); this->uri.node = spa_id_map_get_id (this->map, SPA_NODE_URI);
spa_node_commands_map (this->map, &this->uri.node_commands);
this->node = audiomixer_node; this->node = audiomixer_node;

View file

@ -24,6 +24,7 @@
#include <sys/timerfd.h> #include <sys/timerfd.h>
#include <spa/id-map.h> #include <spa/id-map.h>
#include <spa/clock.h>
#include <spa/log.h> #include <spa/log.h>
#include <spa/loop.h> #include <spa/loop.h>
#include <spa/node.h> #include <spa/node.h>
@ -39,11 +40,13 @@
typedef struct { typedef struct {
uint32_t node; uint32_t node;
uint32_t clock; uint32_t clock;
uint32_t format;
SpaMediaTypes media_types; SpaMediaTypes media_types;
SpaMediaSubtypes media_subtypes; SpaMediaSubtypes media_subtypes;
SpaPropAudio prop_audio; SpaPropAudio prop_audio;
SpaAudioFormats audio_formats; SpaAudioFormats audio_formats;
SpaNodeEvents node_events; SpaNodeEvents node_events;
SpaNodeCommands node_commands;
} URI; } URI;
typedef struct _SpaAudioTestSrc SpaAudioTestSrc; typedef struct _SpaAudioTestSrc SpaAudioTestSrc;
@ -300,8 +303,8 @@ update_state (SpaAudioTestSrc *this, SpaNodeState state)
} }
static SpaResult static SpaResult
spa_audiotestsrc_node_send_command (SpaNode *node, spa_audiotestsrc_node_send_command (SpaNode *node,
SpaNodeCommand *command) SpaCommand *command)
{ {
SpaAudioTestSrc *this; SpaAudioTestSrc *this;
@ -310,58 +313,47 @@ spa_audiotestsrc_node_send_command (SpaNode *node,
this = SPA_CONTAINER_OF (node, SpaAudioTestSrc, node); this = SPA_CONTAINER_OF (node, SpaAudioTestSrc, node);
switch (SPA_NODE_COMMAND_TYPE (command)) { if (SPA_COMMAND_TYPE (command) == this->uri.node_commands.Start) {
case SPA_NODE_COMMAND_INVALID: struct timespec now;
return SPA_RESULT_INVALID_COMMAND;
case SPA_NODE_COMMAND_START: if (!this->have_format)
{ return SPA_RESULT_NO_FORMAT;
struct timespec now;
if (!this->have_format) if (this->n_buffers == 0)
return SPA_RESULT_NO_FORMAT; return SPA_RESULT_NO_BUFFERS;
if (this->n_buffers == 0) if (this->started)
return SPA_RESULT_NO_BUFFERS; return SPA_RESULT_OK;
if (this->started) clock_gettime (CLOCK_MONOTONIC, &now);
return SPA_RESULT_OK; if (this->props.live)
this->start_time = SPA_TIMESPEC_TO_TIME (&now);
else
this->start_time = 0;
this->sample_count = 0;
this->elapsed_time = 0;
clock_gettime (CLOCK_MONOTONIC, &now); this->started = true;
if (this->props.live) set_timer (this, true);
this->start_time = SPA_TIMESPEC_TO_TIME (&now); update_state (this, SPA_NODE_STATE_STREAMING);
else
this->start_time = 0;
this->sample_count = 0;
this->elapsed_time = 0;
this->started = true;
set_timer (this, true);
update_state (this, SPA_NODE_STATE_STREAMING);
break;
}
case SPA_NODE_COMMAND_PAUSE:
{
if (!this->have_format)
return SPA_RESULT_NO_FORMAT;
if (this->n_buffers == 0)
return SPA_RESULT_NO_BUFFERS;
if (!this->started)
return SPA_RESULT_OK;
this->started = false;
set_timer (this, false);
update_state (this, SPA_NODE_STATE_PAUSED);
break;
}
case SPA_NODE_COMMAND_FLUSH:
case SPA_NODE_COMMAND_DRAIN:
case SPA_NODE_COMMAND_MARKER:
case SPA_NODE_COMMAND_CLOCK_UPDATE:
return SPA_RESULT_NOT_IMPLEMENTED;
} }
else if (SPA_COMMAND_TYPE (command) == this->uri.node_commands.Pause) {
if (!this->have_format)
return SPA_RESULT_NO_FORMAT;
if (this->n_buffers == 0)
return SPA_RESULT_NO_BUFFERS;
if (!this->started)
return SPA_RESULT_OK;
this->started = false;
set_timer (this, false);
update_state (this, SPA_NODE_STATE_PAUSED);
}
else
return SPA_RESULT_NOT_IMPLEMENTED;
return SPA_RESULT_OK; return SPA_RESULT_OK;
} }
@ -471,13 +463,13 @@ next:
switch (index++) { switch (index++) {
case 0: case 0:
spa_pod_builder_format (&b, &f[0], spa_pod_builder_format (&b, &f[0], this->uri.format,
this->uri.media_types.audio, this->uri.media_subtypes.raw, this->uri.media_types.audio, this->uri.media_subtypes.raw,
PROP_U_EN (&f[1], this->uri.prop_audio.format, SPA_POD_TYPE_URI, 3, this->uri.audio_formats.S16, PROP_U_EN (&f[1], this->uri.prop_audio.format, SPA_POD_TYPE_URI, 3, this->uri.audio_formats.S16,
this->uri.audio_formats.S16, this->uri.audio_formats.S16,
this->uri.audio_formats.S32), this->uri.audio_formats.S32),
PROP_U_MM (&f[1], this->uri.prop_audio.rate, SPA_POD_TYPE_INT, 44100, 1, INT32_MAX), PROP_U_MM (&f[1], this->uri.prop_audio.rate, SPA_POD_TYPE_INT, 44100, 1, INT32_MAX),
PROP_U_MM (&f[1], this->uri.prop_audio.channels, SPA_POD_TYPE_INT, 2, 1, INT32_MAX)); PROP_U_MM (&f[1], this->uri.prop_audio.channels, SPA_POD_TYPE_INT, 2, 1, INT32_MAX));
break; break;
default: default:
return SPA_RESULT_ENUM_END; return SPA_RESULT_ENUM_END;
@ -589,7 +581,7 @@ spa_audiotestsrc_node_port_get_format (SpaNode *node,
return SPA_RESULT_NO_FORMAT; return SPA_RESULT_NO_FORMAT;
spa_pod_builder_init (&b, this->format_buffer, sizeof (this->format_buffer)); spa_pod_builder_init (&b, this->format_buffer, sizeof (this->format_buffer));
spa_pod_builder_format (&b, &f[0], spa_pod_builder_format (&b, &f[0], this->uri.format,
this->uri.media_types.audio, this->uri.media_subtypes.raw, this->uri.media_types.audio, this->uri.media_subtypes.raw,
PROP (&f[1], this->uri.prop_audio.format, SPA_POD_TYPE_URI, this->current_format.info.raw.format), PROP (&f[1], this->uri.prop_audio.format, SPA_POD_TYPE_URI, this->current_format.info.raw.format),
PROP (&f[1], this->uri.prop_audio.rate, SPA_POD_TYPE_INT, this->current_format.info.raw.rate), PROP (&f[1], this->uri.prop_audio.rate, SPA_POD_TYPE_INT, this->current_format.info.raw.rate),
@ -790,7 +782,7 @@ static SpaResult
spa_audiotestsrc_node_port_send_command (SpaNode *node, spa_audiotestsrc_node_port_send_command (SpaNode *node,
SpaDirection direction, SpaDirection direction,
uint32_t port_id, uint32_t port_id,
SpaNodeCommand *command) SpaCommand *command)
{ {
return SPA_RESULT_NOT_IMPLEMENTED; return SPA_RESULT_NOT_IMPLEMENTED;
} }
@ -957,11 +949,13 @@ audiotestsrc_init (const SpaHandleFactory *factory,
} }
this->uri.node = spa_id_map_get_id (this->map, SPA_NODE_URI); this->uri.node = spa_id_map_get_id (this->map, SPA_NODE_URI);
this->uri.clock = spa_id_map_get_id (this->map, SPA_CLOCK_URI); this->uri.clock = spa_id_map_get_id (this->map, SPA_CLOCK_URI);
this->uri.format = spa_id_map_get_id (this->map, SPA_FORMAT_URI);
spa_media_types_fill (&this->uri.media_types, this->map); spa_media_types_fill (&this->uri.media_types, this->map);
spa_media_subtypes_map (this->map, &this->uri.media_subtypes); spa_media_subtypes_map (this->map, &this->uri.media_subtypes);
spa_prop_audio_map (this->map, &this->uri.prop_audio); spa_prop_audio_map (this->map, &this->uri.prop_audio);
spa_audio_formats_map (this->map, &this->uri.audio_formats); spa_audio_formats_map (this->map, &this->uri.audio_formats);
spa_node_events_map (this->map, &this->uri.node_events); spa_node_events_map (this->map, &this->uri.node_events);
spa_node_commands_map (this->map, &this->uri.node_commands);
this->node = audiotestsrc_node; this->node = audiotestsrc_node;
this->clock = audiotestsrc_clock; this->clock = audiotestsrc_clock;

View file

@ -52,6 +52,7 @@ typedef struct {
typedef struct { typedef struct {
uint32_t node; uint32_t node;
SpaNodeCommands node_commands;
} URI; } URI;
struct _SpaFFMpegDec { struct _SpaFFMpegDec {
@ -94,8 +95,8 @@ update_state (SpaFFMpegDec *this, SpaNodeState state)
} }
static SpaResult static SpaResult
spa_ffmpeg_dec_node_send_command (SpaNode *node, spa_ffmpeg_dec_node_send_command (SpaNode *node,
SpaNodeCommand *command) SpaCommand *command)
{ {
SpaFFMpegDec *this; SpaFFMpegDec *this;
@ -104,24 +105,15 @@ spa_ffmpeg_dec_node_send_command (SpaNode *node,
this = SPA_CONTAINER_OF (node, SpaFFMpegDec, node); this = SPA_CONTAINER_OF (node, SpaFFMpegDec, node);
switch (SPA_NODE_COMMAND_TYPE (command)) { if (SPA_COMMAND_TYPE (command) == this->uri.node_commands.Start) {
case SPA_NODE_COMMAND_INVALID: update_state (this, SPA_NODE_STATE_STREAMING);
return SPA_RESULT_INVALID_COMMAND;
case SPA_NODE_COMMAND_START:
update_state (this, SPA_NODE_STATE_STREAMING);
break;
case SPA_NODE_COMMAND_PAUSE:
update_state (this, SPA_NODE_STATE_PAUSED);
break;
case SPA_NODE_COMMAND_FLUSH:
case SPA_NODE_COMMAND_DRAIN:
case SPA_NODE_COMMAND_MARKER:
case SPA_NODE_COMMAND_CLOCK_UPDATE:
return SPA_RESULT_NOT_IMPLEMENTED;
} }
else if (SPA_COMMAND_TYPE (command) == this->uri.node_commands.Pause) {
update_state (this, SPA_NODE_STATE_PAUSED);
}
else
return SPA_RESULT_NOT_IMPLEMENTED;
return SPA_RESULT_OK; return SPA_RESULT_OK;
} }
@ -453,7 +445,7 @@ static SpaResult
spa_ffmpeg_dec_node_port_send_command (SpaNode *node, spa_ffmpeg_dec_node_port_send_command (SpaNode *node,
SpaDirection direction, SpaDirection direction,
uint32_t port_id, uint32_t port_id,
SpaNodeCommand *command) SpaCommand *command)
{ {
return SPA_RESULT_NOT_IMPLEMENTED; return SPA_RESULT_NOT_IMPLEMENTED;
} }
@ -533,6 +525,7 @@ spa_ffmpeg_dec_init (SpaHandle *handle,
this->uri.node = spa_id_map_get_id (this->map, SPA_NODE_URI); this->uri.node = spa_id_map_get_id (this->map, SPA_NODE_URI);
this->node = ffmpeg_dec_node; this->node = ffmpeg_dec_node;
spa_node_commands_map (this->map, &this->uri.node_commands);
this->in_ports[0].info.flags = SPA_PORT_INFO_FLAG_NONE; this->in_ports[0].info.flags = SPA_PORT_INFO_FLAG_NONE;
this->out_ports[0].info.flags = SPA_PORT_INFO_FLAG_NONE; this->out_ports[0].info.flags = SPA_PORT_INFO_FLAG_NONE;

View file

@ -59,6 +59,7 @@ typedef struct {
uint32_t node; uint32_t node;
SpaMediaTypes media_types; SpaMediaTypes media_types;
SpaMediaSubtypes media_subtypes; SpaMediaSubtypes media_subtypes;
SpaNodeCommands node_commands;
} URI; } URI;
struct _SpaFFMpegEnc { struct _SpaFFMpegEnc {
@ -101,8 +102,8 @@ spa_ffmpeg_enc_node_set_props (SpaNode *node,
} }
static SpaResult static SpaResult
spa_ffmpeg_enc_node_send_command (SpaNode *node, spa_ffmpeg_enc_node_send_command (SpaNode *node,
SpaNodeCommand *command) SpaCommand *command)
{ {
SpaFFMpegEnc *this; SpaFFMpegEnc *this;
@ -111,24 +112,15 @@ spa_ffmpeg_enc_node_send_command (SpaNode *node,
this = SPA_CONTAINER_OF (node, SpaFFMpegEnc, node); this = SPA_CONTAINER_OF (node, SpaFFMpegEnc, node);
switch (SPA_NODE_COMMAND_TYPE (command)) { if (SPA_COMMAND_TYPE (command) == this->uri.node_commands.Start) {
case SPA_NODE_COMMAND_INVALID: update_state (this, SPA_NODE_STATE_STREAMING);
return SPA_RESULT_INVALID_COMMAND;
case SPA_NODE_COMMAND_START:
update_state (this, SPA_NODE_STATE_STREAMING);
break;
case SPA_NODE_COMMAND_PAUSE:
update_state (this, SPA_NODE_STATE_PAUSED);
break;
case SPA_NODE_COMMAND_FLUSH:
case SPA_NODE_COMMAND_DRAIN:
case SPA_NODE_COMMAND_MARKER:
case SPA_NODE_COMMAND_CLOCK_UPDATE:
return SPA_RESULT_NOT_IMPLEMENTED;
} }
else if (SPA_COMMAND_TYPE (command) == this->uri.node_commands.Pause) {
update_state (this, SPA_NODE_STATE_PAUSED);
}
else
return SPA_RESULT_NOT_IMPLEMENTED;
return SPA_RESULT_OK; return SPA_RESULT_OK;
} }
@ -435,7 +427,7 @@ static SpaResult
spa_ffmpeg_enc_node_port_send_command (SpaNode *node, spa_ffmpeg_enc_node_port_send_command (SpaNode *node,
SpaDirection direction, SpaDirection direction,
uint32_t port_id, uint32_t port_id,
SpaNodeCommand *command) SpaCommand *command)
{ {
return SPA_RESULT_NOT_IMPLEMENTED; return SPA_RESULT_NOT_IMPLEMENTED;
} }
@ -546,6 +538,7 @@ spa_ffmpeg_enc_init (SpaHandle *handle,
this->uri.node = spa_id_map_get_id (this->map, SPA_NODE_URI); this->uri.node = spa_id_map_get_id (this->map, SPA_NODE_URI);
spa_media_types_fill (&this->uri.media_types, this->map); spa_media_types_fill (&this->uri.media_types, this->map);
spa_media_subtypes_map (this->map, &this->uri.media_subtypes); spa_media_subtypes_map (this->map, &this->uri.media_subtypes);
spa_node_commands_map (this->map, &this->uri.node_commands);
this->node = ffmpeg_enc_node; this->node = ffmpeg_enc_node;

View file

@ -26,6 +26,7 @@
#include <spa/node.h> #include <spa/node.h>
#include <spa/video/format-utils.h> #include <spa/video/format-utils.h>
#include <spa/clock.h>
#include <spa/list.h> #include <spa/list.h>
#include <spa/log.h> #include <spa/log.h>
#include <spa/loop.h> #include <spa/loop.h>
@ -65,12 +66,14 @@ struct _V4l2Buffer {
typedef struct { typedef struct {
uint32_t node; uint32_t node;
uint32_t clock; uint32_t clock;
uint32_t format;
SpaMediaTypes media_types; SpaMediaTypes media_types;
SpaMediaSubtypes media_subtypes; SpaMediaSubtypes media_subtypes;
SpaMediaSubtypesVideo media_subtypes_video; SpaMediaSubtypesVideo media_subtypes_video;
SpaPropVideo prop_video; SpaPropVideo prop_video;
SpaVideoFormats video_formats; SpaVideoFormats video_formats;
SpaNodeEvents node_events; SpaNodeEvents node_events;
SpaNodeCommands node_commands;
} URI; } URI;
typedef struct { typedef struct {
@ -248,7 +251,7 @@ do_pause (SpaLoop *loop,
{ {
SpaV4l2Source *this = user_data; SpaV4l2Source *this = user_data;
SpaResult res; SpaResult res;
SpaNodeCommand *cmd = data; SpaCommand *cmd = data;
res = spa_node_port_send_command (&this->node, res = spa_node_port_send_command (&this->node,
SPA_DIRECTION_OUTPUT, SPA_DIRECTION_OUTPUT,
@ -299,7 +302,7 @@ do_start (SpaLoop *loop,
{ {
SpaV4l2Source *this = user_data; SpaV4l2Source *this = user_data;
SpaResult res; SpaResult res;
SpaNodeCommand *cmd = data; SpaCommand *cmd = data;
res = spa_node_port_send_command (&this->node, res = spa_node_port_send_command (&this->node,
SPA_DIRECTION_OUTPUT, SPA_DIRECTION_OUTPUT,
@ -321,8 +324,8 @@ do_start (SpaLoop *loop,
} }
static SpaResult static SpaResult
spa_v4l2_source_node_send_command (SpaNode *node, spa_v4l2_source_node_send_command (SpaNode *node,
SpaNodeCommand *command) SpaCommand *command)
{ {
SpaV4l2Source *this; SpaV4l2Source *this;
@ -331,66 +334,53 @@ spa_v4l2_source_node_send_command (SpaNode *node,
this = SPA_CONTAINER_OF (node, SpaV4l2Source, node); this = SPA_CONTAINER_OF (node, SpaV4l2Source, node);
switch (SPA_NODE_COMMAND_TYPE (command)) { if (SPA_COMMAND_TYPE (command) == this->uri.node_commands.Start) {
case SPA_NODE_COMMAND_INVALID: SpaV4l2State *state = &this->state[0];
return SPA_RESULT_INVALID_COMMAND; SpaResult res;
case SPA_NODE_COMMAND_START: if (!state->have_format)
{ return SPA_RESULT_NO_FORMAT;
SpaV4l2State *state = &this->state[0];
SpaResult res;
if (!state->have_format) if (state->n_buffers == 0)
return SPA_RESULT_NO_FORMAT; return SPA_RESULT_NO_BUFFERS;
if (state->n_buffers == 0) if (state->started)
return SPA_RESULT_NO_BUFFERS;
if (state->started)
return SPA_RESULT_OK;
if ((res = spa_v4l2_stream_on (this)) < 0)
return res;
return spa_loop_invoke (this->state[0].data_loop,
do_start,
++this->seq,
SPA_POD_SIZE (command),
command,
this);
}
case SPA_NODE_COMMAND_PAUSE:
{
SpaV4l2State *state = &this->state[0];
if (!state->have_format)
return SPA_RESULT_NO_FORMAT;
if (state->n_buffers == 0)
return SPA_RESULT_NO_BUFFERS;
if (!state->started)
return SPA_RESULT_OK;
return spa_loop_invoke (this->state[0].data_loop,
do_pause,
++this->seq,
SPA_POD_SIZE (command),
command,
this);
}
case SPA_NODE_COMMAND_FLUSH:
case SPA_NODE_COMMAND_DRAIN:
case SPA_NODE_COMMAND_MARKER:
return SPA_RESULT_NOT_IMPLEMENTED;
case SPA_NODE_COMMAND_CLOCK_UPDATE:
{
return SPA_RESULT_OK; return SPA_RESULT_OK;
}
if ((res = spa_v4l2_stream_on (this)) < 0)
return res;
return spa_loop_invoke (this->state[0].data_loop,
do_start,
++this->seq,
SPA_POD_SIZE (command),
command,
this);
} }
return SPA_RESULT_OK; else if (SPA_COMMAND_TYPE (command) == this->uri.node_commands.Pause) {
SpaV4l2State *state = &this->state[0];
if (!state->have_format)
return SPA_RESULT_NO_FORMAT;
if (state->n_buffers == 0)
return SPA_RESULT_NO_BUFFERS;
if (!state->started)
return SPA_RESULT_OK;
return spa_loop_invoke (this->state[0].data_loop,
do_pause,
++this->seq,
SPA_POD_SIZE (command),
command,
this);
}
else if (SPA_COMMAND_TYPE (command) == this->uri.node_commands.ClockUpdate) {
return SPA_RESULT_OK;
}
else
return SPA_RESULT_NOT_IMPLEMENTED;
} }
static SpaResult static SpaResult
@ -577,7 +567,7 @@ spa_v4l2_source_node_port_get_format (SpaNode *node,
b.data = state->format_buffer; b.data = state->format_buffer;
b.size = sizeof (state->format_buffer); b.size = sizeof (state->format_buffer);
spa_pod_builder_push_format (&b, &f[0], spa_pod_builder_push_format (&b, &f[0], this->uri.format,
state->current_format.media_type, state->current_format.media_type,
state->current_format.media_subtype); state->current_format.media_subtype);
@ -784,7 +774,7 @@ static SpaResult
spa_v4l2_source_node_port_send_command (SpaNode *node, spa_v4l2_source_node_port_send_command (SpaNode *node,
SpaDirection direction, SpaDirection direction,
uint32_t port_id, uint32_t port_id,
SpaNodeCommand *command) SpaCommand *command)
{ {
SpaV4l2Source *this; SpaV4l2Source *this;
SpaResult res; SpaResult res;
@ -797,19 +787,14 @@ spa_v4l2_source_node_port_send_command (SpaNode *node,
if (port_id != 0) if (port_id != 0)
return SPA_RESULT_INVALID_PORT; return SPA_RESULT_INVALID_PORT;
switch (SPA_NODE_COMMAND_TYPE (command)) { if (SPA_COMMAND_TYPE (command) == this->uri.node_commands.Pause) {
case SPA_NODE_COMMAND_PAUSE: res = spa_v4l2_port_set_enabled (this, false);
res = spa_v4l2_port_set_enabled (this, false);
break;
case SPA_NODE_COMMAND_START:
res = spa_v4l2_port_set_enabled (this, true);
break;
default:
res = SPA_RESULT_NOT_IMPLEMENTED;
break;
} }
else if (SPA_COMMAND_TYPE (command) == this->uri.node_commands.Start) {
res = spa_v4l2_port_set_enabled (this, true);
} else
res = SPA_RESULT_NOT_IMPLEMENTED;
return res; return res;
} }
@ -972,12 +957,14 @@ v4l2_source_init (const SpaHandleFactory *factory,
} }
this->uri.node = spa_id_map_get_id (this->map, SPA_NODE_URI); this->uri.node = spa_id_map_get_id (this->map, SPA_NODE_URI);
this->uri.clock = spa_id_map_get_id (this->map, SPA_CLOCK_URI); this->uri.clock = spa_id_map_get_id (this->map, SPA_CLOCK_URI);
this->uri.format = spa_id_map_get_id (this->map, SPA_FORMAT_URI);
spa_media_types_fill (&this->uri.media_types, this->map); spa_media_types_fill (&this->uri.media_types, this->map);
spa_media_subtypes_map (this->map, &this->uri.media_subtypes); spa_media_subtypes_map (this->map, &this->uri.media_subtypes);
spa_media_subtypes_video_map (this->map, &this->uri.media_subtypes_video); spa_media_subtypes_video_map (this->map, &this->uri.media_subtypes_video);
spa_prop_video_map (this->map, &this->uri.prop_video); spa_prop_video_map (this->map, &this->uri.prop_video);
spa_video_formats_map (this->map, &this->uri.video_formats); spa_video_formats_map (this->map, &this->uri.video_formats);
spa_node_events_map (this->map, &this->uri.node_events); spa_node_events_map (this->map, &this->uri.node_events);
spa_node_commands_map (this->map, &this->uri.node_commands);
this->node = v4l2source_node; this->node = v4l2source_node;
this->clock = v4l2source_clock; this->clock = v4l2source_clock;

View file

@ -662,7 +662,7 @@ have_size:
media_subtype = *SPA_MEMBER (&this->uri, info->media_subtype_offset, uint32_t); media_subtype = *SPA_MEMBER (&this->uri, info->media_subtype_offset, uint32_t);
video_format = *SPA_MEMBER (&this->uri, info->format_offset, uint32_t); video_format = *SPA_MEMBER (&this->uri, info->format_offset, uint32_t);
spa_pod_builder_push_format (&b, &f[0], spa_pod_builder_push_format (&b, &f[0], this->uri.format,
media_type, media_type,
media_subtype); media_subtype);

View file

@ -25,6 +25,7 @@
#include <sys/timerfd.h> #include <sys/timerfd.h>
#include <spa/id-map.h> #include <spa/id-map.h>
#include <spa/clock.h>
#include <spa/log.h> #include <spa/log.h>
#include <spa/loop.h> #include <spa/loop.h>
#include <spa/node.h> #include <spa/node.h>
@ -39,11 +40,13 @@
typedef struct { typedef struct {
uint32_t node; uint32_t node;
uint32_t clock; uint32_t clock;
uint32_t format;
SpaMediaTypes media_types; SpaMediaTypes media_types;
SpaMediaSubtypes media_subtypes; SpaMediaSubtypes media_subtypes;
SpaPropVideo prop_video; SpaPropVideo prop_video;
SpaVideoFormats video_formats; SpaVideoFormats video_formats;
SpaNodeEvents node_events; SpaNodeEvents node_events;
SpaNodeCommands node_commands;
} URI; } URI;
typedef struct _SpaVideoTestSrc SpaVideoTestSrc; typedef struct _SpaVideoTestSrc SpaVideoTestSrc;
@ -283,8 +286,8 @@ update_state (SpaVideoTestSrc *this, SpaNodeState state)
} }
static SpaResult static SpaResult
spa_videotestsrc_node_send_command (SpaNode *node, spa_videotestsrc_node_send_command (SpaNode *node,
SpaNodeCommand *command) SpaCommand *command)
{ {
SpaVideoTestSrc *this; SpaVideoTestSrc *this;
@ -293,58 +296,47 @@ spa_videotestsrc_node_send_command (SpaNode *node,
this = SPA_CONTAINER_OF (node, SpaVideoTestSrc, node); this = SPA_CONTAINER_OF (node, SpaVideoTestSrc, node);
switch (SPA_NODE_COMMAND_TYPE (command)) { if (SPA_COMMAND_TYPE (command) == this->uri.node_commands.Start) {
case SPA_NODE_COMMAND_INVALID: struct timespec now;
return SPA_RESULT_INVALID_COMMAND;
case SPA_NODE_COMMAND_START: if (!this->have_format)
{ return SPA_RESULT_NO_FORMAT;
struct timespec now;
if (!this->have_format) if (this->n_buffers == 0)
return SPA_RESULT_NO_FORMAT; return SPA_RESULT_NO_BUFFERS;
if (this->n_buffers == 0) if (this->started)
return SPA_RESULT_NO_BUFFERS; return SPA_RESULT_OK;
if (this->started) clock_gettime (CLOCK_MONOTONIC, &now);
return SPA_RESULT_OK; if (this->props.live)
this->start_time = SPA_TIMESPEC_TO_TIME (&now);
else
this->start_time = 0;
this->frame_count = 0;
this->elapsed_time = 0;
clock_gettime (CLOCK_MONOTONIC, &now); this->started = true;
if (this->props.live) set_timer (this, true);
this->start_time = SPA_TIMESPEC_TO_TIME (&now); update_state (this, SPA_NODE_STATE_STREAMING);
else
this->start_time = 0;
this->frame_count = 0;
this->elapsed_time = 0;
this->started = true;
set_timer (this, true);
update_state (this, SPA_NODE_STATE_STREAMING);
break;
}
case SPA_NODE_COMMAND_PAUSE:
{
if (!this->have_format)
return SPA_RESULT_NO_FORMAT;
if (this->n_buffers == 0)
return SPA_RESULT_NO_BUFFERS;
if (!this->started)
return SPA_RESULT_OK;
this->started = false;
set_timer (this, false);
update_state (this, SPA_NODE_STATE_PAUSED);
break;
}
case SPA_NODE_COMMAND_FLUSH:
case SPA_NODE_COMMAND_DRAIN:
case SPA_NODE_COMMAND_MARKER:
case SPA_NODE_COMMAND_CLOCK_UPDATE:
return SPA_RESULT_NOT_IMPLEMENTED;
} }
else if (SPA_COMMAND_TYPE (command) == this->uri.node_commands.Pause) {
if (!this->have_format)
return SPA_RESULT_NO_FORMAT;
if (this->n_buffers == 0)
return SPA_RESULT_NO_BUFFERS;
if (!this->started)
return SPA_RESULT_OK;
this->started = false;
set_timer (this, false);
update_state (this, SPA_NODE_STATE_PAUSED);
}
else
return SPA_RESULT_NOT_IMPLEMENTED;
return SPA_RESULT_OK; return SPA_RESULT_OK;
} }
@ -454,7 +446,7 @@ next:
switch (index++) { switch (index++) {
case 0: case 0:
spa_pod_builder_format (&b, &f[0], spa_pod_builder_format (&b, &f[0], this->uri.format,
this->uri.media_types.video, this->uri.media_subtypes.raw, this->uri.media_types.video, this->uri.media_subtypes.raw,
PROP_U_EN (&f[1], this->uri.prop_video.format, SPA_POD_TYPE_URI, 3, PROP_U_EN (&f[1], this->uri.prop_video.format, SPA_POD_TYPE_URI, 3,
this->uri.video_formats.RGB, this->uri.video_formats.RGB,
@ -592,7 +584,7 @@ spa_videotestsrc_node_port_get_format (SpaNode *node,
spa_pod_builder_init (&b, this->format_buffer, sizeof (this->format_buffer)); spa_pod_builder_init (&b, this->format_buffer, sizeof (this->format_buffer));
spa_pod_builder_format (&b, &f[0], spa_pod_builder_format (&b, &f[0], this->uri.format,
this->uri.media_types.video, this->uri.media_subtypes.raw, this->uri.media_types.video, this->uri.media_subtypes.raw,
PROP (&f[1], this->uri.prop_video.format, SPA_POD_TYPE_URI, this->current_format.info.raw.format), PROP (&f[1], this->uri.prop_video.format, SPA_POD_TYPE_URI, this->current_format.info.raw.format),
PROP (&f[1], this->uri.prop_video.size, -SPA_POD_TYPE_RECTANGLE, &this->current_format.info.raw.size), PROP (&f[1], this->uri.prop_video.size, -SPA_POD_TYPE_RECTANGLE, &this->current_format.info.raw.size),
@ -792,7 +784,7 @@ static SpaResult
spa_videotestsrc_node_port_send_command (SpaNode *node, spa_videotestsrc_node_port_send_command (SpaNode *node,
SpaDirection direction, SpaDirection direction,
uint32_t port_id, uint32_t port_id,
SpaNodeCommand *command) SpaCommand *command)
{ {
return SPA_RESULT_NOT_IMPLEMENTED; return SPA_RESULT_NOT_IMPLEMENTED;
} }
@ -959,11 +951,13 @@ videotestsrc_init (const SpaHandleFactory *factory,
} }
this->uri.node = spa_id_map_get_id (this->map, SPA_NODE_URI); this->uri.node = spa_id_map_get_id (this->map, SPA_NODE_URI);
this->uri.clock = spa_id_map_get_id (this->map, SPA_CLOCK_URI); this->uri.clock = spa_id_map_get_id (this->map, SPA_CLOCK_URI);
this->uri.format = spa_id_map_get_id (this->map, SPA_FORMAT_URI);
spa_media_types_fill (&this->uri.media_types, this->map); spa_media_types_fill (&this->uri.media_types, this->map);
spa_media_subtypes_map (this->map, &this->uri.media_subtypes); spa_media_subtypes_map (this->map, &this->uri.media_subtypes);
spa_prop_video_map (this->map, &this->uri.prop_video); spa_prop_video_map (this->map, &this->uri.prop_video);
spa_video_formats_map (this->map, &this->uri.video_formats); spa_video_formats_map (this->map, &this->uri.video_formats);
spa_node_events_map (this->map, &this->uri.node_events); spa_node_events_map (this->map, &this->uri.node_events);
spa_node_commands_map (this->map, &this->uri.node_commands);
this->node = videotestsrc_node; this->node = videotestsrc_node;
this->clock = videotestsrc_clock; this->clock = videotestsrc_clock;

View file

@ -63,11 +63,13 @@ typedef struct {
typedef struct { typedef struct {
uint32_t node; uint32_t node;
uint32_t format;
SpaMediaTypes media_types; SpaMediaTypes media_types;
SpaMediaSubtypes media_subtypes; SpaMediaSubtypes media_subtypes;
SpaPropAudio prop_audio; SpaPropAudio prop_audio;
SpaAudioFormats audio_formats; SpaAudioFormats audio_formats;
SpaNodeEvents node_events; SpaNodeEvents node_events;
SpaNodeCommands node_commands;
} URI; } URI;
struct _SpaVolume { struct _SpaVolume {
@ -178,8 +180,8 @@ spa_volume_node_set_props (SpaNode *node,
} }
static SpaResult static SpaResult
spa_volume_node_send_command (SpaNode *node, spa_volume_node_send_command (SpaNode *node,
SpaNodeCommand *command) SpaCommand *command)
{ {
SpaVolume *this; SpaVolume *this;
@ -188,24 +190,15 @@ spa_volume_node_send_command (SpaNode *node,
this = SPA_CONTAINER_OF (node, SpaVolume, node); this = SPA_CONTAINER_OF (node, SpaVolume, node);
switch (SPA_NODE_COMMAND_TYPE (command)) { if (SPA_COMMAND_TYPE (command) == this->uri.node_commands.Start) {
case SPA_NODE_COMMAND_INVALID: update_state (this, SPA_NODE_STATE_STREAMING);
return SPA_RESULT_INVALID_COMMAND;
case SPA_NODE_COMMAND_START:
update_state (this, SPA_NODE_STATE_STREAMING);
break;
case SPA_NODE_COMMAND_PAUSE:
update_state (this, SPA_NODE_STATE_PAUSED);
break;
case SPA_NODE_COMMAND_FLUSH:
case SPA_NODE_COMMAND_DRAIN:
case SPA_NODE_COMMAND_MARKER:
case SPA_NODE_COMMAND_CLOCK_UPDATE:
return SPA_RESULT_NOT_IMPLEMENTED;
} }
else if (SPA_COMMAND_TYPE (command) == this->uri.node_commands.Pause) {
update_state (this, SPA_NODE_STATE_PAUSED);
}
else
return SPA_RESULT_NOT_IMPLEMENTED;
return SPA_RESULT_OK; return SPA_RESULT_OK;
} }
@ -312,7 +305,7 @@ next:
switch (index++) { switch (index++) {
case 0: case 0:
spa_pod_builder_format (&b, &f[0], spa_pod_builder_format (&b, &f[0], this->uri.format,
this->uri.media_types.audio, this->uri.media_subtypes.raw, this->uri.media_types.audio, this->uri.media_subtypes.raw,
PROP_U_EN (&f[1], this->uri.prop_audio.format, SPA_POD_TYPE_URI, 3, PROP_U_EN (&f[1], this->uri.prop_audio.format, SPA_POD_TYPE_URI, 3,
this->uri.audio_formats.S16, this->uri.audio_formats.S16,
@ -629,7 +622,7 @@ static SpaResult
spa_volume_node_port_send_command (SpaNode *node, spa_volume_node_port_send_command (SpaNode *node,
SpaDirection direction, SpaDirection direction,
uint32_t port_id, uint32_t port_id,
SpaNodeCommand *command) SpaCommand *command)
{ {
return SPA_RESULT_NOT_IMPLEMENTED; return SPA_RESULT_NOT_IMPLEMENTED;
} }
@ -844,10 +837,13 @@ volume_init (const SpaHandleFactory *factory,
return SPA_RESULT_ERROR; return SPA_RESULT_ERROR;
} }
this->uri.node = spa_id_map_get_id (this->map, SPA_NODE_URI); this->uri.node = spa_id_map_get_id (this->map, SPA_NODE_URI);
this->uri.format = spa_id_map_get_id (this->map, SPA_FORMAT_URI);
spa_media_types_fill (&this->uri.media_types, this->map); spa_media_types_fill (&this->uri.media_types, this->map);
spa_media_subtypes_map (this->map, &this->uri.media_subtypes); spa_media_subtypes_map (this->map, &this->uri.media_subtypes);
spa_prop_audio_map (this->map, &this->uri.prop_audio); spa_prop_audio_map (this->map, &this->uri.prop_audio);
spa_audio_formats_map (this->map, &this->uri.audio_formats); spa_audio_formats_map (this->map, &this->uri.audio_formats);
spa_node_events_map (this->map, &this->uri.node_events);
spa_node_commands_map (this->map, &this->uri.node_commands);
this->node = volume_node; this->node = volume_node;
reset_volume_props (&this->props); reset_volume_props (&this->props);

View file

@ -73,6 +73,7 @@ typedef struct {
uint32_t node; uint32_t node;
SpaMediaTypes media_types; SpaMediaTypes media_types;
SpaMediaSubtypes media_subtypes; SpaMediaSubtypes media_subtypes;
SpaNodeCommands node_commands;
} URI; } URI;
struct _SpaXvSink { struct _SpaXvSink {
@ -166,8 +167,8 @@ spa_xv_sink_node_set_props (SpaNode *node,
} }
static SpaResult static SpaResult
spa_xv_sink_node_send_command (SpaNode *node, spa_xv_sink_node_send_command (SpaNode *node,
SpaNodeCommand *command) SpaCommand *command)
{ {
SpaXvSink *this; SpaXvSink *this;
@ -176,27 +177,19 @@ spa_xv_sink_node_send_command (SpaNode *node,
this = SPA_CONTAINER_OF (node, SpaXvSink, node); this = SPA_CONTAINER_OF (node, SpaXvSink, node);
switch (SPA_NODE_COMMAND_TYPE (command)) { if (SPA_COMMAND_TYPE (command) == this->uri.node_commands.Start) {
case SPA_NODE_COMMAND_INVALID: spa_xv_start (this);
return SPA_RESULT_INVALID_COMMAND;
case SPA_NODE_COMMAND_START: update_state (this, SPA_NODE_STATE_STREAMING);
spa_xv_start (this);
update_state (this, SPA_NODE_STATE_STREAMING);
break;
case SPA_NODE_COMMAND_PAUSE:
spa_xv_stop (this);
update_state (this, SPA_NODE_STATE_PAUSED);
break;
case SPA_NODE_COMMAND_FLUSH:
case SPA_NODE_COMMAND_DRAIN:
case SPA_NODE_COMMAND_MARKER:
case SPA_NODE_COMMAND_CLOCK_UPDATE:
return SPA_RESULT_NOT_IMPLEMENTED;
} }
else if (SPA_COMMAND_TYPE (command) == this->uri.node_commands.Pause) {
spa_xv_stop (this);
update_state (this, SPA_NODE_STATE_PAUSED);
}
else
return SPA_RESULT_NOT_IMPLEMENTED;
return SPA_RESULT_OK; return SPA_RESULT_OK;
} }
@ -471,7 +464,7 @@ static SpaResult
spa_xv_sink_node_port_send_command (SpaNode *node, spa_xv_sink_node_port_send_command (SpaNode *node,
SpaDirection direction, SpaDirection direction,
uint32_t port_id, uint32_t port_id,
SpaNodeCommand *command) SpaCommand *command)
{ {
return SPA_RESULT_NOT_IMPLEMENTED; return SPA_RESULT_NOT_IMPLEMENTED;
} }
@ -573,6 +566,7 @@ xv_sink_init (const SpaHandleFactory *factory,
this->uri.node = spa_id_map_get_id (this->map, SPA_NODE_URI); this->uri.node = spa_id_map_get_id (this->map, SPA_NODE_URI);
spa_media_types_fill (&this->uri.media_types, this->map); spa_media_types_fill (&this->uri.media_types, this->map);
spa_media_subtypes_map (this->map, &this->uri.media_subtypes); spa_media_subtypes_map (this->map, &this->uri.media_subtypes);
spa_node_commands_map (this->map, &this->uri.node_commands);
this->node = xvsink_node; this->node = xvsink_node;
reset_xv_sink_props (&this->props); reset_xv_sink_props (&this->props);

View file

@ -60,6 +60,7 @@ spa_build (SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_RAW,
0); 0);
#endif #endif
static uint32_t format_type;
static SpaMediaTypes media_types; static SpaMediaTypes media_types;
static SpaMediaSubtypes media_subtypes; static SpaMediaSubtypes media_subtypes;
static SpaPropVideo prop_video; static SpaPropVideo prop_video;
@ -95,7 +96,7 @@ do_static_struct (void)
} props; } props;
} test_format = { } test_format = {
{ { sizeof (test_format.props) + sizeof (SpaFormatBody), SPA_POD_TYPE_OBJECT }, { { sizeof (test_format.props) + sizeof (SpaFormatBody), SPA_POD_TYPE_OBJECT },
{ { 0, 0 }, { { 0, format_type },
{ { sizeof (uint32_t), SPA_POD_TYPE_URI }, media_types.video }, { { sizeof (uint32_t), SPA_POD_TYPE_URI }, media_types.video },
{ { sizeof (uint32_t), SPA_POD_TYPE_URI }, media_subtypes.raw } }, { { sizeof (uint32_t), SPA_POD_TYPE_URI }, media_subtypes.raw } },
}, { }, {
@ -148,15 +149,17 @@ main (int argc, char *argv[])
SpaPODFrame frame[4]; SpaPODFrame frame[4];
uint8_t buffer[1024]; uint8_t buffer[1024];
SpaFormat *fmt; SpaFormat *fmt;
SpaIDMap *map = spa_id_map_get_default();
spa_media_types_fill (&media_types, spa_id_map_get_default()); format_type = spa_id_map_get_id (map, SPA_FORMAT_URI);
spa_media_subtypes_map (spa_id_map_get_default(), &media_subtypes); spa_media_types_fill (&media_types, map);
spa_prop_video_map (spa_id_map_get_default(), &prop_video); spa_media_subtypes_map (map, &media_subtypes);
spa_video_formats_map (spa_id_map_get_default(), &video_formats); spa_prop_video_map (map, &prop_video);
spa_video_formats_map (map, &video_formats);
spa_pod_builder_init (&b, buffer, sizeof (buffer)); spa_pod_builder_init (&b, buffer, sizeof (buffer));
fmt = SPA_MEMBER (buffer, spa_pod_builder_push_format (&b, &frame[0], fmt = SPA_MEMBER (buffer, spa_pod_builder_push_format (&b, &frame[0], format_type,
media_types.video, media_types.video,
media_subtypes.raw), SpaFormat); media_subtypes.raw), SpaFormat);
spa_pod_builder_push_prop (&b, &frame[1], spa_pod_builder_push_prop (&b, &frame[1],
@ -189,7 +192,7 @@ main (int argc, char *argv[])
spa_pod_builder_init (&b, buffer, sizeof (buffer)); spa_pod_builder_init (&b, buffer, sizeof (buffer));
spa_pod_builder_format (&b, &frame[0], spa_pod_builder_format (&b, &frame[0], format_type,
media_types.video, media_subtypes.raw, media_types.video, media_subtypes.raw,
SPA_POD_TYPE_PROP, &frame[1], SPA_POD_TYPE_PROP, &frame[1],
prop_video.format, SPA_POD_PROP_FLAG_UNSET | prop_video.format, SPA_POD_PROP_FLAG_UNSET |
@ -214,7 +217,7 @@ main (int argc, char *argv[])
25, 1, 25, 1,
0, 1, 0, 1,
INT32_MAX, 1, INT32_MAX, 1,
-SPA_POD_TYPE_PROP, &frame[1], 0); -SPA_POD_TYPE_PROP, &frame[1]);
fmt = SPA_MEMBER (buffer, frame[0].ref, SpaFormat); fmt = SPA_MEMBER (buffer, frame[0].ref, SpaFormat);
spa_debug_pod (&fmt->pod); spa_debug_pod (&fmt->pod);
@ -223,7 +226,7 @@ main (int argc, char *argv[])
spa_pod_builder_init (&b, buffer, sizeof (buffer)); spa_pod_builder_init (&b, buffer, sizeof (buffer));
spa_pod_builder_add (&b, spa_pod_builder_add (&b,
SPA_POD_TYPE_OBJECT, &frame[0], 0, 0, SPA_POD_TYPE_OBJECT, &frame[0], 0, format_type,
SPA_POD_TYPE_URI, media_types.video, SPA_POD_TYPE_URI, media_types.video,
SPA_POD_TYPE_URI, media_subtypes.raw, SPA_POD_TYPE_URI, media_subtypes.raw,
SPA_POD_TYPE_PROP, &frame[1], SPA_POD_TYPE_PROP, &frame[1],

View file

@ -24,6 +24,7 @@
#include <dlfcn.h> #include <dlfcn.h>
#include <spa/id-map.h> #include <spa/id-map.h>
#include <spa/clock.h>
#include <spa/log.h> #include <spa/log.h>
#include <spa/node.h> #include <spa/node.h>
#include <spa/loop.h> #include <spa/loop.h>