Initial commit

This commit is contained in:
Matt Low 2019-10-14 23:38:14 +04:00
commit 5ec151409e
3 changed files with 210 additions and 0 deletions

11
Makefile Normal file
View File

@ -0,0 +1,11 @@
CC = gcc
CFLAGS = -g -Wall
LDLIBS=-lpthread -lmpdclient
OBJECTS = mpd_control.o
mpd_control: $(OBJECTS)
$(CC) $(CFLAGS) $^ $(LDLIBS) -o $@
clean:
rm $(OBJECTS)
rm mpd_control

19
PKGBUILD Normal file
View File

@ -0,0 +1,19 @@
pkgname=mpd_control
pkgver=0.0.1
pkgrel=1
pkgdesc="An i3blocks blocklet for MPD"
arch=('i686' 'x86_64')
license=('MIT')
depends=('libmpdclient')
source=("Makefile" "mpd_control.c")
sha256sums=('d75fcdd75f83daec43912d6ef243974b181ea9fe98ba2c43160b9e1541abb283'
'fd0383ecc78b393bcb09f6666c3dff20846bf7be047ae7a20f612a84bb9e57fd')
provides=('mpd_control')
build() {
make
}
package() {
install -Dm755 mpd_control ${pkgdir}/usr/bin/mpd_control
}

180
mpd_control.c Normal file
View File

@ -0,0 +1,180 @@
#include <mpd/client.h>
#include <pthread.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <sys/time.h>
#include <unistd.h>
struct worker_meta {
long long update_interval;
bool stop;
};
static long long
current_timestamp() {
struct timeval te;
gettimeofday(&te, NULL);
return te.tv_sec*1000LL + te.tv_usec/1000;
}
static int
handle_error(struct mpd_connection *c)
{
assert(mpd_connection_get_error(c) != MPD_ERROR_SUCCESS);
fprintf(stderr, "%s\n", mpd_connection_get_error_message(c));
mpd_connection_free(c);
return EXIT_FAILURE;
}
static void
get_tag(struct mpd_song *song, char *tag, enum mpd_tag_type type)
{
const char *value;
unsigned i = 0;
while ((value = mpd_song_get_tag(song, type, i++)) != NULL) {
strcpy(tag, value);
break;
}
}
static int
print_status(struct mpd_connection *conn)
{
struct mpd_status *status;
struct mpd_song *song;
mpd_command_list_begin(conn, true);
mpd_send_status(conn);
mpd_send_current_song(conn);
mpd_command_list_end(conn);
status = mpd_recv_status(conn);
if (status == NULL)
return handle_error(conn);
const enum mpd_state state = mpd_status_get_state(status);
const bool repeat = mpd_status_get_repeat(status);
const bool random = mpd_status_get_random(status);
const unsigned queue_pos = mpd_status_get_song_pos(status);
const unsigned queue_length = mpd_status_get_queue_length(status);
const unsigned elapsed = mpd_status_get_elapsed_time(status);
const unsigned remaining = mpd_status_get_total_time(status) - elapsed;
const unsigned remaining_mins = remaining / 60;
const unsigned remaining_secs = remaining % 60;
mpd_status_free(status);
if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS)
return handle_error(conn);
mpd_response_next(conn);
char artist[256];
char album[256];
char title[256];
while ((song = mpd_recv_song(conn)) != NULL) {
get_tag(song, artist, MPD_TAG_ARTIST);
get_tag(song, album, MPD_TAG_ALBUM);
get_tag(song, title, MPD_TAG_TITLE);
mpd_song_free(song);
}
if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS ||
!mpd_response_finish(conn))
return handle_error(conn);
char *play_icon;
if (state == MPD_STATE_PLAY) {
play_icon = "";
} else if (state == MPD_STATE_PAUSE) {
play_icon = "";
} else {
play_icon = "";
}
char state_icon[16];
strcpy(state_icon, "");
if (repeat)
strcat(state_icon, "");
if (random)
strcat(state_icon, "");
if (state == MPD_STATE_PLAY || state == MPD_STATE_PAUSE)
printf("%s%s %s - %s (-%u:%02u) [%u/%u]\n",
play_icon, state_icon, artist, title,
remaining_mins, remaining_secs,
queue_pos+1, queue_length);
fflush(stdout);
return 0;
}
void*
status_loop(void* worker_meta)
{
struct worker_meta *meta = (struct worker_meta*)worker_meta;
struct mpd_connection *conn = mpd_connection_new(NULL, 0, 0);
for (;;) {
if (meta->stop) {
break;
}
long long start = current_timestamp();
print_status(conn);
usleep((meta->update_interval - (current_timestamp() - start)) * 1000);
}
mpd_connection_free(conn);
return NULL;
}
int main(void)
{
struct worker_meta meta = {950, false};
pthread_t update_thread;
if(pthread_create(&update_thread, NULL, status_loop, &meta)) {
fprintf(stderr, "Error creating thread\n");
return 1;
}
for (;;) {
char *line;
size_t size;
if (getline(&line, &size, stdin) != -1) {
struct mpd_connection *conn = mpd_connection_new(NULL, 0, 0);
if (strcmp(line, "1\n") == 0) {
mpd_run_previous(conn);
} else if (strcmp(line, "2\n") == 0) {
mpd_run_toggle_pause(conn);
} else if (strcmp(line, "3\n") == 0) {
mpd_run_next(conn);
} else if (strcmp(line, "4\n") == 0) {
mpd_run_seek_current(conn, 3, true);
} else if (strcmp(line, "5\n") == 0) {
mpd_run_seek_current(conn, -3, true);
} else {
// ignore unrecognized input
continue;
}
print_status(conn);
mpd_connection_free(conn);
}
}
if(pthread_join(update_thread, NULL)) {
fprintf(stderr, "Error joining thread\n");
return 2;
}
return 0;
}