Created
June 16, 2020 04:09
-
-
Save pcewing/c054cda857d06f84af92644ad313f18e to your computer and use it in GitHub Desktop.
Example epoll-based ncurses MPD client
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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