Browse Source

add property change notifications

tags/0.124.0
Paul Davis 12 years ago
parent
commit
3057fcf157
7 changed files with 180 additions and 14 deletions
  1. +1
    -1
      include/engine.h
  2. +10
    -3
      include/internal.h
  3. +103
    -5
      jackd/engine.c
  4. +39
    -4
      libjack/client.c
  5. +24
    -0
      libjack/metadata.c
  6. +2
    -0
      libjack/transclient.c
  7. +1
    -1
      tools

+ 1
- 1
include/engine.h View File

@@ -254,7 +254,7 @@ int jack_stop_freewheeling (jack_engine_t* engine, int engine_exiting);
jack_client_internal_t *
jack_client_by_name (jack_engine_t *engine, const char *name);

int jack_deliver_event (jack_engine_t *, jack_client_internal_t *, jack_event_t *);
int jack_deliver_event (jack_engine_t *, jack_client_internal_t *, jack_event_t *, ...);

void
jack_engine_signal_problems (jack_engine_t* engine);


+ 10
- 3
include/internal.h View File

@@ -223,7 +223,7 @@ typedef enum {
ClientUnregistered,
SaveSession,
LatencyCallback,
PropertyCallback
PropertyChange
} JackEventType;

const char* jack_event_type_name (JackEventType);
@@ -235,7 +235,7 @@ typedef struct {
char name[JACK_PORT_NAME_SIZE];
jack_port_id_t port_id;
jack_port_id_t self_id;
jack_uuid_t property_owner;
jack_uuid_t uuid;
} x;
union {
uint32_t n;
@@ -394,7 +394,8 @@ typedef enum {
GetUUIDByClientName = 27,
ReserveName = 30,
SessionReply = 31,
SessionHasCallback = 32
SessionHasCallback = 32,
PropertyChangeNotify = 33
} RequestType;

struct _jack_request {
@@ -448,6 +449,12 @@ struct _jack_request {
char path[PATH_MAX+1];
char init[JACK_LOAD_INIT_LIMIT];
} POST_PACKED_STRUCTURE intclient;
struct {
jack_property_change_t change;
jack_uuid_t uuid;
size_t keylen;
const char* key; /* not delivered inline to server, see oop_client_deliver_request() */
} POST_PACKED_STRUCTURE property;
jack_uuid_t client_id;
jack_nframes_t nframes;
jack_time_t timeout;


+ 103
- 5
jackd/engine.c View File

@@ -141,6 +141,7 @@ static void jack_do_reserve_name (jack_engine_t *engine, jack_request_t *req);
static void jack_do_session_reply (jack_engine_t *engine, jack_request_t *req );
static void jack_compute_new_latency (jack_engine_t *engine);
static int jack_do_has_session_cb (jack_engine_t *engine, jack_request_t *req);
static void jack_property_change_notify (jack_engine_t *engine, jack_property_change_t change, jack_uuid_t uuid, const char* key);

static inline int
jack_rolling_interval (jack_time_t period_usecs)
@@ -1193,7 +1194,7 @@ do_request (jack_engine_t *engine, jack_request_t *req, int *reply_fd)
*/
pthread_mutex_lock (&engine->request_lock);

DEBUG ("got a request of type %d", req->type);
DEBUG ("got a request of type %d (%s)", req->type, jack_event_type_name (req->type));

switch (req->type) {
case RegisterPort:
@@ -1355,12 +1356,17 @@ do_request (jack_engine_t *engine, jack_request_t *req, int *reply_fd)
jack_rdlock_graph (engine);
req->status = jack_do_has_session_cb (engine, req);
jack_unlock_graph (engine);
break;
case PropertyChangeNotify:
jack_property_change_notify (engine, req->x.property.change, req->x.property.uuid, req->x.property.key);
break;

default:
/* some requests are handled entirely on the client
* side, by adjusting the shared memory area(s) */
break;
}
pthread_mutex_unlock (&engine->request_lock);

DEBUG ("status of request: %d", req->status);
@@ -1423,12 +1429,29 @@ handle_external_client_request (jack_engine_t *engine, int fd)
}
}

if (req.type == PropertyChangeNotify) {
if (req.x.property.keylen) {
req.x.property.key = (char*) malloc (req.x.property.keylen);
if ((r = read (client->request_fd, (char*) req.x.property.key, req.x.property.keylen)) != req.x.property.keylen) {
jack_error ("cannot read property key from client (%d/%d/%s)",
r, sizeof(req), strerror (errno));
return -1;
}
} else {
req.x.property.key = 0;
}
}

reply_fd = client->request_fd;
jack_unlock_graph (engine);
do_request (engine, &req, &reply_fd);
jack_lock_graph (engine);

if (req.type == PropertyChangeNotify && req.x.property.key) {
free ((char *) req.x.property.key);
}

if (reply_fd >= 0) {
DEBUG ("replying to client");
if (write (reply_fd, &req, sizeof (req))
@@ -2616,7 +2639,7 @@ jack_deliver_event_to_all (jack_engine_t *engine, jack_event_t *event)
jack_unlock_graph (engine);
}

static void jack_do_get_client_by_uuid ( jack_engine_t *engine, jack_request_t *req)
static void jack_do_get_client_by_uuid (jack_engine_t *engine, jack_request_t *req)
{
JSList *node;
req->status = -1;
@@ -2875,9 +2898,14 @@ jack_notify_all_port_interested_clients (jack_engine_t *engine, jack_uuid_t src,

int
jack_deliver_event (jack_engine_t *engine, jack_client_internal_t *client,
jack_event_t *event)
jack_event_t *event, ...)
{
va_list ap;
char status=0;
char* key = 0;
size_t keylen = 0;

va_start (ap, event);

/* caller must hold the graph lock */

@@ -2896,6 +2924,21 @@ jack_deliver_event (jack_engine_t *engine, jack_client_internal_t *client,

DEBUG ("client %s is still alive", client->control->name);

/* Check property change events for matching key_size and keys */

if (event->type == PropertyChange) {
key = va_arg (ap, char*);
if (key && key[0] != '\0') {
keylen = strlen (key) + 1;
if (event->y.key_size != keylen) {
jack_error ("property change key %s sent with wrong length (%d vs %d)", key, event->y.key_size, keylen);
return -1;
}
}
}

va_end (ap);

if (jack_client_is_internal (client)) {

switch (event->type) {
@@ -2938,6 +2981,13 @@ jack_deliver_event (jack_engine_t *engine, jack_client_internal_t *client,
}
break;

case PropertyChange:
if (client->control->property_cbset) {
client->private_client->property_cb
(event->x.uuid, key, event->z.property_change, client->private_client->property_cb_arg);
}
break;

case LatencyCallback:
jack_client_handle_latency_callback (client->private_client, event, (client->control->type == ClientDriver));
break;
@@ -2965,6 +3015,20 @@ jack_deliver_event (jack_engine_t *engine, jack_client_internal_t *client,
jack_engine_signal_problems (engine);
}

/* for property changes, deliver the extra data representing
the variable length "key" that has changed in some way.
*/
if (event->type == PropertyChange) {
if (write (client->event_fd, key, keylen) != keylen) {
jack_error ("cannot send property change key to client [%s] (%s)",
client->control->name,
strerror (errno));
client->error += JACK_ERROR_WITH_SOCKETS;
jack_engine_signal_problems (engine);
}
}

if (client->error) {
status = -1;
} else {
@@ -4399,7 +4463,7 @@ jack_port_do_unregister (jack_engine_t *engine, jack_request_t *req)

shared = &engine->control->ports[req->x.port_info.port_id];

if (shared->client_id != req->x.port_info.client_id) {
if (jack_uuid_compare (shared->client_id, req->x.port_info.client_id) != 0) {
char buf[JACK_UUID_STRING_SIZE];
jack_uuid_unparse (req->x.port_info.client_id, buf);
jack_error ("Client %s is not allowed to remove port %s",
@@ -4556,6 +4620,40 @@ jack_port_registration_notify (jack_engine_t *engine,
}
}

void
jack_property_change_notify (jack_engine_t *engine,
jack_property_change_t change,
jack_uuid_t uuid,
const char* key)
{
jack_event_t event;
jack_client_internal_t *client;
JSList *node;

event.type = PropertyChange;
event.z.property_change = change;
jack_uuid_copy (event.x.uuid, uuid);
event.y.key_size = strlen (key) + 1;

for (node = engine->clients; node; node = jack_slist_next (node)) {
client = (jack_client_internal_t *) node->data;

if (!client->control->active) {
continue;
}

if (client->control->port_register_cbset) {
if (jack_deliver_event (engine, client, &event, key)) {
jack_error ("cannot send port registration"
" notification to %s (%s)",
client->control->name,
strerror (errno));
}
}
}
}

void
jack_client_registration_notify (jack_engine_t *engine,
const char* name, int yn)


+ 39
- 4
libjack/client.c View File

@@ -250,6 +250,21 @@ oop_client_deliver_request (void *ptr, jack_request_t *req)

wok = (write (client->request_fd, req, sizeof (*req))
== sizeof (*req));

/* if necessary, add variable length key data after a PropertyChange request
*/
if (req->type == PropertyChangeNotify) {
if (req->x.property.keylen) {
if (write (client->request_fd, req->x.property.key, req->x.property.keylen) != req->x.property.keylen) {
jack_error ("cannot send property key of length %d to server",
req->x.property.keylen);
req->status = -1;
return req->status;
}
}
}

rok = (read (client->request_fd, req, sizeof (*req))
== sizeof (*req));

@@ -281,8 +296,7 @@ jack_client_deliver_request (const jack_client_t *client, jack_request_t *req)
* the server.
*/

return client->deliver_request (client->deliver_arg,
req);
return client->deliver_request (client->deliver_arg, req);
}

#if JACK_USE_MACH_THREADS
@@ -1711,6 +1725,7 @@ jack_client_process_events (jack_client_t* client)
jack_client_control_t *control = client->control;
JSList *node;
jack_port_t* port;
char* key = 0;

DEBUG ("process events");

@@ -1728,7 +1743,17 @@ jack_client_process_events (jack_client_t* client)
strerror (errno));
return -1;
}

if (event.type == PropertyChange) {
key = (char *) malloc (event.y.key_size);
if (read (client->event_fd, key, event.y.key_size) !=
event.y.key_size) {
jack_error ("cannot read property change key (%s)",
strerror (errno));
return -1;
}
}

status = 0;
switch (event.type) {
@@ -1821,6 +1846,14 @@ jack_client_process_events (jack_client_t* client)
case LatencyCallback:
status = jack_client_handle_latency_callback (client, &event, 0 );
break;
case PropertyChange:
if (control->property_cbset) {
client->property_cb (event.x.uuid, key, event.z.property_change, client->property_cb_arg);
}
if (key) {
free (key);
}
break;
}
DEBUG ("client has dealt with the event, writing "
@@ -1832,7 +1865,7 @@ jack_client_process_events (jack_client_t* client)
"engine (%s)", strerror (errno));
return -1;
}
}
}

return 0;
}
@@ -3015,6 +3048,8 @@ jack_event_type_name (JackEventType type)
return "save session";
case LatencyCallback:
return "latency callback";
case PropertyChange:
return "property change callback";
default:
break;
}


+ 24
- 0
libjack/metadata.c View File

@@ -72,9 +72,22 @@ jack_properties_uninit ()
void
jack_free_description(jack_description_t* desc)
{
/* XXX iterate over each property, free values, then free desc itself */
return;
}

static int
jack_property_change_notify (jack_client_t* client, jack_uuid_t uuid, const char* key, jack_property_change_t change)
{
jack_request_t req;
req.type = PropertyChangeNotify;
req.x.property.change = change;
jack_uuid_copy (req.x.property.uuid, uuid);
req.x.property.keylen = key ? strlen (key) + 1 : 0;
req.x.property.key = key;
return jack_client_deliver_request (client, &req);
}

static void
make_key_dbt (DBT* dbt, jack_uuid_t subject, const char* key)
{
@@ -138,6 +151,8 @@ jack_set_property (jack_client_t* client,
return -1;
}

jack_property_change_notify (client, subject, key, PropertyChanged);

return 0;
}

@@ -404,6 +419,9 @@ jack_remove_property (jack_client_t* client, jack_uuid_t subject, const char* ke
jack_error ("Cannot delete key %s (%s)", key, db_strerror (ret));
return -1;
}

jack_property_change_notify (client, subject, key, PropertyDeleted);

return 0;
}

@@ -465,6 +483,8 @@ jack_remove_properties (jack_client_t* client, jack_uuid_t subject)

cursor->close (cursor);

jack_property_change_notify (client, subject, NULL, PropertyDeleted);

return retval;
}

@@ -472,6 +492,7 @@ int
jack_remove_all_properties (jack_client_t* client)
{
int ret;
jack_uuid_t empty_uuid;

if (jack_property_init (NULL)) {
return -1;
@@ -482,5 +503,8 @@ jack_remove_all_properties (jack_client_t* client)
return -1;
}

jack_uuid_clear (empty_uuid);
jack_property_change_notify (client, empty_uuid, NULL, PropertyDeleted);

return 0;
}

+ 2
- 0
libjack/transclient.c View File

@@ -25,6 +25,8 @@
#include <math.h>
#include <stdio.h>

#include <jack/uuid.h>

#include "atomicity.h"
#include "internal.h"
#include "local.h"


+ 1
- 1
tools

@@ -1 +1 @@
Subproject commit 9222d7a4eeb4fb18916db7c4b8487841ea1ab531
Subproject commit 6ac302ba8664e20c6c03d6da7fa8adeb7949925f

Loading…
Cancel
Save