Skip to content

Instantly share code, notes, and snippets.

@pcewing
Created June 16, 2020 04:09
Show Gist options
  • Select an option

  • Save pcewing/c054cda857d06f84af92644ad313f18e to your computer and use it in GitHub Desktop.

Select an option

Save pcewing/c054cda857d06f84af92644ad313f18e to your computer and use it in GitHub Desktop.

Revisions

  1. pcewing created this gist Jun 16, 2020.
    104 changes: 104 additions & 0 deletions epoll_mpd_client.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,104 @@
    #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;
    }