diff --git a/src/gidle.c b/src/gidle.c
index 16901679e84bd9d822f5e558ed34cfd249bc5597..ca07fefbaf34a457c053f66d597797e06fd946c8 100644 (file)
--- a/src/gidle.c
+++ b/src/gidle.c
/* ncmpc (Ncurses MPD Client)
- (c) 2004-2009 The Music Player Daemon Project
+ (c) 2004-2010 The Music Player Daemon Project
Project homepage: http://musicpd.org
Redistribution and use in source and binary forms, with or without
*/
#include "gidle.h"
+#include "Compiler.h"
#include <mpd/async.h>
#include <mpd/parser.h>
#include <glib.h>
+
#include <assert.h>
#include <string.h>
-#include <sys/select.h>
#include <errno.h>
struct mpd_glib_source {
* flag is set, mpd_glib_enter() is a no-op to prevent this.
*/
bool leaving;
+
+ /**
+ * This flag is true when mpd_glib_free() has been called
+ * during a callback invoked from mpd_glib_leave().
+ * mpd_glib_leave() will do the real g_free() call then.
+ */
+ bool destroyed;
};
struct mpd_glib_source *
source->io_events = 0;
source->id = 0;
source->leaving = false;
+ source->destroyed = false;
return source;
}
void
mpd_glib_free(struct mpd_glib_source *source)
{
+ assert(!source->destroyed);
+
if (source->id != 0)
g_source_remove(source->id);
g_io_channel_unref(source->channel);
mpd_parser_free(source->parser);
- g_free(source);
+
+ if (source->leaving)
+ source->destroyed = true;
+ else
+ g_free(source);
}
static void
mpd_glib_invoke(const struct mpd_glib_source *source)
{
assert(source->id == 0);
+ assert(!source->destroyed);
if (source->idle_events != 0)
source->callback(MPD_ERROR_SUCCESS, 0, NULL,
const char *message)
{
assert(source->id == 0);
+ assert(!source->destroyed);
source->callback(error, server_error, message,
0, source->callback_ctx);
mpd_glib_recv(struct mpd_glib_source *source)
{
char *line;
- bool success;
-
while ((line = mpd_async_recv_line(source->async)) != NULL) {
- success = mpd_glib_feed(source, line);
- if (!success)
+ if (!mpd_glib_feed(source, line))
return false;
}
}
static gboolean
-mpd_glib_source_callback(G_GNUC_UNUSED GIOChannel *_source,
+mpd_glib_source_callback(gcc_unused GIOChannel *_source,
GIOCondition condition, gpointer data)
{
struct mpd_glib_source *source = data;
- bool success;
- enum mpd_async_event events;
assert(source->id != 0);
assert(source->io_events != 0);
/* let libmpdclient do some I/O */
- success = mpd_async_io(source->async,
- g_io_condition_to_mpd_async_event(condition));
- if (!success) {
+ if (!mpd_async_io(source->async,
+ g_io_condition_to_mpd_async_event(condition))) {
source->id = 0;
source->io_events = 0;
/* receive the response */
if ((condition & G_IO_IN) != 0) {
- success = mpd_glib_recv(source);
- if (!success)
+ if (!mpd_glib_recv(source))
return false;
}
/* continue polling? */
- events = mpd_async_events(source->async);
+ enum mpd_async_event events = mpd_async_events(source->async);
if (events == 0) {
/* no events - disable watch */
source->id = 0;
mpd_glib_add_watch(struct mpd_glib_source *source)
{
enum mpd_async_event events = mpd_async_events(source->async);
- GIOCondition condition;
assert(source->io_events == 0);
assert(source->id == 0);
- condition = mpd_async_events_to_g_io_condition(events);
-
+ GIOCondition condition = mpd_async_events_to_g_io_condition(events);
source->id = g_io_add_watch(source->channel, condition,
mpd_glib_source_callback, source);
source->io_events = events;
}
-void
+bool
mpd_glib_enter(struct mpd_glib_source *source)
{
- bool success;
-
assert(source->io_events == 0);
assert(source->id == 0);
+ assert(!source->destroyed);
if (source->leaving)
- return;
+ return false;
source->idle_events = 0;
- success = mpd_async_send_command(source->async, "idle", NULL);
- if (!success) {
+ if (!mpd_async_send_command(source->async, "idle", NULL)) {
mpd_glib_invoke_async_error(source);
- return;
+ return false;
}
mpd_glib_add_watch(source);
+ return true;
}
-void
+bool
mpd_glib_leave(struct mpd_glib_source *source)
{
- enum mpd_idle events;
+ assert(!source->destroyed);
if (source->id == 0)
/* already left, callback was invoked */
- return;
+ return true;
g_source_remove(source->id);
source->id = 0;
source->io_events = 0;
- events = source->idle_events == 0
+ enum mpd_idle events = source->idle_events == 0
? mpd_run_noidle(source->connection)
: mpd_recv_idle(source->connection, false);
mpd_glib_invoke_error(source, error, server_error,
mpd_connection_get_error_message(source->connection));
+
+ if (source->destroyed) {
+ g_free(source);
+ return false;
+ }
+
source->leaving = false;
- return;
+ return true;
}
source->idle_events |= events;
mpd_glib_invoke(source);
+ if (source->destroyed) {
+ g_free(source);
+ return false;
+ }
+
source->leaving = false;
+ return true;
}