2 * Copyright (C) 2003-2009 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 "event_pipe.h"
28 #include <sys/types.h>
37 #define G_LOG_DOMAIN "event_pipe"
39 static int event_pipe
[2];
40 static guint event_pipe_source_id
;
41 static GMutex
*event_pipe_mutex
;
42 static bool pipe_events
[PIPE_EVENT_MAX
];
43 static event_pipe_callback_t event_pipe_callbacks
[PIPE_EVENT_MAX
];
46 * Invoke the callback for a certain event.
49 event_pipe_invoke(enum pipe_event event
)
51 assert((unsigned)event
< PIPE_EVENT_MAX
);
52 assert(event_pipe_callbacks
[event
] != NULL
);
54 event_pipe_callbacks
[event
]();
58 main_notify_event(G_GNUC_UNUSED GIOChannel
*source
,
59 G_GNUC_UNUSED GIOCondition condition
,
60 G_GNUC_UNUSED gpointer data
)
63 ssize_t r
= read(event_pipe
[0], buffer
, sizeof(buffer
));
64 bool events
[PIPE_EVENT_MAX
];
66 if (r
< 0 && errno
!= EAGAIN
&& errno
!= EINTR
)
67 g_error("error reading from pipe: %s", strerror(errno
));
69 g_mutex_lock(event_pipe_mutex
);
70 memcpy(events
, pipe_events
, sizeof(events
));
71 memset(pipe_events
, 0, sizeof(pipe_events
));
72 g_mutex_unlock(event_pipe_mutex
);
74 for (unsigned i
= 0; i
< PIPE_EVENT_MAX
; ++i
)
76 /* invoke the event handler */
82 void event_pipe_init(void)
88 ret
= _pipe(event_pipe
, 512, _O_BINARY
);
90 ret
= pipe(event_pipe
);
93 g_error("Couldn't open pipe: %s", strerror(errno
));
95 if (set_nonblocking(event_pipe
[1]) < 0)
96 g_error("Couldn't set non-blocking I/O: %s", strerror(errno
));
99 channel
= g_io_channel_unix_new(event_pipe
[0]);
100 event_pipe_source_id
= g_io_add_watch(channel
, G_IO_IN
,
101 main_notify_event
, NULL
);
102 g_io_channel_unref(channel
);
104 event_pipe_mutex
= g_mutex_new();
107 void event_pipe_deinit(void)
109 g_mutex_free(event_pipe_mutex
);
111 g_source_remove(event_pipe_source_id
);
113 close(event_pipe
[0]);
114 close(event_pipe
[1]);
118 event_pipe_register(enum pipe_event event
, event_pipe_callback_t callback
)
120 assert((unsigned)event
< PIPE_EVENT_MAX
);
121 assert(event_pipe_callbacks
[event
] == NULL
);
123 event_pipe_callbacks
[event
] = callback
;
126 void event_pipe_emit(enum pipe_event event
)
130 assert((unsigned)event
< PIPE_EVENT_MAX
);
132 g_mutex_lock(event_pipe_mutex
);
133 if (pipe_events
[event
]) {
134 /* already set: don't write */
135 g_mutex_unlock(event_pipe_mutex
);
139 pipe_events
[event
] = true;
140 g_mutex_unlock(event_pipe_mutex
);
142 w
= write(event_pipe
[1], "", 1);
143 if (w
< 0 && errno
!= EAGAIN
&& errno
!= EINTR
)
144 g_error("error writing to pipe: %s", strerror(errno
));
147 void event_pipe_emit_fast(enum pipe_event event
)
149 assert((unsigned)event
< PIPE_EVENT_MAX
);
151 pipe_events
[event
] = true;
152 (void)write(event_pipe
[1], "", 1);