![]() | ![]() | ![]() | GNetwork Library Manual | ![]() |
---|
Object-Specific Code — Code specific for your object
The object-specific code is mainly filling in the code your object needs to function properly. As with the "recv" object callback featured above, we'll use the object callback functions for FLPClient signals to do things like open and close the destination file.
The "download-start" object callback is used to open the destination file:
static void flp_client_download_start (FLPClient *client, const gchar *filename, gsize filesize, gsize offset) { gchar *path; /* The client should not have an open file already */ g_assert (client->fd == -1); /* Put the file in ~/Downloads/<filename> */ path = g_build_filename (g_get_home_dir (), "Downloads", filename, NULL); /* Actually open the file */ client->fd = open (path, (O_CREAT | O_NONBLOCK | O_APPEND)); /* Free the path */ g_free (path); } [...] static void flp_client_class_init (FLPClientClass *class) { [...] class->download_start = flp_client_download_start; [...] }
This function opens the destination file if it exists or creates a new one if it doesn't, makes sure that it will append to the end of the file, and opens it in "non-blocking" mode, so it doesn't freeze the program when the FLPClient object writes to the file. More documentation can be found in the "open(2)" UNIX man page.
Also note that you don't have to use UNIX system calls in your object, you could just as easily use the GIOChannel mechanism available in GLib, GNOME-VFS, or any other file API you wish.
The "download-done" object callback is used to clean up after the download has been completed:
static void flp_client_download_done (FLPClient *client, const gchar *filename, gboolean completed) { /* The destination file should always be open at this point. */ g_assert (client->fd != -1); close (client->fd); /* Reset the object members */ client->fd = -1; client->filesize_recieved = 0; /* Reset the object properties */ /* Freeze the "notify" signal until we're done. */ g_object_freeze_notify (G_OBJECT (client)); client->offset = 0; g_object_notify (G_OBJECT (client), "offset"); client->filesize = 0; g_object_notify (G_OBJECT (client), "filesize"); g_free (client->filename); client->filename = NULL; g_object_notify (G_OBJECT (client), "filename"); /* We're done, so thaw the "notify" signal. */ g_object_thaw_notify (G_OBJECT (client)); } [...] static void flp_client_class_init (FLPClientClass *class) { [...] class->download_start = flp_client_download_start; class->download_done = flp_client_download_done; [...] }
This function closes the destination file and resets the object data to it's original "we're not downloading anything yet" state.
The last bit of code to write is the "quit" and "error" object callbacks. The main job of these signals is to emit the "download-done" signal if a download is in progress:
static void flp_client_quit (FLPClient *client, gboolean requested) { if (client->fd != -1) { g_signal_emit (client, flp_signals[DOWNLOAD_DONE], 0, client->filename, FALSE); } } static void flp_client_error (FLPClient *client, FLPErrorType error) { if (client->fd != -1) { g_signal_emit (client, flp_signals[DOWNLOAD_DONE], 0, client->filename, FALSE); } } [...] static void flp_client_class_init (FLPClientClass *class) { [...] class->quit = flp_client_quit; class->error = flp_client_error; [...] }
As you can see, it's simply a matter of checking to see if the download was completed or not.
That's about all you need to do in order to subclass a GTcpConnection object. The example given was moderately complex, and much of the code doing the actual work was immature, but it does provide a decent introduction on how to create a subclass, as well as the basic layout of what work a subclass would have to perform to be useful.
<< Sub-Classing | Source Code >> |