@@ -57,6 +57,23 @@ enum JackSessionEventType { | |||
typedef enum JackSessionEventType jack_session_event_type_t; | |||
enum JackSessionFlags { | |||
/** | |||
* an error occured while saving. | |||
*/ | |||
JackSessionSaveError = 0x01, | |||
/** | |||
* this reply indicates that a client is part of a multiclient application. | |||
* the command reply is left empty. but the session manager should still | |||
* consider this client part of a session. it will come up due to invocation of another | |||
* client. | |||
*/ | |||
JackSessionChildClient = 0x02 | |||
}; | |||
typedef enum JackSessionFlags jack_session_flags_t; | |||
struct _jack_session_event { | |||
/** | |||
* the actual type of this session event. | |||
@@ -87,6 +104,11 @@ struct _jack_session_event { | |||
* initially set to NULL by jack; | |||
*/ | |||
char *command_line; | |||
/** | |||
* flags to be set by the client. normally left 0. | |||
*/ | |||
jack_session_flags_t flags; | |||
}; | |||
typedef struct _jack_session_event jack_session_event_t; | |||
@@ -139,16 +161,16 @@ int jack_session_reply( jack_client_t *client, jack_session_event_t *event ) JAC | |||
*/ | |||
typedef struct { | |||
char uuid[16]; | |||
char client_name[33]; | |||
char command[256]; | |||
const char *uuid; | |||
const char *client_name; | |||
const char *command; | |||
} jack_session_command_t; | |||
/** | |||
* send a save or quit event, to all clients listening for session | |||
* callbacks. the returned strings of the clients are accumulated and | |||
* returned as an array of jack_session_command_t. | |||
* its terminated by ret[i].uuid[0]='\0' | |||
* its terminated by ret[i].uuid == NULL | |||
* target == NULL means send to all interested clients. otherwise a clientname | |||
*/ | |||
@@ -157,6 +179,12 @@ jack_session_command_t *jack_session_notify (jack_client_t* client, | |||
jack_session_event_type_t type, | |||
const char *path ) JACK_WEAK_EXPORT; | |||
/** | |||
* free the memory allocated by a session command. | |||
*/ | |||
void jack_session_commands_free (jack_session_command_t *cmds) JACK_WEAK_EXPORT; | |||
/** | |||
* get the sessionid for a client name. | |||
* the sessionmanager needs this to reassociate a client_name to the session_id. | |||
@@ -170,7 +198,20 @@ char *jack_get_uuid_for_client_name( jack_client_t *client, const char *client_n | |||
* session_ids to client names. | |||
*/ | |||
char *jack_get_client_name_for_uuid( jack_client_t *client, const char *client_uuid ) JACK_WEAK_EXPORT; | |||
char *jack_get_client_name_by_uuid( jack_client_t *client, const char *client_uuid ) JACK_WEAK_EXPORT; | |||
/** | |||
* reserve a client name and associate it to a uuid. | |||
* when a client later call jack_client_open() and specifies the uuid, | |||
* jackd will assign the reserved name. | |||
* this allows a session manager to know in advance under which client name | |||
* its managed clients will appear. | |||
* | |||
* @return 0 on success, otherwise a non-zero error code | |||
*/ | |||
int | |||
jack_reserve_client_name( jack_client_t *client, const char *name, const char *uuid ) JACK_WEAK_EXPORT; | |||
#ifdef __cplusplus | |||
} | |||
@@ -1369,6 +1369,24 @@ jack_session_reply (jack_client_t *client, jack_session_event_t *event ) | |||
return retval; | |||
} | |||
void | |||
jack_session_commands_free (jack_session_command_t *cmds) | |||
{ | |||
int i=0; | |||
while(1) { | |||
if (cmds[i].client_name) | |||
free ((char *)cmds[i].client_name); | |||
if (cmds[i].command) | |||
free ((char *)cmds[i].command); | |||
if (cmds[i].uuid) | |||
free ((char *)cmds[i].uuid); | |||
else | |||
break; | |||
} | |||
free(cmds); | |||
} | |||
jack_session_command_t * | |||
jack_session_notify (jack_client_t* client, const char *target, jack_session_event_type_t code, const char *path ) | |||
{ | |||
@@ -1388,8 +1406,6 @@ jack_session_notify (jack_client_t* client, const char *target, jack_session_eve | |||
request.x.session.target[0] = '\0'; | |||
request.x.session.type = code; | |||
// XXX: this is hacky now. | |||
// a) we dont support for internal clients :D FUCK EM | |||
if( (write (client->request_fd, &request, sizeof (request)) | |||
!= sizeof (request)) ) { | |||
@@ -1408,29 +1424,39 @@ jack_session_notify (jack_client_t* client, const char *target, jack_session_eve | |||
num_replies += 1; | |||
retval = realloc( retval, (num_replies)*sizeof(jack_session_command_t) ); | |||
retval[num_replies-1].client_name = malloc (JACK_CLIENT_NAME_SIZE); | |||
retval[num_replies-1].command = malloc (JACK_PORT_NAME_SIZE); | |||
retval[num_replies-1].uuid = malloc (16); | |||
if ( (retval[num_replies-1].client_name == NULL) | |||
||(retval[num_replies-1].command == NULL) | |||
||(retval[num_replies-1].uuid == NULL) ) | |||
goto out; | |||
if( uid == 0 ) | |||
break; | |||
if (read (client->request_fd, retval[num_replies-1].client_name, sizeof (retval[num_replies].client_name)) | |||
!= sizeof (retval[num_replies-1].client_name)) { | |||
if (read (client->request_fd, (char *)retval[num_replies-1].client_name, JACK_CLIENT_NAME_SIZE) | |||
!= JACK_CLIENT_NAME_SIZE) { | |||
jack_error ("cannot read result for request type %d from" | |||
" server (%s)", request.type, strerror (errno)); | |||
goto out; | |||
} | |||
if (read (client->request_fd, retval[num_replies-1].command, sizeof (retval[num_replies].command)) | |||
!= sizeof (retval[num_replies-1].command)) { | |||
if (read (client->request_fd, (char *)retval[num_replies-1].command, JACK_PORT_NAME_SIZE) | |||
!= JACK_PORT_NAME_SIZE) { | |||
jack_error ("cannot read result for request type %d from" | |||
" server (%s)", request.type, strerror (errno)); | |||
goto out; | |||
} | |||
snprintf( retval[num_replies-1].uuid, sizeof( retval[num_replies-1].uuid ), "%d", uid ); | |||
snprintf( (char *)retval[num_replies-1].uuid, 16, "%d", uid ); | |||
} | |||
retval[num_replies-1].uuid[0] = '\0'; | |||
free((char *)retval[num_replies-1].uuid); | |||
retval[num_replies-1].uuid = NULL; | |||
return retval; | |||
out: | |||
if( retval ) | |||
free(retval); | |||
jack_session_commands_free(retval); | |||
return NULL; | |||
} | |||