aboutsummaryrefslogtreecommitdiff
path: root/moc_x11.c
diff options
context:
space:
mode:
authorCalvin Morrison <calvin@fastmailteam.com>2022-07-27 20:58:28 -0400
committerCalvin Morrison <calvin@fastmailteam.com>2022-07-27 20:58:28 -0400
commitbcd8da8b1a3d02a90b3c9c8ca73d8b26760bb219 (patch)
treea89057557b9076306864428ff542c672b5ce7eb4 /moc_x11.c
parentd210af2268c29420983cdd6937affc7a2d3f5b47 (diff)
libmoc
our previous attempt ran into issues where we have two loops, a GUI loop and the MOC loop. I rewrote this into lib_moc which has it's own thread that manages the MOC socket connection and exposes the interface to a client program via a moc object. all you need to do is call moc_init(); Pretty cool, still runs into issues regarding autoconnect and some other problems.
Diffstat (limited to 'moc_x11.c')
-rw-r--r--moc_x11.c142
1 files changed, 142 insertions, 0 deletions
diff --git a/moc_x11.c b/moc_x11.c
new file mode 100644
index 0000000..efc4ce3
--- /dev/null
+++ b/moc_x11.c
@@ -0,0 +1,142 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h> //Header file for sleep(). man 3 sleep for details.
+#include <errno.h>
+
+#include <pthread.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xos.h>
+
+#include "moc_library.h"
+
+void *xmalloc (size_t size)
+{
+ void *p;
+
+
+ if ((p = malloc(size)) == NULL) {
+ fprintf(stderr, "Can't allocate memory!");
+ exit(0);
+ }
+ return p;
+}
+
+/* Obtains the next X11 event with specified timeout. */
+ static int XNextEventTimed(Display* dsp, XEvent* event_return, long millis) {
+ if (millis == 0)
+ {
+ XNextEvent(dsp, event_return);
+ return True;
+ }
+
+ struct timeval tv;
+ tv.tv_sec = millis / 1000;
+ tv.tv_usec = (millis % 1000) * 1000;
+
+ XFlush(dsp);
+ if (XPending(dsp))
+ {
+ XNextEvent(dsp, event_return);
+ return True;
+ }
+ else
+ {
+ int fd = ConnectionNumber(dsp);
+ fd_set readset;
+ FD_ZERO(&readset);
+ FD_SET(fd, &readset);
+ if (select(fd+1, &readset, NULL, NULL, &tv) <= 0)
+ {
+ return False;
+ }
+ else
+ {
+ if (XPending(dsp))
+ {
+ XNextEvent(dsp, event_return);
+ return True;
+ }
+ else
+ {
+ return False;
+ }
+ }
+ }
+}
+
+char *time_format(int sec) {
+
+ int h = (sec/3600);
+ int m = (sec -(3600*h))/60;
+ int s = (sec -(3600*h)-(m*60));
+
+ char *str = xmalloc(256);
+ if(h) {
+ sprintf(str, "%d:%2d:%02d",h,m,s);
+ } else {
+ sprintf(str, "%02d:%02d",m,s);
+ }
+ return str;
+}
+
+int main() {
+
+ Display* dpy = XOpenDisplay(NULL);
+ if (dpy == NULL)
+ {
+ fprintf(stderr, "Cannot open display\n");
+ exit(1);
+ }
+
+ int s = DefaultScreen(dpy);
+ Window win = XCreateSimpleWindow(dpy, RootWindow(dpy, s), 10, 10, 660, 200, 1,
+ BlackPixel(dpy, s), WhitePixel(dpy, s));
+ XSelectInput(dpy, win, ExposureMask | ButtonPress | KeyPressMask);
+ XMapWindow(dpy, win);
+
+ XStoreName(dpy, win, "mocicon");
+
+ Atom WM_DELETE_WINDOW = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
+ XSetWMProtocols(dpy, win, &WM_DELETE_WINDOW, 1);
+
+ struct moc *mh = moc_init();
+ if(mh == NULL) {
+ return 1;
+ }
+
+ XEvent e;
+ while(1) {
+ int got_event = XNextEventTimed(dpy, &e, 250);
+
+ if(mh->status != CONNECTED) {
+ printf("can't connect\n");
+ }
+
+ XClearWindow(dpy, win);
+ int y_offset = 20;
+ int x = 10;
+ pthread_mutex_lock(&mh->lock);
+ if(mh->state == PLAYING || mh->state == PAUSED) {
+ char *timestr= time_format(mh->time);
+
+ XDrawString(dpy, win, DefaultGC(dpy, s), x, y_offset, mh->title, strlen(mh->title));
+ y_offset += 15;
+ XDrawString(dpy, win, DefaultGC(dpy, s), x, y_offset, mh->artist, strlen(mh->artist));
+ y_offset += 15;
+ XDrawString(dpy, win, DefaultGC(dpy, s), x, y_offset, mh->album, strlen(mh->album));
+ y_offset += 15;
+ XDrawString(dpy, win, DefaultGC(dpy, s), x, y_offset, timestr, strlen(timestr));
+ y_offset += 15;
+
+
+ free(timestr);
+
+ }
+ pthread_mutex_unlock(&mh->lock);
+
+ }
+ };