Skip to content

Instantly share code, notes, and snippets.

@pcewing
Created June 16, 2020 04:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pcewing/c054cda857d06f84af92644ad313f18e to your computer and use it in GitHub Desktop.
Save pcewing/c054cda857d06f84af92644ad313f18e to your computer and use it in GitHub Desktop.
Example epoll-based ncurses MPD client
#include <curses.h>
#include <mpd/client.h>
#include <stdlib.h>
#include <sys/epoll.h>
#include <unistd.h>
#define MAX_EVENTS 10
void
toggle_play_pause(struct mpd_connection *mpd_conn) {
// Get the current status
struct mpd_status *status = mpd_run_status(mpd_conn);
// Play/pause/unpase depending on the current state
switch (mpd_status_get_state(status)) {
case MPD_STATE_UNKNOWN:
break;
case MPD_STATE_STOP:
mpd_run_play(mpd_conn);
break;
case MPD_STATE_PAUSE:
mpd_run_pause(mpd_conn, 0);
break;
case MPD_STATE_PLAY:
mpd_run_pause(mpd_conn, 1);
break;
default:
break;
}
}
int
main(int argc, char **argv) {
// Initialize the mpd connection and get the underlying socket fd
struct mpd_connection *mpd_conn = mpd_connection_new("127.0.0.1", 6600, 0);
if (mpd_conn == NULL)
exit(EXIT_FAILURE);
mpd_send_idle(mpd_conn);
int mpd_fd = mpd_connection_get_fd(mpd_conn);
// Startup ncurses
initscr();
noecho();
curs_set(0);
timeout(0);
// Print the available key commands
printw("Commands:");
mvprintw(1, 0, " Toggle Play/Pause: p");
mvprintw(2, 0, " Quit: q");
refresh();
// Create an epoll instance for the event loop
int epfd = epoll_create1(0);
if (epfd == -1)
exit(EXIT_FAILURE);
// Register the mpd socket with epoll
struct epoll_event ev_mpd = {.events = EPOLLIN, .data = {.fd = mpd_fd}};
if (epoll_ctl(epfd, EPOLL_CTL_ADD, mpd_fd, &ev_mpd) == -1)
exit(EXIT_FAILURE);
// Register stdin with epoll
struct epoll_event ev_stdin = {.events = EPOLLIN,
.data = {.fd = STDIN_FILENO}};
if (epoll_ctl(epfd, EPOLL_CTL_ADD, STDIN_FILENO, &ev_stdin) == -1)
exit(EXIT_FAILURE);
// Main event loop
struct epoll_event evlist[MAX_EVENTS];
for (;;) {
int nfds = epoll_wait(epfd, evlist, MAX_EVENTS, -1);
if (nfds == -1)
exit(EXIT_FAILURE);
for (int i = 0; i < nfds; ++i) {
if (evlist[i].data.fd == mpd_fd) {
enum mpd_idle idle = mpd_recv_idle(mpd_conn, false);
time_t t = time(NULL);
mvprintw(5, 0, "State last changed: %s %s\n",
mpd_idle_name(idle), asctime(localtime(&t)));
mpd_send_idle(mpd_conn);
} else if (evlist[i].data.fd == STDIN_FILENO) {
int c = getch();
mpd_run_noidle(mpd_conn);
while (c != -1) {
mvprintw(4, 0, "Key pressed: %c\n", (char)c);
if (c == 112) // p
toggle_play_pause(mpd_conn);
if (c == 113) // q
goto done;
c = getch();
}
mpd_send_idle(mpd_conn);
}
}
refresh();
}
done:
endwin();
mpd_connection_free(mpd_conn);
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment