strtok() is recursive by default on win32.
[mpd-mk.git] / src / event_pipe.c
blobf66dc86d6e7ae4cdabf0ace9953498bc24dfe6c5
1 /*
2 * Copyright (C) 2003-2010 The Music Player Daemon Project
3 * http://www.musicpd.org
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include "config.h"
21 #include "event_pipe.h"
22 #include "fd_util.h"
24 #include <stdbool.h>
25 #include <assert.h>
26 #include <glib.h>
27 #include <string.h>
28 #include <errno.h>
29 #include <sys/types.h>
30 #include <unistd.h>
32 #ifdef WIN32
33 /* for _O_BINARY */
34 #include <fcntl.h>
35 #endif
37 #undef G_LOG_DOMAIN
38 #define G_LOG_DOMAIN "event_pipe"
40 static int event_pipe[2];
41 static guint event_pipe_source_id;
42 static GMutex *event_pipe_mutex;
43 static bool pipe_events[PIPE_EVENT_MAX];
44 static event_pipe_callback_t event_pipe_callbacks[PIPE_EVENT_MAX];
46 /**
47 * Invoke the callback for a certain event.
49 static void
50 event_pipe_invoke(enum pipe_event event)
52 assert((unsigned)event < PIPE_EVENT_MAX);
53 assert(event_pipe_callbacks[event] != NULL);
55 event_pipe_callbacks[event]();
58 static gboolean
59 main_notify_event(G_GNUC_UNUSED GIOChannel *source,
60 G_GNUC_UNUSED GIOCondition condition,
61 G_GNUC_UNUSED gpointer data)
63 char buffer[256];
64 ssize_t r = read(event_pipe[0], buffer, sizeof(buffer));
65 bool events[PIPE_EVENT_MAX];
67 if (r < 0 && errno != EAGAIN && errno != EINTR)
68 g_error("error reading from pipe: %s", strerror(errno));
70 g_mutex_lock(event_pipe_mutex);
71 memcpy(events, pipe_events, sizeof(events));
72 memset(pipe_events, 0, sizeof(pipe_events));
73 g_mutex_unlock(event_pipe_mutex);
75 for (unsigned i = 0; i < PIPE_EVENT_MAX; ++i)
76 if (events[i])
77 /* invoke the event handler */
78 event_pipe_invoke(i);
80 return true;
83 void event_pipe_init(void)
85 GIOChannel *channel;
86 int ret;
88 ret = pipe_cloexec_nonblock(event_pipe);
89 if (ret < 0)
90 g_error("Couldn't open pipe: %s", strerror(errno));
92 channel = g_io_channel_unix_new(event_pipe[0]);
93 event_pipe_source_id = g_io_add_watch(channel, G_IO_IN,
94 main_notify_event, NULL);
95 g_io_channel_unref(channel);
97 event_pipe_mutex = g_mutex_new();
100 void event_pipe_deinit(void)
102 g_mutex_free(event_pipe_mutex);
104 g_source_remove(event_pipe_source_id);
106 close(event_pipe[0]);
107 close(event_pipe[1]);
110 void
111 event_pipe_register(enum pipe_event event, event_pipe_callback_t callback)
113 assert((unsigned)event < PIPE_EVENT_MAX);
114 assert(event_pipe_callbacks[event] == NULL);
116 event_pipe_callbacks[event] = callback;
119 void event_pipe_emit(enum pipe_event event)
121 ssize_t w;
123 assert((unsigned)event < PIPE_EVENT_MAX);
125 g_mutex_lock(event_pipe_mutex);
126 if (pipe_events[event]) {
127 /* already set: don't write */
128 g_mutex_unlock(event_pipe_mutex);
129 return;
132 pipe_events[event] = true;
133 g_mutex_unlock(event_pipe_mutex);
135 w = write(event_pipe[1], "", 1);
136 if (w < 0 && errno != EAGAIN && errno != EINTR)
137 g_error("error writing to pipe: %s", strerror(errno));
140 void event_pipe_emit_fast(enum pipe_event event)
142 assert((unsigned)event < PIPE_EVENT_MAX);
144 pipe_events[event] = true;
145 (void)write(event_pipe[1], "", 1);