Implement subscription with a signal

Use a signal for subscription events
Work on handling OOM errors and other errors.
This commit is contained in:
Wim Taymans 2016-12-22 16:50:01 +01:00
parent 1b66bbcffd
commit 85d375e4bb
32 changed files with 531 additions and 176 deletions

View file

@ -98,6 +98,17 @@ connection_parse_client_update (PinosConnection *conn, PinosMessageClientUpdate
m->props = pinos_serialize_dict_deserialize (p, SPA_PTR_TO_INT (m->props)); m->props = pinos_serialize_dict_deserialize (p, SPA_PTR_TO_INT (m->props));
} }
static void
connection_parse_error (PinosConnection *conn, PinosMessageError *m)
{
void *p;
p = conn->in.data;
memcpy (m, p, sizeof (PinosMessageError));
if (m->error)
m->error = SPA_MEMBER (p, SPA_PTR_TO_INT (m->error), const char);
}
static void static void
connection_parse_notify_global (PinosConnection *conn, PinosMessageNotifyGlobal *ng) connection_parse_notify_global (PinosConnection *conn, PinosMessageNotifyGlobal *ng)
{ {
@ -198,6 +209,8 @@ connection_parse_node_info (PinosConnection *conn, PinosMessageNodeInfo *m)
if (m->info->name) if (m->info->name)
m->info->name = SPA_MEMBER (di, SPA_PTR_TO_INT (m->info->name), const char); m->info->name = SPA_MEMBER (di, SPA_PTR_TO_INT (m->info->name), const char);
if (m->info->error)
m->info->error = SPA_MEMBER (di, SPA_PTR_TO_INT (m->info->error), const char);
if (m->info->props) if (m->info->props)
m->info->props = pinos_serialize_dict_deserialize (di, SPA_PTR_TO_INT (m->info->props)); m->info->props = pinos_serialize_dict_deserialize (di, SPA_PTR_TO_INT (m->info->props));
} }
@ -374,6 +387,29 @@ connection_add_client_update (PinosConnection *conn,
} }
} }
static void
connection_add_error (PinosConnection *conn,
uint32_t dest_id,
PinosMessageError *m)
{
size_t len;
void *p;
PinosMessageError *d;
/* calc len */
len = sizeof (PinosMessageError);
len += m->error ? strlen (m->error) + 1 : 0;
p = connection_add_message (conn, dest_id, PINOS_MESSAGE_ERROR, len);
memcpy (p, m, sizeof (PinosMessageError));
d = p;
if (m->error) {
strcpy (p, m->error);
d->error = SPA_INT_TO_PTR (SPA_PTRDIFF (p, d));
}
}
static void static void
connection_add_notify_global (PinosConnection *conn, connection_add_notify_global (PinosConnection *conn,
uint32_t dest_id, uint32_t dest_id,
@ -593,6 +629,7 @@ connection_add_node_info (PinosConnection *conn, uint32_t dest_id, PinosMessageN
if (m->info) { if (m->info) {
len += sizeof (PinosNodeInfo); len += sizeof (PinosNodeInfo);
len += m->info->name ? strlen (m->info->name) + 1 : 0; len += m->info->name ? strlen (m->info->name) + 1 : 0;
len += m->info->error ? strlen (m->info->error) + 1 : 0;
len += pinos_serialize_dict_get_size (m->info->props); len += pinos_serialize_dict_get_size (m->info->props);
} }
@ -615,6 +652,12 @@ connection_add_node_info (PinosConnection *conn, uint32_t dest_id, PinosMessageN
di->name = SPA_INT_TO_PTR (SPA_PTRDIFF (p, di)); di->name = SPA_INT_TO_PTR (SPA_PTRDIFF (p, di));
p += slen; p += slen;
} }
if (m->info->error) {
slen = strlen (m->info->error) + 1;
memcpy (p, m->info->error, slen);
di->error = SPA_INT_TO_PTR (SPA_PTRDIFF (p, di));
p += slen;
}
if (m->info->props) { if (m->info->props) {
len = pinos_serialize_dict_serialize (p, m->info->props); len = pinos_serialize_dict_serialize (p, m->info->props);
di->props = SPA_INT_TO_PTR (SPA_PTRDIFF (p, di)); di->props = SPA_INT_TO_PTR (SPA_PTRDIFF (p, di));
@ -952,7 +995,11 @@ pinos_connection_new (int fd)
PinosConnection *c; PinosConnection *c;
c = calloc (1, sizeof (PinosConnection)); c = calloc (1, sizeof (PinosConnection));
if (c == NULL)
return NULL;
pinos_log_debug ("connection %p: new", c); pinos_log_debug ("connection %p: new", c);
c->fd = fd; c->fd = fd;
c->out.buffer_data = malloc (MAX_BUFFER_SIZE); c->out.buffer_data = malloc (MAX_BUFFER_SIZE);
c->out.buffer_maxsize = MAX_BUFFER_SIZE; c->out.buffer_maxsize = MAX_BUFFER_SIZE;
@ -960,7 +1007,16 @@ pinos_connection_new (int fd)
c->in.buffer_maxsize = MAX_BUFFER_SIZE; c->in.buffer_maxsize = MAX_BUFFER_SIZE;
c->in.update = true; c->in.update = true;
if (c->out.buffer_data == NULL || c->in.buffer_data == NULL)
goto no_mem;
return c; return c;
no_mem:
free (c->out.buffer_data);
free (c->in.buffer_data);
free (c);
return NULL;
} }
void void
@ -1069,6 +1125,10 @@ pinos_connection_parse_message (PinosConnection *conn,
memcpy (message, conn->in.data, sizeof (PinosMessageNotifyDone)); memcpy (message, conn->in.data, sizeof (PinosMessageNotifyDone));
break; break;
case PINOS_MESSAGE_ERROR:
connection_parse_error (conn, message);
break;
case PINOS_MESSAGE_GET_REGISTRY: case PINOS_MESSAGE_GET_REGISTRY:
if (conn->in.size < sizeof (PinosMessageGetRegistry)) if (conn->in.size < sizeof (PinosMessageGetRegistry))
return false; return false;
@ -1265,6 +1325,10 @@ pinos_connection_add_message (PinosConnection *conn,
memcpy (p, message, sizeof (PinosMessageNotifyDone)); memcpy (p, message, sizeof (PinosMessageNotifyDone));
break; break;
case PINOS_MESSAGE_ERROR:
connection_add_error (conn, dest_id, message);
break;
case PINOS_MESSAGE_GET_REGISTRY: case PINOS_MESSAGE_GET_REGISTRY:
p = connection_add_message (conn, dest_id, type, sizeof (PinosMessageGetRegistry)); p = connection_add_message (conn, dest_id, type, sizeof (PinosMessageGetRegistry));
memcpy (p, message, sizeof (PinosMessageGetRegistry)); memcpy (p, message, sizeof (PinosMessageGetRegistry));

View file

@ -39,6 +39,7 @@ typedef enum {
PINOS_MESSAGE_SYNC, PINOS_MESSAGE_SYNC,
PINOS_MESSAGE_NOTIFY_DONE, PINOS_MESSAGE_NOTIFY_DONE,
PINOS_MESSAGE_ERROR,
PINOS_MESSAGE_GET_REGISTRY, PINOS_MESSAGE_GET_REGISTRY,
PINOS_MESSAGE_REMOVE_ID, PINOS_MESSAGE_REMOVE_ID,
PINOS_MESSAGE_CORE_INFO, PINOS_MESSAGE_CORE_INFO,
@ -103,6 +104,13 @@ typedef struct {
uint32_t seq; uint32_t seq;
} PinosMessageNotifyDone; } PinosMessageNotifyDone;
/* PINOS_MESSAGE_ERROR */
typedef struct {
uint32_t id;
SpaResult res;
const char *error;
} PinosMessageError;
/* PINOS_MESSAGE_GET_REGISTRY */ /* PINOS_MESSAGE_GET_REGISTRY */
typedef struct { typedef struct {
uint32_t seq; uint32_t seq;

View file

@ -37,9 +37,6 @@ typedef struct {
SpaSource source; SpaSource source;
bool disconnecting; bool disconnecting;
PinosSubscriptionFunc subscribe_func;
void *subscribe_data;
} PinosContextImpl; } PinosContextImpl;
/** /**
@ -112,6 +109,7 @@ core_dispatch_func (void *object,
PinosSubscriptionEvent event; PinosSubscriptionEvent event;
pinos_log_debug ("got core info %d", type); pinos_log_debug ("got core info %d", type);
if (proxy->user_data == NULL) if (proxy->user_data == NULL)
event = PINOS_SUBSCRIPTION_EVENT_NEW; event = PINOS_SUBSCRIPTION_EVENT_NEW;
else else
@ -119,13 +117,11 @@ core_dispatch_func (void *object,
proxy->user_data = pinos_core_info_update (proxy->user_data, m->info); proxy->user_data = pinos_core_info_update (proxy->user_data, m->info);
if (impl->subscribe_func) { pinos_signal_emit (&this->subscription,
impl->subscribe_func (this, this,
event, event,
proxy->type, proxy->type,
proxy->id, proxy->id);
impl->subscribe_data);
}
break; break;
} }
case PINOS_MESSAGE_NOTIFY_DONE: case PINOS_MESSAGE_NOTIFY_DONE:
@ -136,6 +132,12 @@ core_dispatch_func (void *object,
context_set_state (this, PINOS_CONTEXT_STATE_CONNECTED, NULL); context_set_state (this, PINOS_CONTEXT_STATE_CONNECTED, NULL);
break; break;
} }
case PINOS_MESSAGE_ERROR:
{
PinosMessageError *m = message;
context_set_state (this, PINOS_CONTEXT_STATE_ERROR, m->error);
break;
}
case PINOS_MESSAGE_REMOVE_ID: case PINOS_MESSAGE_REMOVE_ID:
{ {
PinosMessageRemoveId *m = message; PinosMessageRemoveId *m = message;
@ -180,13 +182,11 @@ module_dispatch_func (void *object,
proxy->user_data = pinos_module_info_update (proxy->user_data, m->info); proxy->user_data = pinos_module_info_update (proxy->user_data, m->info);
if (impl->subscribe_func) { pinos_signal_emit (&this->subscription,
impl->subscribe_func (this, this,
event, event,
proxy->type, proxy->type,
proxy->id, proxy->id);
impl->subscribe_data);
}
break; break;
} }
@ -221,13 +221,11 @@ node_dispatch_func (void *object,
proxy->user_data = pinos_node_info_update (proxy->user_data, m->info); proxy->user_data = pinos_node_info_update (proxy->user_data, m->info);
if (impl->subscribe_func) { pinos_signal_emit (&this->subscription,
impl->subscribe_func (this, this,
event, event,
proxy->type, proxy->type,
proxy->id, proxy->id);
impl->subscribe_data);
}
break; break;
} }
default: default:
@ -261,13 +259,11 @@ client_dispatch_func (void *object,
proxy->user_data = pinos_client_info_update (proxy->user_data, m->info); proxy->user_data = pinos_client_info_update (proxy->user_data, m->info);
if (impl->subscribe_func) { pinos_signal_emit (&this->subscription,
impl->subscribe_func (this, this,
event, event,
proxy->type, proxy->type,
proxy->id, proxy->id);
impl->subscribe_data);
}
break; break;
} }
default: default:
@ -301,13 +297,11 @@ link_dispatch_func (void *object,
proxy->user_data = pinos_link_info_update (proxy->user_data, m->info); proxy->user_data = pinos_link_info_update (proxy->user_data, m->info);
if (impl->subscribe_func) { pinos_signal_emit (&this->subscription,
impl->subscribe_func (this, this,
event, event,
proxy->type, proxy->type,
proxy->id, proxy->id);
impl->subscribe_data);
}
break; break;
} }
default: default:
@ -338,24 +332,32 @@ registry_dispatch_func (void *object,
proxy = pinos_proxy_new (this, proxy = pinos_proxy_new (this,
SPA_ID_INVALID, SPA_ID_INVALID,
this->uri.node); this->uri.node);
if (proxy == NULL)
goto no_mem;
proxy->dispatch_func = node_dispatch_func; proxy->dispatch_func = node_dispatch_func;
proxy->dispatch_data = impl; proxy->dispatch_data = impl;
} else if (!strcmp (ng->type, PINOS_MODULE_URI)) { } else if (!strcmp (ng->type, PINOS_MODULE_URI)) {
proxy = pinos_proxy_new (this, proxy = pinos_proxy_new (this,
SPA_ID_INVALID, SPA_ID_INVALID,
this->uri.module); this->uri.module);
if (proxy == NULL)
goto no_mem;
proxy->dispatch_func = module_dispatch_func; proxy->dispatch_func = module_dispatch_func;
proxy->dispatch_data = impl; proxy->dispatch_data = impl;
} else if (!strcmp (ng->type, PINOS_CLIENT_URI)) { } else if (!strcmp (ng->type, PINOS_CLIENT_URI)) {
proxy = pinos_proxy_new (this, proxy = pinos_proxy_new (this,
SPA_ID_INVALID, SPA_ID_INVALID,
this->uri.client); this->uri.client);
if (proxy == NULL)
goto no_mem;
proxy->dispatch_func = client_dispatch_func; proxy->dispatch_func = client_dispatch_func;
proxy->dispatch_data = impl; proxy->dispatch_data = impl;
} else if (!strcmp (ng->type, PINOS_LINK_URI)) { } else if (!strcmp (ng->type, PINOS_LINK_URI)) {
proxy = pinos_proxy_new (this, proxy = pinos_proxy_new (this,
SPA_ID_INVALID, SPA_ID_INVALID,
this->uri.link); this->uri.link);
if (proxy == NULL)
goto no_mem;
proxy->dispatch_func = link_dispatch_func; proxy->dispatch_func = link_dispatch_func;
proxy->dispatch_data = impl; proxy->dispatch_data = impl;
} }
@ -376,13 +378,11 @@ registry_dispatch_func (void *object,
PinosMessageNotifyGlobalRemove *ng = message; PinosMessageNotifyGlobalRemove *ng = message;
pinos_log_debug ("got global remove %u", ng->id); pinos_log_debug ("got global remove %u", ng->id);
if (impl->subscribe_func) { pinos_signal_emit (&this->subscription,
impl->subscribe_func (this, this,
PINOS_SUBSCRIPTION_EVENT_REMOVE, PINOS_SUBSCRIPTION_EVENT_REMOVE,
SPA_ID_INVALID, SPA_ID_INVALID,
ng->id, ng->id);
impl->subscribe_data);
}
break; break;
} }
default: default:
@ -390,6 +390,9 @@ registry_dispatch_func (void *object,
break; break;
} }
return SPA_RESULT_OK; return SPA_RESULT_OK;
no_mem:
return SPA_RESULT_NO_MEMORY;
} }
static void static void
@ -477,6 +480,9 @@ pinos_context_new (PinosLoop *loop,
PinosContext *this; PinosContext *this;
impl = calloc (1, sizeof (PinosContextImpl)); impl = calloc (1, sizeof (PinosContextImpl));
if (impl == NULL)
return NULL;
this = &impl->this; this = &impl->this;
pinos_log_debug ("context %p: new", impl); pinos_log_debug ("context %p: new", impl);
@ -484,6 +490,9 @@ pinos_context_new (PinosLoop *loop,
if (properties == NULL) if (properties == NULL)
properties = pinos_properties_new ("application.name", name, NULL); properties = pinos_properties_new ("application.name", name, NULL);
if (properties == NULL)
goto no_mem;
pinos_fill_context_properties (properties); pinos_fill_context_properties (properties);
this->properties = properties; this->properties = properties;
@ -503,9 +512,15 @@ pinos_context_new (PinosLoop *loop,
spa_list_init (&this->proxy_list); spa_list_init (&this->proxy_list);
pinos_signal_init (&this->state_changed); pinos_signal_init (&this->state_changed);
pinos_signal_init (&this->subscription);
pinos_signal_init (&this->destroy_signal); pinos_signal_init (&this->destroy_signal);
return this; return this;
no_mem:
free (this->name);
free (impl);
return NULL;
} }
void void
@ -523,14 +538,10 @@ pinos_context_destroy (PinosContext *context)
spa_list_for_each_safe (proxy, t2, &context->proxy_list, link) spa_list_for_each_safe (proxy, t2, &context->proxy_list, link)
pinos_proxy_destroy (proxy); pinos_proxy_destroy (proxy);
if (context->name)
free (context->name); free (context->name);
if (context->properties) if (context->properties)
pinos_properties_free (context->properties); pinos_properties_free (context->properties);
if (context->error)
free (context->error); free (context->error);
free (impl); free (impl);
} }
@ -579,8 +590,7 @@ pinos_context_connect (PinosContext *context)
if (name_size > (int)sizeof addr.sun_path) { if (name_size > (int)sizeof addr.sun_path) {
pinos_log_error ("socket path \"%s/%s\" plus null terminator exceeds 108 bytes", pinos_log_error ("socket path \"%s/%s\" plus null terminator exceeds 108 bytes",
runtime_dir, name); runtime_dir, name);
close (fd); goto error_close;
return false;
}; };
size = offsetof (struct sockaddr_un, sun_path) + name_size; size = offsetof (struct sockaddr_un, sun_path) + name_size;
@ -589,12 +599,14 @@ pinos_context_connect (PinosContext *context)
context_set_state (context, context_set_state (context,
PINOS_CONTEXT_STATE_ERROR, PINOS_CONTEXT_STATE_ERROR,
"connect failed: %s", strerror (errno)); "connect failed: %s", strerror (errno));
close (fd); goto error_close;
return false;
} }
impl->fd = fd;
impl->connection = pinos_connection_new (fd); impl->connection = pinos_connection_new (fd);
if (impl->connection == NULL)
goto error_close;
impl->fd = fd;
pinos_loop_add_io (context->loop, pinos_loop_add_io (context->loop,
fd, fd,
@ -606,6 +618,9 @@ pinos_context_connect (PinosContext *context)
context->core_proxy = pinos_proxy_new (context, context->core_proxy = pinos_proxy_new (context,
SPA_ID_INVALID, SPA_ID_INVALID,
context->uri.core); context->uri.core);
if (context->core_proxy == NULL)
goto no_proxy;
context->core_proxy->dispatch_func = core_dispatch_func; context->core_proxy->dispatch_func = core_dispatch_func;
context->core_proxy->dispatch_data = impl; context->core_proxy->dispatch_data = impl;
@ -618,6 +633,9 @@ pinos_context_connect (PinosContext *context)
context->registry_proxy = pinos_proxy_new (context, context->registry_proxy = pinos_proxy_new (context,
SPA_ID_INVALID, SPA_ID_INVALID,
context->uri.registry); context->uri.registry);
if (context->registry_proxy == NULL)
goto no_registry;
context->registry_proxy->dispatch_func = registry_dispatch_func; context->registry_proxy->dispatch_func = registry_dispatch_func;
context->registry_proxy->dispatch_data = impl; context->registry_proxy->dispatch_data = impl;
@ -628,6 +646,14 @@ pinos_context_connect (PinosContext *context)
&grm, &grm,
true); true);
return true; return true;
no_registry:
pinos_proxy_destroy (context->core_proxy);
no_proxy:
pinos_connection_destroy (impl->connection);
error_close:
close (fd);
return false;
} }
/** /**
@ -645,6 +671,8 @@ pinos_context_disconnect (PinosContext *context)
impl->disconnecting = true; impl->disconnecting = true;
pinos_proxy_destroy (context->registry_proxy);
pinos_proxy_destroy (context->core_proxy);
pinos_connection_destroy (impl->connection); pinos_connection_destroy (impl->connection);
close (impl->fd); close (impl->fd);
@ -653,17 +681,6 @@ pinos_context_disconnect (PinosContext *context)
return true; return true;
} }
void
pinos_context_subscribe (PinosContext *context,
PinosSubscriptionFunc func,
void *data)
{
PinosContextImpl *impl = SPA_CONTAINER_OF (context, PinosContextImpl, this);
impl->subscribe_func = func;
impl->subscribe_data = data;
}
void void
pinos_context_get_core_info (PinosContext *context, pinos_context_get_core_info (PinosContext *context,
PinosCoreInfoCallback cb, PinosCoreInfoCallback cb,

View file

@ -29,6 +29,7 @@ typedef struct _PinosContext PinosContext;
#include <pinos/client/map.h> #include <pinos/client/map.h>
#include <pinos/client/loop.h> #include <pinos/client/loop.h>
#include <pinos/client/properties.h> #include <pinos/client/properties.h>
#include <pinos/client/subscribe.h>
#include <pinos/client/proxy.h> #include <pinos/client/proxy.h>
#include <pinos/client/uri.h> #include <pinos/client/uri.h>
@ -80,6 +81,12 @@ struct _PinosContext {
PINOS_SIGNAL (state_changed, (PinosListener *listener, PINOS_SIGNAL (state_changed, (PinosListener *listener,
PinosContext *context)); PinosContext *context));
PINOS_SIGNAL (subscription, (PinosListener *listener,
PinosContext *context,
PinosSubscriptionEvent event,
uint32_t type,
uint32_t id));
PINOS_SIGNAL (destroy_signal, (PinosListener *listener, PINOS_SIGNAL (destroy_signal, (PinosListener *listener,
PinosContext *context)); PinosContext *context));
}; };

View file

@ -127,7 +127,11 @@ pinos_spa_dict_copy (SpaDict *dict)
return NULL; return NULL;
copy = calloc (1, sizeof (SpaDict)); copy = calloc (1, sizeof (SpaDict));
if (copy == NULL)
goto no_mem;
copy->items = calloc (dict->n_items, sizeof (SpaDictItem)); copy->items = calloc (dict->n_items, sizeof (SpaDictItem));
if (copy->items == NULL)
goto no_items;
copy->n_items = dict->n_items; copy->n_items = dict->n_items;
for (i = 0; i < dict->n_items; i++) { for (i = 0; i < dict->n_items; i++) {
@ -135,6 +139,11 @@ pinos_spa_dict_copy (SpaDict *dict)
copy->items[i].value = strdup (dict->items[i].value); copy->items[i].value = strdup (dict->items[i].value);
} }
return copy; return copy;
no_items:
free (copy);
no_mem:
return NULL;
} }
PinosCoreInfo * PinosCoreInfo *
@ -148,6 +157,8 @@ pinos_core_info_update (PinosCoreInfo *info,
if (info == NULL) { if (info == NULL) {
info = calloc (1, sizeof (PinosCoreInfo)); info = calloc (1, sizeof (PinosCoreInfo));
if (info == NULL)
return NULL;
change_mask = ~0; change_mask = ~0;
} else { } else {
change_mask = info->change_mask | update->change_mask; change_mask = info->change_mask | update->change_mask;
@ -215,6 +226,8 @@ pinos_node_info_update (PinosNodeInfo *info,
if (info == NULL) { if (info == NULL) {
info = calloc (1, sizeof (PinosNodeInfo)); info = calloc (1, sizeof (PinosNodeInfo));
if (info == NULL)
return NULL;
change_mask = ~0; change_mask = ~0;
} else { } else {
change_mask = info->change_mask | update->change_mask; change_mask = info->change_mask | update->change_mask;
@ -229,6 +242,9 @@ pinos_node_info_update (PinosNodeInfo *info,
} }
if (update->change_mask & (1 << 1)) { if (update->change_mask & (1 << 1)) {
info->state = update->state; info->state = update->state;
if (info->error)
free ((void*)info->error);
info->error = update->error ? strdup (update->error) : NULL;
} }
if (update->change_mask & (1 << 2)) { if (update->change_mask & (1 << 2)) {
if (info->props) if (info->props)
@ -245,6 +261,8 @@ pinos_node_info_free (PinosNodeInfo *info)
return; return;
if (info->name) if (info->name)
free ((void*)info->name); free ((void*)info->name);
if (info->error)
free ((void*)info->error);
if (info->props) if (info->props)
pinos_spa_dict_destroy (info->props); pinos_spa_dict_destroy (info->props);
free (info); free (info);
@ -261,6 +279,8 @@ pinos_module_info_update (PinosModuleInfo *info,
if (info == NULL) { if (info == NULL) {
info = calloc (1, sizeof (PinosModuleInfo)); info = calloc (1, sizeof (PinosModuleInfo));
if (info == NULL)
return NULL;
change_mask = ~0; change_mask = ~0;
} else { } else {
change_mask = info->change_mask | update->change_mask; change_mask = info->change_mask | update->change_mask;
@ -320,6 +340,8 @@ pinos_client_info_update (PinosClientInfo *info,
if (info == NULL) { if (info == NULL) {
info = calloc (1, sizeof (PinosClientInfo)); info = calloc (1, sizeof (PinosClientInfo));
if (info == NULL)
return NULL;
change_mask = ~0; change_mask = ~0;
} else { } else {
change_mask = info->change_mask | update->change_mask; change_mask = info->change_mask | update->change_mask;
@ -356,6 +378,8 @@ pinos_link_info_update (PinosLinkInfo *info,
if (info == NULL) { if (info == NULL) {
info = calloc (1, sizeof (PinosLinkInfo)); info = calloc (1, sizeof (PinosLinkInfo));
if (info == NULL)
return NULL;
change_mask = ~0; change_mask = ~0;
} else { } else {
change_mask = info->change_mask | update->change_mask; change_mask = info->change_mask | update->change_mask;

View file

@ -240,8 +240,9 @@ void pinos_context_get_client_info_by_id (PinosContext *co
* @id: generic id of the node * @id: generic id of the node
* @change_mask: bitfield of changed fields since last call * @change_mask: bitfield of changed fields since last call
* @name: name the node, suitable for display * @name: name the node, suitable for display
* @props: the properties of the node
* @state: the current state of the node * @state: the current state of the node
* @error: an error reason if @state is error
* @props: the properties of the node
* *
* The node information. Extra information can be added in later * The node information. Extra information can be added in later
* versions. * versions.
@ -251,6 +252,7 @@ struct _PinosNodeInfo {
uint64_t change_mask; uint64_t change_mask;
const char *name; const char *name;
PinosNodeState state; PinosNodeState state;
const char *error;
SpaDict *props; SpaDict *props;
}; };

View file

@ -312,6 +312,8 @@ loop_add_io (SpaLoopUtils *utils,
SpaSourceImpl *source; SpaSourceImpl *source;
source = calloc (1, sizeof (SpaSourceImpl)); source = calloc (1, sizeof (SpaSourceImpl));
if (source == NULL)
return NULL;
source->source.loop = &impl->loop; source->source.loop = &impl->loop;
source->source.func = source_io_func; source->source.func = source_io_func;
@ -353,6 +355,8 @@ loop_add_idle (SpaLoopUtils *utils,
SpaSourceImpl *source; SpaSourceImpl *source;
source = calloc (1, sizeof (SpaSourceImpl)); source = calloc (1, sizeof (SpaSourceImpl));
if (source == NULL)
return NULL;
source->source.loop = &impl->loop; source->source.loop = &impl->loop;
source->source.func = source_idle_func; source->source.func = source_idle_func;
@ -408,6 +412,8 @@ loop_add_event (SpaLoopUtils *utils,
SpaSourceImpl *source; SpaSourceImpl *source;
source = calloc (1, sizeof (SpaSourceImpl)); source = calloc (1, sizeof (SpaSourceImpl));
if (source == NULL)
return NULL;
source->source.loop = &impl->loop; source->source.loop = &impl->loop;
source->source.func = source_event_func; source->source.func = source_event_func;
@ -454,6 +460,8 @@ loop_add_timer (SpaLoopUtils *utils,
SpaSourceImpl *source; SpaSourceImpl *source;
source = calloc (1, sizeof (SpaSourceImpl)); source = calloc (1, sizeof (SpaSourceImpl));
if (source == NULL)
return NULL;
source->source.loop = &impl->loop; source->source.loop = &impl->loop;
source->source.func = source_timer_func; source->source.func = source_timer_func;
@ -516,6 +524,8 @@ loop_add_signal (SpaLoopUtils *utils,
sigset_t mask; sigset_t mask;
source = calloc (1, sizeof (SpaSourceImpl)); source = calloc (1, sizeof (SpaSourceImpl));
if (source == NULL)
return NULL;
source->source.loop = &impl->loop; source->source.loop = &impl->loop;
source->source.func = source_signal_func; source->source.func = source_signal_func;
@ -557,13 +567,14 @@ pinos_loop_new (void)
PinosLoop *this; PinosLoop *this;
impl = calloc (1, sizeof (PinosLoopImpl)); impl = calloc (1, sizeof (PinosLoopImpl));
if (impl == NULL)
return NULL;
this = &impl->this; this = &impl->this;
impl->epoll_fd = epoll_create1 (EPOLL_CLOEXEC); impl->epoll_fd = epoll_create1 (EPOLL_CLOEXEC);
if (impl->epoll_fd == -1) { if (impl->epoll_fd == -1)
free (impl); goto no_epoll;
return NULL;
}
spa_list_init (&impl->source_list); spa_list_init (&impl->source_list);
@ -600,6 +611,10 @@ pinos_loop_new (void)
spa_ringbuffer_init (&impl->buffer, DATAS_SIZE); spa_ringbuffer_init (&impl->buffer, DATAS_SIZE);
return this; return this;
no_epoll:
free (impl);
return NULL;
} }
void void

View file

@ -91,14 +91,14 @@ pinos_memblock_alloc (PinosMemblockFlags flags,
mem->fd = memfd_create ("pinos-memfd", MFD_CLOEXEC | MFD_ALLOW_SEALING); mem->fd = memfd_create ("pinos-memfd", MFD_CLOEXEC | MFD_ALLOW_SEALING);
if (mem->fd == -1) { if (mem->fd == -1) {
pinos_log_error ("Failed to create memfd: %s\n", strerror (errno)); pinos_log_error ("Failed to create memfd: %s\n", strerror (errno));
return SPA_RESULT_ERROR; return SPA_RESULT_ERRNO;
} }
#else #else
char filename[] = "/dev/shm/spa-tmpfile.XXXXXX"; char filename[] = "/dev/shm/spa-tmpfile.XXXXXX";
mem->fd = mkostemp (filename, O_CLOEXEC); mem->fd = mkostemp (filename, O_CLOEXEC);
if (mem->fd == -1) { if (mem->fd == -1) {
pinos_log_error ("Failed to create temporary file: %s\n", strerror (errno)); pinos_log_error ("Failed to create temporary file: %s\n", strerror (errno));
return SPA_RESULT_ERROR; return SPA_RESULT_ERRNO;
} }
unlink (filename); unlink (filename);
#endif #endif
@ -106,7 +106,7 @@ pinos_memblock_alloc (PinosMemblockFlags flags,
if (ftruncate (mem->fd, size) < 0) { if (ftruncate (mem->fd, size) < 0) {
pinos_log_warn ("Failed to truncate temporary file: %s", strerror (errno)); pinos_log_warn ("Failed to truncate temporary file: %s", strerror (errno));
close (mem->fd); close (mem->fd);
return SPA_RESULT_ERROR; return SPA_RESULT_ERRNO;
} }
#ifdef USE_MEMFD #ifdef USE_MEMFD
if (flags & PINOS_MEMBLOCK_FLAG_SEAL) { if (flags & PINOS_MEMBLOCK_FLAG_SEAL) {
@ -125,11 +125,15 @@ pinos_memblock_alloc (PinosMemblockFlags flags,
prot |= PROT_WRITE; prot |= PROT_WRITE;
mem->ptr = mmap (NULL, size, prot, MAP_SHARED, mem->fd, 0); mem->ptr = mmap (NULL, size, prot, MAP_SHARED, mem->fd, 0);
if (mem->ptr == MAP_FAILED)
return SPA_RESULT_NO_MEMORY;
} else { } else {
mem->ptr = NULL; mem->ptr = NULL;
} }
} else { } else {
mem->ptr = malloc (size); mem->ptr = malloc (size);
if (mem->ptr == NULL)
return SPA_RESULT_NO_MEMORY;
mem->fd = -1; mem->fd = -1;
} }
return SPA_RESULT_OK; return SPA_RESULT_OK;

View file

@ -78,6 +78,9 @@ pinos_properties_new (const char *key, ...)
const char *value; const char *value;
impl = calloc (1, sizeof (PinosPropertiesImpl)); impl = calloc (1, sizeof (PinosPropertiesImpl));
if (impl == NULL)
return NULL;
pinos_array_init (&impl->items); pinos_array_init (&impl->items);
va_start (varargs, key); va_start (varargs, key);
@ -106,6 +109,9 @@ pinos_properties_new_dict (const SpaDict *dict)
PinosPropertiesImpl *impl; PinosPropertiesImpl *impl;
impl = calloc (1, sizeof (PinosPropertiesImpl)); impl = calloc (1, sizeof (PinosPropertiesImpl));
if (impl == NULL)
return NULL;
pinos_array_init (&impl->items); pinos_array_init (&impl->items);
for (i = 0; i < dict->n_items; i++) for (i = 0; i < dict->n_items; i++)
@ -130,6 +136,9 @@ pinos_properties_copy (PinosProperties *properties)
SpaDictItem *item; SpaDictItem *item;
copy = pinos_properties_new (NULL, NULL); copy = pinos_properties_new (NULL, NULL);
if (copy == NULL)
return NULL;
pinos_array_for_each (item, &impl->items) pinos_array_for_each (item, &impl->items)
add_func (copy, strdup (item->key), strdup (item->value)); add_func (copy, strdup (item->key), strdup (item->value));
@ -154,6 +163,9 @@ pinos_properties_merge (PinosProperties *oldprops,
void * state = NULL; void * state = NULL;
res = pinos_properties_copy (oldprops); res = pinos_properties_copy (oldprops);
if (res == NULL)
return NULL;
while ((key = pinos_properties_iterate (newprops, &state))) { while ((key = pinos_properties_iterate (newprops, &state))) {
pinos_properties_set (res, pinos_properties_set (res,
key, key,

View file

@ -33,6 +33,9 @@ pinos_proxy_new (PinosContext *context,
PinosProxy *this; PinosProxy *this;
impl = calloc (1, sizeof (PinosProxyImpl)); impl = calloc (1, sizeof (PinosProxyImpl));
if (impl == NULL)
return NULL;
this = &impl->this; this = &impl->this;
this->context = context; this->context = context;

View file

@ -64,6 +64,9 @@ pinos_rtkit_bus_get_system (void)
dbus_error_init(&error); dbus_error_init(&error);
bus = calloc (1, sizeof (PinosRTKitBus)); bus = calloc (1, sizeof (PinosRTKitBus));
if (bus == NULL)
return NULL;
bus->bus = dbus_bus_get_private (DBUS_BUS_SYSTEM, &error); bus->bus = dbus_bus_get_private (DBUS_BUS_SYSTEM, &error);
if (bus->bus == NULL) if (bus->bus == NULL)
goto error; goto error;

View file

@ -173,19 +173,25 @@ pinos_stream_new (PinosContext *context,
PinosStream *this; PinosStream *this;
impl = calloc (1, sizeof (PinosStreamImpl)); impl = calloc (1, sizeof (PinosStreamImpl));
if (impl == NULL)
return NULL;
this = &impl->this; this = &impl->this;
pinos_log_debug ("stream %p: new", impl); pinos_log_debug ("stream %p: new", impl);
this->context = context;
this->name = strdup (name);
if (props == NULL) { if (props == NULL) {
props = pinos_properties_new ("media.name", name, NULL); props = pinos_properties_new ("media.name", name, NULL);
} else if (!pinos_properties_get (props, "media.name")) { } else if (!pinos_properties_get (props, "media.name")) {
pinos_properties_set (props, "media.name", name); pinos_properties_set (props, "media.name", name);
} }
if (props == NULL)
goto no_mem;
this->properties = props; this->properties = props;
this->context = context;
this->name = strdup (name);
pinos_signal_init (&this->destroy_signal); pinos_signal_init (&this->destroy_signal);
pinos_signal_init (&this->state_changed); pinos_signal_init (&this->state_changed);
pinos_signal_init (&this->format_changed); pinos_signal_init (&this->format_changed);
@ -206,6 +212,10 @@ pinos_stream_new (PinosContext *context,
spa_list_insert (&context->stream_list, &this->link); spa_list_insert (&context->stream_list, &this->link);
return this; return this;
no_mem:
free (impl);
return NULL;
} }
void void

View file

@ -48,16 +48,6 @@ typedef enum {
PINOS_SUBSCRIPTION_EVENT_REMOVE = 2, PINOS_SUBSCRIPTION_EVENT_REMOVE = 2,
} PinosSubscriptionEvent; } PinosSubscriptionEvent;
typedef void (*PinosSubscriptionFunc) (PinosContext *context,
PinosSubscriptionEvent event,
uint32_t type,
uint32_t id,
void *data);
void pinos_context_subscribe (PinosContext *context,
PinosSubscriptionFunc func,
void *data);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -83,12 +83,14 @@ pinos_thread_main_loop_new (PinosLoop *loop,
pthread_mutexattr_t attr; pthread_mutexattr_t attr;
impl = calloc (1, sizeof (PinosThreadMainLoopImpl)); impl = calloc (1, sizeof (PinosThreadMainLoopImpl));
if (impl == NULL)
return NULL;
this = &impl->this; this = &impl->this;
pinos_log_debug ("thread-mainloop %p: new", impl); pinos_log_debug ("thread-mainloop %p: new", impl);
this->loop = loop; this->loop = loop;
if (name) this->name = name ? strdup (name) : NULL;
this->name = strdup (name);
pinos_loop_set_hooks (loop, pinos_loop_set_hooks (loop,
pre_hook, pre_hook,
@ -97,7 +99,6 @@ pinos_thread_main_loop_new (PinosLoop *loop,
pinos_signal_init (&this->destroy_signal); pinos_signal_init (&this->destroy_signal);
pthread_mutexattr_init (&attr); pthread_mutexattr_init (&attr);
pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE); pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init (&impl->lock, &attr); pthread_mutex_init (&impl->lock, &attr);

View file

@ -99,6 +99,9 @@ pinos_transport_new (unsigned int max_inputs,
area.n_outputs = 0; area.n_outputs = 0;
impl = calloc (1, sizeof (PinosTransportImpl)); impl = calloc (1, sizeof (PinosTransportImpl));
if (impl == NULL)
return NULL;
impl->offset = 0; impl->offset = 0;
trans = &impl->trans; trans = &impl->trans;
@ -124,6 +127,9 @@ pinos_transport_new_from_info (PinosTransportInfo *info)
void *tmp; void *tmp;
impl = calloc (1, sizeof (PinosTransportImpl)); impl = calloc (1, sizeof (PinosTransportImpl));
if (impl == NULL)
return NULL;
trans = &impl->trans; trans = &impl->trans;
pinos_signal_init (&trans->destroy_signal); pinos_signal_init (&trans->destroy_signal);

View file

@ -254,14 +254,14 @@ find_device (GstDeviceProvider *provider, uint32_t id)
} }
static void static void
context_subscribe_cb (PinosContext *context, on_context_subscription (PinosListener *listener,
PinosContext *context,
PinosSubscriptionEvent event, PinosSubscriptionEvent event,
uint32_t type, uint32_t type,
uint32_t id, uint32_t id)
void *user_data)
{ {
GstPinosDeviceProvider *self = user_data; GstPinosDeviceProvider *self = SPA_CONTAINER_OF (listener, GstPinosDeviceProvider, ctx_subscription);
GstDeviceProvider *provider = user_data; GstDeviceProvider *provider = GST_DEVICE_PROVIDER (self);
GstPinosDevice *dev; GstPinosDevice *dev;
if (type != context->uri.node) if (type != context->uri.node)
@ -442,11 +442,12 @@ gst_pinos_device_provider_start (GstDeviceProvider * provider)
goto failed_context; goto failed_context;
} }
pinos_signal_add (&self->context->state_changed, &self->ctx_state_changed, on_context_state_changed); pinos_signal_add (&self->context->state_changed,
&self->ctx_state_changed,
pinos_context_subscribe (self->context, on_context_state_changed);
context_subscribe_cb, pinos_signal_add (&self->context->subscription,
self); &self->ctx_subscription,
on_context_subscription);
pinos_context_connect (self->context); pinos_context_connect (self->context);
for (;;) { for (;;) {

View file

@ -85,6 +85,7 @@ struct _GstPinosDeviceProvider {
PinosContext *context; PinosContext *context;
PinosListener ctx_state_changed; PinosListener ctx_state_changed;
PinosListener ctx_subscription;
}; };
struct _GstPinosDeviceProviderClass { struct _GstPinosDeviceProviderClass {

View file

@ -111,28 +111,31 @@ on_link_state_changed (PinosListener *listener,
switch (state) { switch (state) {
case PINOS_LINK_STATE_ERROR: case PINOS_LINK_STATE_ERROR:
{ {
PinosResource *resource;
pinos_log_debug ("module %p: link %p: state error: %s", impl, link, link->error); pinos_log_debug ("module %p: link %p: state error: %s", impl, link, link->error);
spa_list_for_each (resource, &link->resource_list, link) {
pinos_resource_send_error (resource,
SPA_RESULT_ERROR,
link->error);
}
#if 0
if (link->input && link->input->node) if (link->input && link->input->node)
pinos_node_update_state (link->input->node, PINOS_NODE_STATE_ERROR, strdup (link->error)); pinos_node_update_state (link->input->node, PINOS_NODE_STATE_ERROR, strdup (link->error));
if (link->output && link->output->node) if (link->output && link->output->node)
pinos_node_update_state (link->output->node, PINOS_NODE_STATE_ERROR, strdup (link->error)); pinos_node_update_state (link->output->node, PINOS_NODE_STATE_ERROR, strdup (link->error));
#endif
break; break;
} }
case PINOS_LINK_STATE_UNLINKED: case PINOS_LINK_STATE_UNLINKED:
pinos_log_debug ("module %p: link %p: unlinked", impl, link); pinos_log_debug ("module %p: link %p: unlinked", impl, link);
#if 0 #if 0
g_set_error (&error,
PINOS_ERROR,
PINOS_ERROR_NODE_LINK,
"error node unlinked");
if (link->input && link->input->node) if (link->input && link->input->node)
pinos_node_report_error (link->input->node, g_error_copy (error)); pinos_node_update_state (link->input->node, PINOS_NODE_STATE_ERROR, strdup ("node unlinked"));
if (link->output && link->output->node) if (link->output && link->output->node)
pinos_node_report_error (link->output->node, g_error_copy (error)); pinos_node_update_state (link->output->node, PINOS_NODE_STATE_ERROR, strdup ("node unlinked"));
#endif #endif
break; break;

View file

@ -1234,6 +1234,9 @@ pinos_client_node_new (PinosClient *client,
PinosClientNode *this; PinosClientNode *this;
impl = calloc (1, sizeof (PinosClientNodeImpl)); impl = calloc (1, sizeof (PinosClientNodeImpl));
if (impl == NULL)
return NULL;
this = &impl->this; this = &impl->this;
impl->core = client->core; impl->core = client->core;
impl->data_fd = -1; impl->data_fd = -1;
@ -1248,6 +1251,8 @@ pinos_client_node_new (PinosClient *client,
&impl->proxy.node, &impl->proxy.node,
NULL, NULL,
properties); properties);
if (this->node == NULL)
goto error_no_node;
impl->proxy.pnode = this->node; impl->proxy.pnode = this->node;
@ -1264,12 +1269,21 @@ pinos_client_node_new (PinosClient *client,
client->core->uri.client_node, client->core->uri.client_node,
this, this,
(PinosDestroy) client_node_resource_destroy); (PinosDestroy) client_node_resource_destroy);
impl->proxy.resource = this->resource; if (this->resource == NULL)
goto error_no_resource;
impl->proxy.resource = this->resource;
this->resource->dispatch_func = client_node_dispatch_func; this->resource->dispatch_func = client_node_dispatch_func;
this->resource->dispatch_data = this; this->resource->dispatch_data = this;
return this; return this;
error_no_resource:
pinos_node_destroy (this->node);
error_no_node:
proxy_clear (&impl->proxy);
free (impl);
return NULL;
} }
static void static void

View file

@ -69,6 +69,8 @@ client_bind_func (PinosGlobal *global,
global->core->uri.client, global->core->uri.client,
global->object, global->object,
client_unbind_func); client_unbind_func);
if (resource == NULL)
goto no_mem;
resource->dispatch_func = client_dispatch_func; resource->dispatch_func = client_dispatch_func;
resource->dispatch_data = global; resource->dispatch_data = global;
@ -86,6 +88,12 @@ client_bind_func (PinosGlobal *global,
PINOS_MESSAGE_CLIENT_INFO, PINOS_MESSAGE_CLIENT_INFO,
&m, &m,
true); true);
return;
no_mem:
pinos_resource_send_error (client->core_resource,
SPA_RESULT_NO_MEMORY,
"no memory");
} }
/** /**
@ -105,6 +113,9 @@ pinos_client_new (PinosCore *core,
PinosClientImpl *impl; PinosClientImpl *impl;
impl = calloc (1, sizeof (PinosClientImpl)); impl = calloc (1, sizeof (PinosClientImpl));
if (impl == NULL)
return NULL;
pinos_log_debug ("client %p: new", impl); pinos_log_debug ("client %p: new", impl);
this = &impl->this; this = &impl->this;

View file

@ -68,6 +68,8 @@ parse_command_module_load (const char * line, char ** err)
PinosCommandImpl *impl; PinosCommandImpl *impl;
impl = calloc (1, sizeof (PinosCommandImpl)); impl = calloc (1, sizeof (PinosCommandImpl));
if (impl == NULL)
goto no_mem;
impl->func = execute_command_module_load; impl->func = execute_command_module_load;
impl->args = pinos_split_strv (line, whitespace, 3, &impl->n_args); impl->args = pinos_split_strv (line, whitespace, 3, &impl->n_args);
@ -83,6 +85,9 @@ no_module:
asprintf (err, "%s requires a module name", impl->args[0]); asprintf (err, "%s requires a module name", impl->args[0]);
pinos_free_strv (impl->args); pinos_free_strv (impl->args);
return NULL; return NULL;
no_mem:
asprintf (err, "no memory");
return NULL;
} }
static bool static bool

View file

@ -51,15 +51,19 @@ registry_dispatch_func (void *object,
break; break;
if (&global->link == &this->global_list) { if (&global->link == &this->global_list) {
pinos_log_error ("unknown object id %d", m->id); pinos_resource_send_error (resource,
SPA_RESULT_INVALID_OBJECT_ID,
"unknown object id %u", m->id);
return SPA_RESULT_ERROR; return SPA_RESULT_ERROR;
} }
if (global->bind == NULL) { if (global->bind == NULL) {
pinos_log_error ("can't bind object id %d", m->id); pinos_resource_send_error (resource,
SPA_RESULT_NOT_IMPLEMENTED,
"can't bind object id %d", m->id);
return SPA_RESULT_ERROR; return SPA_RESULT_ERROR;
} }
pinos_log_error ("global %p: bind object id %d", global, m->id); pinos_log_debug ("global %p: bind object id %d", global, m->id);
global->bind (global, client, 0, m->id); global->bind (global, client, 0, m->id);
break; break;
} }
@ -109,6 +113,8 @@ core_dispatch_func (void *object,
this->uri.registry, this->uri.registry,
this, this,
destroy_registry_resource); destroy_registry_resource);
if (registry_resource == NULL)
goto no_mem;
registry_resource->dispatch_func = registry_dispatch_func; registry_resource->dispatch_func = registry_dispatch_func;
registry_resource->dispatch_data = this; registry_resource->dispatch_data = this;
@ -142,6 +148,9 @@ core_dispatch_func (void *object,
PinosProperties *props; PinosProperties *props;
props = pinos_properties_new (NULL, NULL); props = pinos_properties_new (NULL, NULL);
if (props == NULL)
goto no_mem;
for (i = 0; i < m->props->n_items; i++) { for (i = 0; i < m->props->n_items; i++) {
pinos_properties_set (props, m->props->items[i].key, pinos_properties_set (props, m->props->items[i].key,
m->props->items[i].value); m->props->items[i].value);
@ -151,9 +160,13 @@ core_dispatch_func (void *object,
m->new_id, m->new_id,
m->name, m->name,
props); props);
if (node == NULL)
goto no_mem;
if ((res = pinos_client_node_get_data_socket (node, &data_fd)) < 0) { if ((res = pinos_client_node_get_data_socket (node, &data_fd)) < 0) {
pinos_log_error ("can't get data fd"); pinos_resource_send_error (resource,
SPA_RESULT_ERROR,
"can't get data fd");
break; break;
} }
@ -170,6 +183,12 @@ core_dispatch_func (void *object,
break; break;
} }
return SPA_RESULT_OK; return SPA_RESULT_OK;
no_mem:
pinos_resource_send_error (resource,
SPA_RESULT_NO_MEMORY,
"no memory");
return SPA_RESULT_NO_MEMORY;
} }
static void static void
@ -188,6 +207,8 @@ core_bind_func (PinosGlobal *global,
global->core->uri.core, global->core->uri.core,
global->object, global->object,
NULL); NULL);
if (resource == NULL)
goto no_mem;
resource->dispatch_func = core_dispatch_func; resource->dispatch_func = core_dispatch_func;
resource->dispatch_data = this; resource->dispatch_data = this;
@ -211,6 +232,10 @@ core_bind_func (PinosGlobal *global,
PINOS_MESSAGE_CORE_INFO, PINOS_MESSAGE_CORE_INFO,
&m, &m,
true); true);
return;
no_mem:
pinos_log_error ("can't create core resource");
} }
PinosCore * PinosCore *
@ -220,14 +245,19 @@ pinos_core_new (PinosMainLoop *main_loop)
PinosCore *this; PinosCore *this;
impl = calloc (1, sizeof (PinosCoreImpl)); impl = calloc (1, sizeof (PinosCoreImpl));
if (impl == NULL)
return NULL;
this = &impl->this; this = &impl->this;
pinos_uri_init (&this->uri);
pinos_map_init (&this->objects, 512);
this->data_loop = pinos_data_loop_new (); this->data_loop = pinos_data_loop_new ();
if (this->data_loop == NULL)
goto no_data_loop;
this->main_loop = main_loop; this->main_loop = main_loop;
pinos_uri_init (&this->uri);
pinos_map_init (&this->objects, 512);
impl->support[0].uri = SPA_ID_MAP_URI; impl->support[0].uri = SPA_ID_MAP_URI;
impl->support[0].data = this->uri.map; impl->support[0].data = this->uri.map;
impl->support[1].uri = SPA_LOG_URI; impl->support[1].uri = SPA_LOG_URI;
@ -266,6 +296,10 @@ pinos_core_new (PinosMainLoop *main_loop)
core_bind_func); core_bind_func);
return this; return this;
no_data_loop:
free (impl);
return NULL;
} }
void void
@ -292,6 +326,9 @@ pinos_core_add_global (PinosCore *core,
PinosMessageNotifyGlobal ng; PinosMessageNotifyGlobal ng;
global = calloc (1, sizeof (PinosGlobal)); global = calloc (1, sizeof (PinosGlobal));
if (global == NULL)
return NULL;
global->core = core; global->core = core;
global->type = type; global->type = type;
global->version = version; global->version = version;

View file

@ -131,16 +131,26 @@ pinos_data_loop_new (void)
PinosDataLoop *this; PinosDataLoop *this;
impl = calloc (1, sizeof (PinosDataLoopImpl)); impl = calloc (1, sizeof (PinosDataLoopImpl));
if (impl == NULL)
return NULL;
pinos_log_debug ("data-loop %p: new", impl); pinos_log_debug ("data-loop %p: new", impl);
this = &impl->this; this = &impl->this;
this->loop = pinos_loop_new (); this->loop = pinos_loop_new ();
if (this->loop == NULL)
goto no_loop;
pinos_signal_init (&this->destroy_signal); pinos_signal_init (&this->destroy_signal);
impl->event = pinos_loop_add_event (this->loop, impl->event = pinos_loop_add_event (this->loop,
do_stop, do_stop,
impl); impl);
return this; return this;
no_loop:
free (impl);
return NULL;
} }
void void

View file

@ -49,28 +49,23 @@ typedef struct
} PinosLinkImpl; } PinosLinkImpl;
static void static void
pinos_link_update_state (PinosLink *link, PinosLinkState state) pinos_link_update_state (PinosLink *link,
PinosLinkState state,
char *error)
{ {
if (state != link->state) { if (state != link->state) {
free (link->error);
link->error = NULL;
pinos_log_debug ("link %p: update state %s -> %s", link, pinos_log_debug ("link %p: update state %s -> %s", link,
pinos_link_state_as_string (link->state), pinos_link_state_as_string (link->state),
pinos_link_state_as_string (state)); pinos_link_state_as_string (state));
link->state = state;
pinos_signal_emit (&link->core->link_state_changed, link);
}
}
static void link->state = state;
pinos_link_report_error (PinosLink *link, char *error) if (link->error)
{
free (link->error); free (link->error);
link->error = error; link->error = error;
link->state = PINOS_LINK_STATE_ERROR;
pinos_log_debug ("link %p: got error state %s", link, error);
pinos_signal_emit (&link->core->link_state_changed, link); pinos_signal_emit (&link->core->link_state_changed, link);
} }
}
static SpaResult static SpaResult
do_negotiate (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state) do_negotiate (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
@ -83,7 +78,7 @@ do_negotiate (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
if (in_state != SPA_NODE_STATE_CONFIGURE && out_state != SPA_NODE_STATE_CONFIGURE) if (in_state != SPA_NODE_STATE_CONFIGURE && out_state != SPA_NODE_STATE_CONFIGURE)
return SPA_RESULT_OK; return SPA_RESULT_OK;
pinos_link_update_state (this, PINOS_LINK_STATE_NEGOTIATING); pinos_link_update_state (this, PINOS_LINK_STATE_NEGOTIATING, NULL);
/* both ports need a format */ /* both ports need a format */
if (in_state == SPA_NODE_STATE_CONFIGURE && out_state == SPA_NODE_STATE_CONFIGURE) { if (in_state == SPA_NODE_STATE_CONFIGURE && out_state == SPA_NODE_STATE_CONFIGURE) {
@ -170,7 +165,7 @@ again:
error: error:
{ {
pinos_link_report_error (this, error); pinos_link_update_state (this, PINOS_LINK_STATE_ERROR, error);
return res; return res;
} }
} }
@ -352,7 +347,7 @@ do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
if (in_state != SPA_NODE_STATE_READY && out_state != SPA_NODE_STATE_READY) if (in_state != SPA_NODE_STATE_READY && out_state != SPA_NODE_STATE_READY)
return SPA_RESULT_OK; return SPA_RESULT_OK;
pinos_link_update_state (this, PINOS_LINK_STATE_ALLOCATING); pinos_link_update_state (this, PINOS_LINK_STATE_ALLOCATING, NULL);
pinos_log_debug ("link %p: doing alloc buffers %p %p", this, this->output->node, this->input->node); pinos_log_debug ("link %p: doing alloc buffers %p %p", this, this->output->node, this->input->node);
/* find out what's possible */ /* find out what's possible */
@ -552,7 +547,7 @@ error:
this->input->buffers = NULL; this->input->buffers = NULL;
this->input->n_buffers = 0; this->input->n_buffers = 0;
this->input->allocated = false; this->input->allocated = false;
pinos_link_report_error (this, error); pinos_link_update_state (this, PINOS_LINK_STATE_ERROR, error);
return res; return res;
} }
} }
@ -565,9 +560,9 @@ do_start (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
if (in_state < SPA_NODE_STATE_PAUSED || out_state < SPA_NODE_STATE_PAUSED) if (in_state < SPA_NODE_STATE_PAUSED || out_state < SPA_NODE_STATE_PAUSED)
return SPA_RESULT_OK; return SPA_RESULT_OK;
else if (in_state == SPA_NODE_STATE_STREAMING && out_state == SPA_NODE_STATE_STREAMING) { else if (in_state == SPA_NODE_STATE_STREAMING && out_state == SPA_NODE_STATE_STREAMING) {
pinos_link_update_state (this, PINOS_LINK_STATE_RUNNING); pinos_link_update_state (this, PINOS_LINK_STATE_RUNNING, NULL);
} else { } else {
pinos_link_update_state (this, PINOS_LINK_STATE_PAUSED); pinos_link_update_state (this, PINOS_LINK_STATE_PAUSED, NULL);
if (in_state == SPA_NODE_STATE_PAUSED) { if (in_state == SPA_NODE_STATE_PAUSED) {
res = pinos_node_set_state (this->input->node, PINOS_NODE_STATE_RUNNING); res = pinos_node_set_state (this->input->node, PINOS_NODE_STATE_RUNNING);
@ -587,9 +582,16 @@ check_states (PinosLink *this,
SpaNodeState in_state, out_state; SpaNodeState in_state, out_state;
again: again:
if (this->state == PINOS_LINK_STATE_ERROR)
return SPA_RESULT_ERROR;
if (this->input == NULL || this->output == NULL) if (this->input == NULL || this->output == NULL)
return SPA_RESULT_OK; return SPA_RESULT_OK;
if (this->input->node->state == PINOS_NODE_STATE_ERROR ||
this->output->node->state == PINOS_NODE_STATE_ERROR)
return SPA_RESULT_ERROR;
in_state = this->input->node->node->state; in_state = this->input->node->node->state;
out_state = this->output->node->node->state; out_state = this->output->node->node->state;
@ -652,7 +654,7 @@ on_port_unlinked (PinosPort *port, PinosLink *this, SpaResult res, uint32_t id)
pinos_signal_emit (&this->core->port_unlinked, this, port); pinos_signal_emit (&this->core->port_unlinked, this, port);
if (this->input == NULL || this->output == NULL) { if (this->input == NULL || this->output == NULL) {
pinos_link_update_state (this, PINOS_LINK_STATE_UNLINKED); pinos_link_update_state (this, PINOS_LINK_STATE_UNLINKED, NULL);
pinos_link_destroy (this); pinos_link_destroy (this);
} }
@ -719,7 +721,11 @@ bool
pinos_link_activate (PinosLink *this) pinos_link_activate (PinosLink *this)
{ {
spa_ringbuffer_init (&this->ringbuffer, SPA_N_ELEMENTS (this->queue)); spa_ringbuffer_init (&this->ringbuffer, SPA_N_ELEMENTS (this->queue));
check_states (this, NULL, SPA_RESULT_OK); pinos_main_loop_defer (this->core->main_loop,
this,
SPA_RESULT_WAIT_SYNC,
(PinosDeferFunc) check_states,
this);
return true; return true;
} }
@ -766,6 +772,8 @@ link_bind_func (PinosGlobal *global,
global->core->uri.link, global->core->uri.link,
global->object, global->object,
link_unbind_func); link_unbind_func);
if (resource == NULL)
goto no_mem;
resource->dispatch_func = link_dispatch_func; resource->dispatch_func = link_dispatch_func;
resource->dispatch_data = global; resource->dispatch_data = global;
@ -785,6 +793,12 @@ link_bind_func (PinosGlobal *global,
PINOS_MESSAGE_LINK_INFO, PINOS_MESSAGE_LINK_INFO,
&m, &m,
true); true);
return;
no_mem:
pinos_resource_send_error (client->core_resource,
SPA_RESULT_NO_MEMORY,
"no memory");
} }
PinosLink * PinosLink *
@ -798,6 +812,9 @@ pinos_link_new (PinosCore *core,
PinosLink *this; PinosLink *this;
impl = calloc (1, sizeof (PinosLinkImpl)); impl = calloc (1, sizeof (PinosLinkImpl));
if (impl == NULL)
return NULL;
this = &impl->this; this = &impl->this;
pinos_log_debug ("link %p: new", this); pinos_log_debug ("link %p: new", this);

View file

@ -97,6 +97,8 @@ main_loop_defer (PinosMainLoop *loop,
spa_list_remove (&item->link); spa_list_remove (&item->link);
} else { } else {
item = malloc (sizeof (WorkItem)); item = malloc (sizeof (WorkItem));
if (item == NULL)
return SPA_ID_INVALID;
} }
item->id = ++impl->counter; item->id = ++impl->counter;
item->obj = obj; item->obj = obj;
@ -189,10 +191,15 @@ pinos_main_loop_new (void)
PinosMainLoop *this; PinosMainLoop *this;
impl = calloc (1, sizeof (PinosMainLoopImpl)); impl = calloc (1, sizeof (PinosMainLoopImpl));
if (impl == NULL)
return NULL;
pinos_log_debug ("main-loop %p: new", impl); pinos_log_debug ("main-loop %p: new", impl);
this = &impl->this; this = &impl->this;
this->loop = pinos_loop_new (); this->loop = pinos_loop_new ();
if (this->loop == NULL)
goto no_loop;
pinos_signal_init (&this->destroy_signal); pinos_signal_init (&this->destroy_signal);
@ -208,6 +215,10 @@ pinos_main_loop_new (void)
spa_list_init (&impl->free_list); spa_list_init (&impl->free_list);
return this; return this;
no_loop:
free (impl);
return NULL;
} }
void void

View file

@ -123,6 +123,8 @@ module_bind_func (PinosGlobal *global,
global->core->uri.module, global->core->uri.module,
global->object, global->object,
NULL); NULL);
if (resource == NULL)
goto no_mem;
resource->dispatch_func = module_dispatch_func; resource->dispatch_func = module_dispatch_func;
resource->dispatch_data = global; resource->dispatch_data = global;
@ -141,6 +143,12 @@ module_bind_func (PinosGlobal *global,
PINOS_MESSAGE_MODULE_INFO, PINOS_MESSAGE_MODULE_INFO,
&m, &m,
true); true);
return;
no_mem:
pinos_resource_send_error (resource,
SPA_RESULT_NO_MEMORY,
"no memory");
} }
/** /**
@ -201,6 +209,9 @@ pinos_module_load (PinosCore *core,
goto no_pinos_module; goto no_pinos_module;
impl = calloc (1, sizeof (PinosModuleImpl)); impl = calloc (1, sizeof (PinosModuleImpl));
if (impl == NULL)
goto no_mem;
impl->hnd = hnd; impl->hnd = hnd;
this = &impl->this; this = &impl->this;
@ -229,10 +240,11 @@ not_found:
} }
open_failed: open_failed:
{ {
asprintf (err, "Failed to open module: %s", dlerror ()); asprintf (err, "Failed to open module: \"%s\" %s", filename, dlerror ());
free (filename); free (filename);
return NULL; return NULL;
} }
no_mem:
no_pinos_module: no_pinos_module:
{ {
asprintf (err, "\"%s\" is not a pinos module", name); asprintf (err, "\"%s\" is not a pinos module", name);

View file

@ -422,6 +422,8 @@ node_bind_func (PinosGlobal *global,
global->core->uri.registry, global->core->uri.registry,
global->object, global->object,
node_unbind_func); node_unbind_func);
if (resource == NULL)
goto no_mem;
resource->dispatch_func = node_dispatch_func; resource->dispatch_func = node_dispatch_func;
resource->dispatch_data = global; resource->dispatch_data = global;
@ -435,12 +437,19 @@ node_bind_func (PinosGlobal *global,
info.change_mask = ~0; info.change_mask = ~0;
info.name = this->name; info.name = this->name;
info.state = this->state; info.state = this->state;
info.error = this->error;
info.props = this->properties ? &this->properties->dict : NULL; info.props = this->properties ? &this->properties->dict : NULL;
pinos_resource_send_message (resource, pinos_resource_send_message (resource,
PINOS_MESSAGE_NODE_INFO, PINOS_MESSAGE_NODE_INFO,
&m, &m,
true); true);
return;
no_mem:
pinos_resource_send_error (resource,
SPA_RESULT_NO_MEMORY,
"no memory");
} }
static void static void
@ -482,6 +491,9 @@ pinos_node_new (PinosCore *core,
PinosNode *this; PinosNode *this;
impl = calloc (1, sizeof (PinosNodeImpl)); impl = calloc (1, sizeof (PinosNodeImpl));
if (impl == NULL)
return NULL;
this = &impl->this; this = &impl->this;
this->core = core; this->core = core;
pinos_log_debug ("node %p: new", this); pinos_log_debug ("node %p: new", this);
@ -514,6 +526,9 @@ pinos_node_new (PinosCore *core,
if (this->properties == NULL) if (this->properties == NULL)
this->properties = pinos_properties_new (NULL, NULL); this->properties = pinos_properties_new (NULL, NULL);
if (this->properties)
goto no_mem;
for (i = 0; i < this->node->info->n_items; i++) for (i = 0; i < this->node->info->n_items; i++)
pinos_properties_set (this->properties, pinos_properties_set (this->properties,
this->node->info->items[i].key, this->node->info->items[i].key,
@ -532,6 +547,11 @@ pinos_node_new (PinosCore *core,
} }
return this; return this;
no_mem:
free (this->name);
free (impl);
return NULL;
} }
static SpaResult static SpaResult
@ -814,6 +834,7 @@ pinos_node_update_state (PinosNode *node,
m.info = &info; m.info = &info;
info.change_mask = 1 << 1; info.change_mask = 1 << 1;
info.state = node->state; info.state = node->state;
info.error = node->error;
spa_list_for_each (resource, &node->resource_list, link) { spa_list_for_each (resource, &node->resource_list, link) {
info.id = node->global->id; info.id = node->global->id;

View file

@ -41,6 +41,9 @@ pinos_port_new (PinosNode *node,
PinosPort *this; PinosPort *this;
impl = calloc (1, sizeof (PinosPortImpl)); impl = calloc (1, sizeof (PinosPortImpl));
if (impl == NULL)
return NULL;
this = &impl->this; this = &impl->this;
this->node = node; this->node = node;
this->direction = direction; this->direction = direction;
@ -177,6 +180,8 @@ pinos_port_link (PinosPort *output_port,
input_port, input_port,
format_filter, format_filter,
properties); properties);
if (link == NULL)
goto no_mem;
spa_list_insert (output_port->links.prev, &link->output_link); spa_list_insert (output_port->links.prev, &link->output_link);
spa_list_insert (input_port->links.prev, &link->input_link); spa_list_insert (input_port->links.prev, &link->input_link);
@ -209,6 +214,8 @@ was_linked:
asprintf (error, "input port was already linked"); asprintf (error, "input port was already linked");
return NULL; return NULL;
} }
no_mem:
return NULL;
} }
static SpaResult static SpaResult

View file

@ -31,6 +31,9 @@ pinos_resource_new (PinosClient *client,
PinosResource *this; PinosResource *this;
this = calloc (1, sizeof (PinosResource)); this = calloc (1, sizeof (PinosResource));
if (this == NULL)
return NULL;
this->core = client->core; this->core = client->core;
this->client = client; this->client = client;
this->id = id; this->id = id;
@ -95,15 +98,42 @@ pinos_resource_send_message (PinosResource *resource,
void *message, void *message,
bool flush) bool flush)
{ {
if (resource->send_func) if (!resource->send_func) {
pinos_log_error ("resource %p: send func not implemented", resource);
return SPA_RESULT_NOT_IMPLEMENTED;
}
return resource->send_func (resource, return resource->send_func (resource,
resource->id, resource->id,
opcode, opcode,
message, message,
flush, flush,
resource->send_data); resource->send_data);
}
pinos_log_error ("resource %p: send func not implemented", resource);
SpaResult
return SPA_RESULT_NOT_IMPLEMENTED; pinos_resource_send_error (PinosResource *resource,
SpaResult res,
const char *message,
...)
{
PinosClient *client = resource->client;
PinosMessageError m;
char buffer[128];
va_list ap;
va_start (ap, message);
vsnprintf (buffer, sizeof (buffer), message, ap);
va_end (ap);
m.id = resource->id;
m.res = res;
m.error = buffer;
pinos_log_error ("resource %p: %u send error %d %s", resource, resource->id, res, buffer);
return pinos_resource_send_message (client->core_resource,
PINOS_MESSAGE_ERROR,
&m,
true);
} }

View file

@ -76,6 +76,9 @@ SpaResult pinos_resource_send_message (PinosResource *resource,
uint32_t opcode, uint32_t opcode,
void *message, void *message,
bool flush); bool flush);
SpaResult pinos_resource_send_error (PinosResource *resource,
SpaResult res,
const char *message, ...);
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -28,6 +28,7 @@ typedef struct {
PinosContext *context; PinosContext *context;
PinosListener on_state_changed; PinosListener on_state_changed;
PinosListener on_subscription;
} Data; } Data;
static void static void
@ -110,7 +111,11 @@ dump_node_info (PinosContext *c,
printf ("\ttype: %s\n", PINOS_NODE_URI); printf ("\ttype: %s\n", PINOS_NODE_URI);
if (data->print_all) { if (data->print_all) {
printf ("%c\tname: \"%s\"\n", MARK_CHANGE (0), info->name); printf ("%c\tname: \"%s\"\n", MARK_CHANGE (0), info->name);
printf ("%c\tstate: \"%s\"\n", MARK_CHANGE (1), pinos_node_state_as_string (info->state)); printf ("%c\tstate: \"%s\"", MARK_CHANGE (1), pinos_node_state_as_string (info->state));
if (info->state == PINOS_NODE_STATE_ERROR && info->error)
printf (" \"%s\"\n", info->error);
else
printf ("\n");
print_properties (info->props, MARK_CHANGE (2)); print_properties (info->props, MARK_CHANGE (2));
} }
} }
@ -202,11 +207,11 @@ dump_object (PinosContext *context,
} }
static void static void
subscription_cb (PinosContext *context, on_subscription (PinosListener *listener,
PinosContext *context,
PinosSubscriptionEvent event, PinosSubscriptionEvent event,
uint32_t type, uint32_t type,
uint32_t id, uint32_t id)
void *data)
{ {
DumpData dd; DumpData dd;
@ -267,9 +272,9 @@ main (int argc, char *argv[])
&data.on_state_changed, &data.on_state_changed,
on_state_changed); on_state_changed);
pinos_context_subscribe (data.context, pinos_signal_add (&data.context->subscription,
subscription_cb, &data.on_subscription,
&data); on_subscription);
pinos_context_connect (data.context); pinos_context_connect (data.context);

View file

@ -66,6 +66,7 @@ typedef enum {
SPA_RESULT_WRONG_STATE = -29, SPA_RESULT_WRONG_STATE = -29,
SPA_RESULT_ASYNC_BUSY = -30, SPA_RESULT_ASYNC_BUSY = -30,
SPA_RESULT_INVALID_OBJECT_ID = -31, SPA_RESULT_INVALID_OBJECT_ID = -31,
SPA_RESULT_NO_MEMORY = -32,
} SpaResult; } SpaResult;
#define SPA_ASYNC_MASK (3 << 30) #define SPA_ASYNC_MASK (3 << 30)