aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCalvin Morrison <calvin@fastmailteam.com>2022-07-21 12:21:24 -0400
committerCalvin Morrison <calvin@fastmailteam.com>2022-07-21 12:21:24 -0400
commitd210af2268c29420983cdd6937affc7a2d3f5b47 (patch)
treec41b846d41863b198c1e77e3751abe4c73890929
parentd52e7aa09a792d42460b2999158fc91dcc791dfb (diff)
first attempt at talking to MOC over it's socket. Realtime updates. Only works with -R null right now. This work will go into mocicon at some point, so can provide realtime info / feedback
-rw-r--r--x11-moc-widget.c949
1 files changed, 949 insertions, 0 deletions
diff --git a/x11-moc-widget.c b/x11-moc-widget.c
new file mode 100644
index 0000000..808bd85
--- /dev/null
+++ b/x11-moc-widget.c
@@ -0,0 +1,949 @@
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xos.h>
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/utsname.h>
+
+/* Maximal socket name. */
+#define UNIX_PATH_MAX 108
+#define SOCKET_NAME "socket2"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include <assert.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <sys/un.h>
+#include <unistd.h>
+
+struct file_tags
+{
+ char *title;
+ char *artist;
+ char *album;
+ int track;
+ int time;
+ int filled; /* Which tags are filled: TAGS_COMMENTS, TAGS_TIME. */
+};
+struct event_queue
+{
+ struct event *head;
+ struct event *tail;
+};
+struct event
+{
+ int type; /* type of the event (one of EV_*) */
+ void *data; /* optional data associated with the event */
+ struct event *next;
+};
+
+/* Flags for the info decoder function. */
+enum tags_select
+{
+ TAGS_COMMENTS = 0x01, /* artist, title, etc. */
+ TAGS_TIME = 0x02 /* time of the file. */
+};
+
+
+/* Definition of events sent by server to the client. */
+#define EV_STATE 0x01 /* server has changed the state */
+#define EV_CTIME 0x02 /* current time of the song has changed */
+#define EV_SRV_ERROR 0x04 /* an error occurred */
+#define EV_BUSY 0x05 /* another client is connected to the server */
+#define EV_DATA 0x06 /* data in response to a request will arrive */
+#define EV_BITRATE 0x07 /* the bitrate has changed */
+#define EV_RATE 0x08 /* the rate has changed */
+#define EV_CHANNELS 0x09 /* the number of channels has changed */
+#define EV_EXIT 0x0a /* the server is about to exit */
+#define EV_PONG 0x0b /* response for CMD_PING */
+#define EV_OPTIONS 0x0c /* the options has changed */
+#define EV_SEND_PLIST 0x0d /* request for sending the playlist */
+#define EV_TAGS 0x0e /* tags for the current file have changed */
+#define EV_STATUS_MSG 0x0f /* followed by a status message */
+#define EV_MIXER_CHANGE 0x10 /* the mixer channel was changed */
+#define EV_FILE_TAGS 0x11 /* tags in a response for tags request */
+#define EV_AVG_BITRATE 0x12 /* average bitrate has changed (new song) */
+#define EV_AUDIO_START 0x13 /* playing of audio has started */
+#define EV_AUDIO_STOP 0x14 /* playing of audio has stopped */
+
+/* Events caused by a client that wants to modify the playlist (see
+ * CMD_CLI_PLIST* commands). */
+#define EV_PLIST_ADD 0x50 /* add an item, followed by the file name */
+#define EV_PLIST_DEL 0x51 /* delete an item, followed by the file name */
+#define EV_PLIST_MOVE 0x52 /* move an item, followed by 2 file names */
+#define EV_PLIST_CLEAR 0x53 /* clear the playlist */
+
+/* These events, though similar to the four previous are caused by server
+ * which takes care of clients' queue synchronization. */
+#define EV_QUEUE_ADD 0x54
+#define EV_QUEUE_DEL 0x55
+#define EV_QUEUE_MOVE 0x56
+#define EV_QUEUE_CLEAR 0x57
+
+/* State of the server. */
+#define STATE_PLAY 0x01
+#define STATE_STOP 0x02
+#define STATE_PAUSE 0x03
+
+/* Definition of server commands. */
+#define CMD_PLAY 0x00 /* play the first element on the list */
+#define CMD_LIST_CLEAR 0x01 /* clear the list */
+#define CMD_LIST_ADD 0x02 /* add an item to the list */
+#define CMD_STOP 0x04 /* stop playing */
+#define CMD_PAUSE 0x05 /* pause */
+#define CMD_UNPAUSE 0x06 /* unpause */
+#define CMD_SET_OPTION 0x07 /* set an option */
+#define CMD_GET_OPTION 0x08 /* get an option */
+#define CMD_GET_CTIME 0x0d /* get the current song time */
+#define CMD_GET_SNAME 0x0f /* get the stream file name */
+#define CMD_NEXT 0x10 /* start playing next song if available */
+#define CMD_QUIT 0x11 /* shutdown the server */
+#define CMD_SEEK 0x12 /* seek in the current stream */
+#define CMD_GET_STATE 0x13 /* get the state */
+#define CMD_DISCONNECT 0x15 /* disconnect from the server */
+#define CMD_GET_BITRATE 0x16 /* get the bitrate */
+#define CMD_GET_RATE 0x17 /* get the rate */
+#define CMD_GET_CHANNELS 0x18 /* get the number of channels */
+#define CMD_PING 0x19 /* request for EV_PONG */
+#define CMD_GET_MIXER 0x1a /* get the volume level */
+#define CMD_SET_MIXER 0x1b /* set the volume level */
+#define CMD_DELETE 0x1c /* delete an item from the playlist */
+#define CMD_SEND_PLIST_EVENTS 0x1d /* request for playlist events */
+#define CMD_PREV 0x20 /* start playing previous song if available */
+#define CMD_SEND_PLIST 0x21 /* send the playlist to the requesting client */
+#define CMD_GET_PLIST 0x22 /* get the playlist from one of the clients */
+#define CMD_CAN_SEND_PLIST 0x23 /* mark the client as able to send
+ playlist */
+#define CMD_CLI_PLIST_ADD 0x24 /* add an item to the client's playlist */
+#define CMD_CLI_PLIST_DEL 0x25 /* delete an item from the client's
+ playlist */
+#define CMD_CLI_PLIST_CLEAR 0x26 /* clear the client's playlist */
+#define CMD_GET_SERIAL 0x27 /* get an unique serial number */
+#define CMD_PLIST_SET_SERIAL 0x28 /* assign a serial number to the server's
+ playlist */
+#define CMD_LOCK 0x29 /* acquire a lock */
+#define CMD_UNLOCK 0x2a /* release the lock */
+#define CMD_PLIST_GET_SERIAL 0x2b /* get the serial number of the server's
+ playlist */
+#define CMD_GET_TAGS 0x2c /* get tags for the currently played file */
+#define CMD_TOGGLE_MIXER_CHANNEL 0x2d /* toggle the mixer channel */
+#define CMD_GET_MIXER_CHANNEL_NAME 0x2e /* get the mixer channel's name */
+#define CMD_GET_FILE_TAGS 0x2f /* get tags for the specified file */
+#define CMD_ABORT_TAGS_REQUESTS 0x30 /* abort previous CMD_GET_FILE_TAGS
+ requests up to some file */
+#define CMD_CLI_PLIST_MOVE 0x31 /* move an item */
+#define CMD_LIST_MOVE 0x32 /* move an item */
+#define CMD_GET_AVG_BITRATE 0x33 /* get the average bitrate */
+
+#define CMD_TOGGLE_SOFTMIXER 0x34 /* toggle use of softmixer */
+#define CMD_TOGGLE_EQUALIZER 0x35 /* toggle use of equalizer */
+#define CMD_EQUALIZER_REFRESH 0x36 /* refresh EQ-presets */
+#define CMD_EQUALIZER_PREV 0x37 /* select previous eq-preset */
+#define CMD_EQUALIZER_NEXT 0x38 /* select next eq-preset */
+
+#define CMD_TOGGLE_MAKE_MONO 0x39 /* toggle mono mixing */
+#define CMD_JUMP_TO 0x3a /* jumps to a some position in the current stream */
+#define CMD_QUEUE_ADD 0x3b /* add an item to the queue */
+#define CMD_QUEUE_DEL 0x3c /* delete an item from the queue */
+#define CMD_QUEUE_MOVE 0x3d /* move an item in the queue */
+#define CMD_QUEUE_CLEAR 0x3e /* clear the queue */
+#define CMD_GET_QUEUE 0x3f /* request the queue from the server */
+
+
+#define MAX_SEND_STRING 4096
+
+#ifndef RANGE
+#define RANGE(min, val, max) ((val) >= (min) && (val) <= (max))
+#endif
+
+// Functions
+static int fatal(char *string);
+static int server_connect ();
+void *xmalloc (size_t size);
+
+// Raw gets
+char *get_str (int sock);
+int send_int (int sock, int i);
+int get_int (int sock, int *i);
+
+//wrapper gets
+static int get_data_int();
+static int get_int_from_srv();
+static char *get_str_from_srv ();
+static void wait_for_data ();
+static void *get_event_data (const int type);
+static struct file_tags *recv_tags_from_srv();
+static struct file_tags *get_data_tags ();
+struct file_tags *tags_new ();
+void tags_free (struct file_tags *tags);
+
+// Globals.
+static int srv_sock = -1;
+char *socket_path = "/home/calvin/.moc/socket2";
+static struct event_queue events;
+
+
+
+static int fatal(char *string) {
+ fprintf(stderr, "%s\n", string);
+ exit(0);
+}
+char *sock_path() {
+ return socket_path;
+};
+static int server_connect ()
+{
+ char *path = socket_path;
+ struct sockaddr_un sock_name;
+ int sock;
+
+ /* Create a socket */
+ if ((sock = socket (PF_LOCAL, SOCK_STREAM, 0)) == -1)
+ return -1;
+
+ sock_name.sun_family = AF_LOCAL;
+ strcpy (sock_name.sun_path, sock_path());
+
+ if (connect(sock, (struct sockaddr *)&sock_name,
+ SUN_LEN(&sock_name)) == -1) {
+ close (sock);
+ fprintf(stderr, "%s at (%s)\n", strerror(errno), sock_name);
+ return -1;
+ }
+
+ return sock;
+}
+
+char *get_str (int sock)
+{
+ int len;
+ int res, nread = 0;
+ char *str;
+
+ if (!get_int(sock, &len))
+ return NULL;
+
+ if (!RANGE(0, len, MAX_SEND_STRING)) {
+ printf("Bad string length.");
+ return NULL;
+ }
+
+ str = (char *)malloc (sizeof(char) * (len + 1));
+ while (nread < len) {
+ res = recv (sock, str + nread, len - nread, 0);
+ if (res == -1) {
+ printf("recv() failed when getting string: %s\n",
+ strerror(errno));
+ free (str);
+ return NULL;
+ }
+ if (res == 0) {
+ printf("Unexpected EOF when getting string\n");
+ free (str);
+ return NULL;
+ }
+ nread += res;
+ }
+ str[len] = 0;
+
+ return str;
+}
+
+int send_str (int sock, const char *str)
+{
+ int len;
+
+ len = strlen (str);
+ if (!send_int (sock, len))
+ return 0;
+
+ if (send (sock, str, len, 0) != len)
+ return 0;
+
+ return 1;
+}
+
+int get_int (int sock, int *i)
+{
+ int res;
+
+ res = recv (sock, i, sizeof(int), 0);
+ if (res == -1)
+ printf("recv() failed when getting int: %s", strerror(errno));
+
+ return res == sizeof(int) ? 1 : 0;
+}
+
+static char *get_data_str ()
+{
+ wait_for_data ();
+ return get_str_from_srv ();
+}
+
+static int get_data_int ()
+{
+ wait_for_data ();
+ return get_int_from_srv ();
+}
+
+static void send_str_to_srv (const char *str)
+{
+ if (!send_str(srv_sock, str))
+ fatal ("Can't send() string to the server!");
+}
+
+struct file_tags *tags_new ()
+{
+ struct file_tags *tags;
+
+ tags = (struct file_tags *)xmalloc (sizeof(struct file_tags));
+ tags->title = NULL;
+ tags->artist = NULL;
+ tags->album = NULL;
+ tags->track = -1;
+ tags->time = -1;
+ tags->filled = 0;
+
+ return tags;
+}
+
+void tags_free (struct file_tags *tags)
+{
+ assert (tags != NULL);
+
+ if (tags->title)
+ free (tags->title);
+ if (tags->artist)
+ free (tags->artist);
+ if (tags->album)
+ free (tags->album);
+
+ free (tags);
+}
+
+struct file_tags *recv_tags (int sock)
+{
+ struct file_tags *tags = tags_new ();
+
+ // filename first.
+ get_str(sock);
+
+ if (!(tags->title = get_str(sock))) {
+ fprintf(stderr, "Error while receiving title\n");
+ tags_free (tags);
+ return NULL;
+ }
+
+ if (!(tags->artist = get_str(sock))) {
+ fprintf(stderr, "Error while receiving artist\n");
+ tags_free (tags);
+ return NULL;
+ }
+
+ if (!(tags->album = get_str(sock))) {
+ fprintf(stderr, "Error while receiving album\n");
+ tags_free (tags);
+ return NULL;
+ }
+
+ if (!get_int(sock, &tags->track)) {
+ fprintf(stderr, "Error while receiving track\n");
+ tags_free (tags);
+ return NULL;
+ }
+
+ if (!get_int(sock, &tags->time)) {
+ fprintf(stderr, "Error while receiving time\n");
+ tags_free (tags);
+ return NULL;
+ }
+
+ if (!get_int(sock, &tags->filled)) {
+ fprintf(stderr, "Error while receiving filled\n");
+ tags_free (tags);
+ return NULL;
+ }
+
+ /* Set NULL instead of empty tags. */
+ if (!tags->title[0]) {
+ free (tags->title);
+ tags->title = NULL;
+ }
+ if (!tags->artist[0]) {
+ free (tags->artist);
+ tags->artist = NULL;
+ }
+ if (!tags->album[0]) {
+ free (tags->album);
+ tags->album = NULL;
+ }
+
+ return tags;
+}
+
+/* Send an integer value to the socket, return == 0 on error */
+int send_int (int sock, int i)
+{
+ int res;
+
+ res = send (sock, &i, sizeof(int), 0);
+ if (res == -1)
+ printf("send() failed: %s", strerror(errno));
+
+ return res == sizeof(int) ? 1 : 0;
+}
+/* helper that doesn't require a socket */
+static void send_int_to_srv (const int num)
+{
+ if (!send_int(srv_sock, num))
+ fprintf(stderr, "Can't send() int to the server!\n");
+}
+
+/* Returned memory is malloc()ed. */
+static char *get_str_from_srv ()
+{
+ char *str = get_str (srv_sock);
+
+ if (!str)
+ fprintf(stderr,"Can't receive string from the server!\n");
+
+ return str;
+}
+
+static void *get_event_data (const int type)
+{
+ switch (type) {
+ case EV_PLIST_ADD:
+ case EV_QUEUE_ADD:
+ break;
+ // return recv_item_from_srv ();
+ case EV_PLIST_DEL:
+ case EV_QUEUE_DEL:
+ case EV_STATUS_MSG:
+ case EV_SRV_ERROR:
+ return get_str_from_srv ();
+ case EV_FILE_TAGS:
+ // return recv_tags_data_from_srv ();
+ break;
+ case EV_PLIST_MOVE:
+ break;
+ }
+
+ return NULL;
+}
+/* Get an integer value from the server that will arrive after EV_DATA. */
+static void wait_for_data ()
+{
+ int event;
+
+ do {
+ event = get_int_from_srv ();
+ if (event == EV_EXIT)
+ fatal("The server exited!");
+ if (event != EV_DATA)
+ event_push (&events, event, get_event_data(event));
+ } while (event != EV_DATA);
+}
+
+
+void *xmalloc (size_t size)
+{
+ void *p;
+
+
+ if ((p = malloc(size)) == NULL)
+ fatal ("Can't allocate memory!");
+ return p;
+}
+void event_push (struct event_queue *q, const int event, void *data)
+{
+ assert (q != NULL);
+
+ if (!q->head) {
+ q->head = (struct event *)xmalloc (sizeof(struct event));
+ q->head->next = NULL;
+ q->head->type = event;
+ q->head->data = data;
+ q->tail = q->head;
+ }
+ else {
+ assert (q->head != NULL);
+ assert (q->tail != NULL);
+ assert (q->tail->next == NULL);
+
+ q->tail->next = (struct event *)xmalloc (
+ sizeof(struct event));
+ q->tail = q->tail->next;
+ q->tail->next = NULL;
+ q->tail->type = event;
+ q->tail->data = data;
+ }
+}
+
+static int get_int_from_srv ()
+{
+ int num;
+
+ if (!get_int(srv_sock, &num))
+ fprintf(stderr, "get_int_from_srv: Can't receive value from the server!\n");
+
+ return num;
+}
+
+static struct file_tags *recv_tags_from_srv ()
+{
+ struct file_tags *tags = recv_tags (srv_sock);
+
+ if (!tags)
+ fatal ("recv_tags_from_server: Can't receive tags from the server!");
+
+ return tags;
+}
+
+static struct file_tags *get_data_tags ()
+{
+ int got_it = 0;
+
+ while (!got_it) {
+ int type = get_int_from_srv ();
+ void *data = get_event_data (type);
+
+ if (type == EV_FILE_TAGS) {
+ got_it = 1;
+ }
+ }
+ return recv_tags_from_srv ();
+}
+
+/* helper functions for getting server info */
+static int get_curr_time ()
+{
+ send_int_to_srv (CMD_GET_CTIME);
+ return get_data_int ();
+}
+
+static char *get_curr_file ()
+{
+ send_int_to_srv (CMD_GET_SNAME);
+ return get_data_str ();
+}
+
+static struct file_tags *get_tags(char *file) {
+
+ send_int_to_srv (CMD_GET_FILE_TAGS);
+ send_str_to_srv (file);
+ send_int_to_srv (TAGS_COMMENTS | TAGS_TIME);
+
+ return get_data_tags();
+
+}
+
+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;
+}
+
+
+/* Obtains the next X11 event with specified timeout. */
+ static Bool
+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;
+ }
+ }
+ }
+}
+
+
+int main(int argc, char** argv)
+{
+ Display* dpy = XOpenDisplay(NULL);
+ if (dpy == NULL)
+ {
+ fprintf(stderr, "Cannot open display\n");
+ exit(1);
+ }
+
+ srv_sock = server_connect();
+ if(srv_sock == -1) {
+ fprintf(stderr, "Can't connect to MOCP Server at: %s\n", socket_path);
+ 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);
+
+ bool uname_ok = false;
+ struct utsname sname;
+ int ret = uname(&sname);
+ if (ret != -1)
+ {
+ uname_ok = true;
+ }
+
+ while (1)
+ {
+ char *lastfile = NULL;
+ XEvent e;
+ int state;
+ int ev = -1;
+ int cmd = -1;
+
+ if (!send_int(srv_sock, CMD_GET_STATE))
+ fatal ("Can't send commands!");
+
+ if (!get_int(srv_sock, &ev)) {
+ fatal("Can't get data from the server 1.");
+ }
+ // skip other updates... wait for our data.
+ while(ev != EV_DATA) {
+ send_int(srv_sock, CMD_GET_STATE);
+ if (!get_int(srv_sock, &ev)) {
+ fprintf(stderr, "Can't get data from the server 1.\n");
+ }
+ }
+ if(!get_int(srv_sock, &state)) {
+ fatal ("Can't get state from the server!");
+ }
+
+ if (state == STATE_STOP) {
+ int got_event = XNextEventTimed(dpy, &e, 500);
+ XClearWindow(dpy, win);
+ char *no_song = "No Song is Playing.";
+ XDrawString(dpy, win, DefaultGC(dpy, s), 10, 20, no_song, strlen(no_song));
+ } else {
+
+ char *file = get_curr_file();
+
+ struct file_tags *tags= get_tags(file);
+ /*
+ printf("current_file: %s\n", file);
+ printf("current_title: %s\n", tags->title);
+
+ printf("current_artist: %s\n", tags->artist);
+ printf("current_artist: %s\n", tags->album);
+ printf("current_track: %d\n", tags->track);
+
+ printf("current_time: %s\n", time_format(get_curr_time()));
+ printf("current_length: %s\n", time_format(tags->time));
+ */
+
+ char *curt = time_format(get_curr_time());
+ char *curtt = time_format(tags->time);
+ char *timestr = xmalloc(256);
+ sprintf(timestr,"%s / %s", curt, curtt);
+
+ int got_event = XNextEventTimed(dpy, &e, 250);
+
+ XClearWindow(dpy, win);
+ int y_offset = 20;
+ int x = 10;
+ XDrawString(dpy, win, DefaultGC(dpy, s), x, y_offset, tags->title, strlen(tags->title));
+ y_offset += 15;
+ XDrawString(dpy, win, DefaultGC(dpy, s), x, y_offset, tags->artist, strlen(tags->artist));
+ y_offset += 15;
+ XDrawString(dpy, win, DefaultGC(dpy, s), x, y_offset, tags->album, strlen(tags->album));
+ y_offset += 15;
+ XDrawString(dpy, win, DefaultGC(dpy, s), x, y_offset, timestr, strlen(timestr));
+ y_offset += 15;
+
+ tags_free(tags);
+ free(file);
+ free(curt);
+ free(curtt);
+ free(timestr);
+ }
+
+ if (e.type == ButtonPress) {
+ if (state == STATE_PAUSE) {
+ cmd = CMD_UNPAUSE;
+ }
+ else if (state == STATE_PLAY) {
+ cmd = CMD_PAUSE;
+ }
+ printf("sending pause/play\n");
+ send_int(srv_sock, cmd);
+ e.type=0;
+ }
+ if (e.type == KeyPress)
+ {
+ char buf[128] = {0};
+ KeySym keysym;
+ int len = XLookupString(&e.xkey, buf, sizeof buf, &keysym, NULL);
+ if (keysym == XK_Escape)
+ break;
+ }
+
+ if ((e.type == ClientMessage) &&
+ (e.xclient.data.l[0]) == WM_DELETE_WINDOW)
+ {
+ break;
+ }
+
+ }
+
+ XDestroyWindow(dpy, win);
+ XCloseDisplay(dpy);
+ return 0;
+}
+/*
+ int main2(int argc, char** argv)
+ {
+ Display* dpy = XOpenDisplay(NULL);
+ if (dpy == NULL)
+ {
+ fprintf(stderr, "Cannot open display\n");
+ exit(1);
+ }
+
+
+ srv_sock = server_connect();
+ if(srv_sock == -1) {
+ fprintf(stderr, "Can't connect to MOCP Server at: %s\n", socket_path);
+ 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 | KeyPressMask);
+ XMapWindow(dpy, win);
+
+ XStoreName(dpy, win, "Geeks3D.com - X11 window under Linux (Mint 10)");
+
+ Atom WM_DELETE_WINDOW = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
+ XSetWMProtocols(dpy, win, &WM_DELETE_WINDOW, 1);
+
+ bool uname_ok = false;
+ struct utsname sname;
+ int ret = uname(&sname);
+ if (ret != -1)
+ {
+ uname_ok = true;
+ }
+
+ XEvent e;
+ while (1)
+ {
+ XNextEvent(dpy, &e);
+ if (e.type == Expose)
+ {
+ int y_offset = 20;
+
+ const char* s1 = "X11 test app under Linux";
+
+ const char* s2 = "(C)2012 Geeks3D.com";
+ XDrawString(dpy, win, DefaultGC(dpy, s), 10, y_offset, tags->title, strlen(tags->artist));
+ y_offset += 20;
+ XDrawString(dpy, win, DefaultGC(dpy, s), 10, y_offset, tags->artist, strlen(tags->artist));
+ y_offset += 20;
+
+ if (uname_ok)
+ {
+ char buf[256] = {0};
+
+ sprintf(buf, "System information:");
+ XDrawString(dpy, win, DefaultGC(dpy, s), 10, y_offset, buf, strlen(buf));
+ y_offset += 15;
+
+ sprintf(buf, "- System: %s", sname.sysname);
+ XDrawString(dpy, win, DefaultGC(dpy, s), 10, y_offset, buf, strlen(buf));
+ y_offset += 15;
+
+ sprintf(buf, "- Release: %s", sname.release);
+ XDrawString(dpy, win, DefaultGC(dpy, s), 10, y_offset, buf, strlen(buf));
+ y_offset += 15;
+
+ sprintf(buf, "- Version: %s", sname.version);
+ XDrawString(dpy, win, DefaultGC(dpy, s), 10, y_offset, buf, strlen(buf));
+ y_offset += 15;
+
+sprintf(buf, "- Machine: %s", sname.machine);
+XDrawString(dpy, win, DefaultGC(dpy, s), 10, y_offset, buf, strlen(buf));
+y_offset += 20;
+}
+
+
+XWindowAttributes wa;
+XGetWindowAttributes(dpy, win, &wa);
+int width = wa.width;
+int height = wa.height;
+char buf[128]={0};
+sprintf(buf, "Current window size: %dx%d", width, height);
+XDrawString(dpy, win, DefaultGC(dpy, s), 10, y_offset, buf, strlen(buf));
+y_offset += 20;
+}
+
+if (e.type == KeyPress)
+{
+ char buf[128] = {0};
+ KeySym keysym;
+ int len = XLookupString(&e.xkey, buf, sizeof buf, &keysym, NULL);
+ if (keysym == XK_Escape)
+ break;
+}
+
+if ((e.type == ClientMessage) &&
+ (e.xclient.data.l[0]) == WM_DELETE_WINDOW)
+{
+ break;
+}
+}
+
+XDestroyWindow(dpy, win);
+XCloseDisplay(dpy);
+return 0;
+} */
+/* main loop to publish on MPRIS */
+int main1() {
+
+ srv_sock = server_connect();
+ if(srv_sock == -1) {
+ fprintf(stderr, "Can't connect to MOCP Server at: %s\n", socket_path);
+ exit(1);
+ }
+
+ while(1) {
+ int state;
+ int ev = -1;
+ int cmd = -1;
+
+ if (!send_int(srv_sock, CMD_GET_STATE))
+ fatal ("Can't send commands!");
+
+ if (!get_int(srv_sock, &ev)) {
+ fatal("Can't get data from the server 1.");
+ }
+ // skip other updates... wait for our data.
+ while(ev != EV_DATA) {
+ if (!get_int(srv_sock, &ev)) {
+ fatal("Can't get data from the server 1.");
+ }
+ }
+ if(!get_int(srv_sock, &state)) {
+ fatal ("Can't get state from the server!");
+ }
+
+ if (state == STATE_STOP) {
+ fprintf(stderr, "no song playing\n");
+ exit(0);
+ }
+ //int type = get_int_from_srv ();
+ //void *data = get_event_data (type);
+
+
+ char *file = get_curr_file();
+ printf("current_file: %s\n", file);
+
+ struct file_tags *tags= get_tags(file);
+ printf("current_title: %s\n", tags->title);
+
+ printf("current_artist: %s\n", tags->artist);
+ printf("current_artist: %s\n", tags->album);
+ printf("current_track: %d\n", tags->track);
+
+ printf("current_time: %s\n", time_format(get_curr_time()));
+ printf("current_length: %s\n", time_format(tags->time));
+
+ tags_free(tags);
+ free(file);
+ sleep(1);
+
+ }
+ /* if (state == STATE_PAUSE) {
+ printf("state paused\n");
+ cmd = CMD_UNPAUSE;
+ }
+ else if (state == STATE_PLAY) {
+ printf("state paused\n");
+ cmd = CMD_PAUSE;
+ }
+
+ if (cmd != -1 && !send_int(sock, cmd))
+ fatal ("Can't send commands!");
+ if (!send_int(sock, CMD_DISCONNECT))
+ fatal ("Can't send commands!");
+ */
+}
+
+/*
+ * DBusError err;
+ DBusConnection* conn;
+ int ret;
+// initialise the errors
+dbus_error_init(&err);
+
+// connect to the bus
+conn = dbus_bus_get(DBUS_BUS_SESSION, &err);
+if (dbus_error_is_set(&err)) {
+fprintf(stderr, "Connection Error (%s)\n", err.message);
+dbus_error_free(&err);
+}
+if (NULL == conn) {
+exit(1);
+}
+ *
+ */