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.
21 #include "event_pipe.h"
29 #include <sys/types.h>
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
];
47 * Invoke the callback for a certain event.
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
]();
59 main_notify_event(G_GNUC_UNUSED GIOChannel
*source
,
60 G_GNUC_UNUSED GIOCondition condition
,
61 G_GNUC_UNUSED gpointer data
)
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
)
77 /* invoke the event handler */
83 void event_pipe_init(void)
88 ret
= pipe_cloexec_nonblock(event_pipe
);
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]);
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
)
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
);
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);