Hello, I have been thinking about the GUI / Core separation, and perhaps we shouldn't create a daemon and a frontend side, but a client and a lib site. The client could of course still be a deamon but it can also be a 'normal' GUI.
My proposal, make the core send events to an event 'queue' and the
client should process the queue and extract the data from it it wants to
have. Events are send using structs. The structures its structure are
only known at the library side. The client has to use functions to
retreive the meaning of the data. Small example for a new incoming
upload.
(private struct)
typedef struct event_upload {
/* All event structures must begin with gchar
"GTK_GNUTELLA_LIB_EVENT"; gint even_type; gchar *description */
gchar[] is_event "GTK_GNUTELLA_LIB_EVENT"; /* I know this doesn't
compile, it is just an example */
gint event_type;
gchar *description;
gint id;
gint progress;
gint speed;
guint size;
} event_upload_t;
void new_upload (...) {
...
event_upload = new walloc0(sizeof(event_upload_t));
event_upload->description = "New incoming upload request";
event_upload->event_type = UPLOAD;
event_upload->id = upload->handle;
send_event(event_upload->event_type, event_upload);
}
The GUI listens for new events by using the gtk-gnutella-library
function call get_event(*data). This function returns the event type,
which identifies which structure was used, and sets the data pointer to
the structure containing the real data:
event_type = get_event(&data);
The GUI can use a switch to detect what event kind of an event happend:
switch(event_type)
case UPLOAD:
...
Then it can call various functions to retreive more info, for example
gnut_upload_get_filename(data), gnut_upload_get_progress(data):
size = gnut_upload_get_filesize(data);
when it is done retreiving the wanted info, it uses
gnut_free_event(event_type, data).
struct event_s {
gchar[] is_event "GTK_GNUTELLA_LIB_EVENT";
gint event_type;
gchar *description;
} event_t;
void gnut_free_event(event_type, data)
{
event_t *event = (event_t *) data;
#ifdef DEBUG
g_assert(event->event_type == event_type);
#else
if (event->event_type != event_type) {
g_warning("The client tried to free an event with an incorrect
event type. \n");
if (event->is_event == "GTK_GNUTELLA_LIB_EVENT")
g_warning("Looks like a valid event data though, freeing
anyway");
else {
g_warning("Data doesn't look like a valid event anyway. Will
probably leak memory");
return;
}
}
#endif
switch (event->event_type) {
case UPLOAD:
wfree(event, sizeof(event_upload_t));
break;
default:
#ifdef DEBUG
g_abort();
#else
g_warning("Unknown event_type %d, is the client fooling us?",
event->event_type);
#endif
}
In case you wonder why I don't use data->size on the client side
directly, that is this will allow one to upgrade the library without
breaking the allready compiled client when the structure's format gets
changed. For example the upload and download structures are extended
with queueing info. This would make the gtk-gnutella-lib downloads
compatible. Which is a good thing, because we want users to upgrade the
lib asap when an older version harms the network, without waiting for a
client to update there version too.
Longer example for the client:
while (waiting_events()) {
switch ( (event_type = get_event(&data)) ) {
case UPLOAD:
name = gnut_upload_get_filename(data);
size = gnut_upload_get_filesize(data);
id = gnut_upload_get_id(data);
status = gnut_upload_get_status(data);
speed = gnut_upload_get_speed(data);
progress = gnut_upload_get_progress(data);
/* Later on, PARQ was added. */
queue_size = gnut_upload_get_queue_size(data);
queue_position = gnut_upload_get_queue_position(data);
queue_eta = gnut_upload_get_queue_eta(data);
break;
case GNET_CONNECTION:
/* etc... */
default:
printf("Eventype %d with description %s not yet supported by
the GUI. Are you running a newer gtk-gnutella-lib version?\r\n",
event_type, gnut_get_description(data));
gnut_free_event(event_type, data);
}
}
Comments?
ps.
What would be a good prefix for the gtk-gnutella-functions? I suppose
gtk-gnutella_upload_get_size() would get too long.
gnut_upload_get_size() might be confusing as there is allready a program
called gnut, right? ggl (gtk-gnutella lib) might not be obvious enough.
--
Jeroen Asselman <[EMAIL PROTECTED]>
signature.asc
Description: Dit berichtdeel is digitaal ondertekend
