Standardize mpd.c
[dwm-status.git] / mpd.c
blob6d6a21097bd923aa585ff0ad8be5e27f26ce354d
1 /*-
2 * "THE BEER-WARE LICENSE" (Revision 42):
3 * <tobias.rehbein@web.de> wrote this file. As long as you retain this notice
4 * you can do whatever you want with this stuff. If we meet some day, and you
5 * think this stuff is worth it, you can buy me a beer in return.
6 * Tobias Rehbein
7 */
9 #define _POSIX_C_SOURCE 199506
11 #include <assert.h>
12 #include <err.h>
13 #include <iconv.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <time.h>
18 #include <sysexits.h>
20 #include <mpd/connection.h>
21 #include <mpd/error.h>
22 #include <mpd/player.h>
23 #include <mpd/song.h>
24 #include <mpd/status.h>
25 #include <mpd/tag.h>
27 #include "buffers.h"
28 #include "mpd.h"
29 #include "tools.h"
31 enum {
32 SLEEP = 5,
35 const char *NOTAVAILABLE = "n/a";
36 const char *NOARTIST = "unknown artist";
37 const char *NOTITLE = "unknown title";
39 struct mpd_context {
40 struct mpd_connection *conn;
41 char mpd_utf[MPD_BUFFLEN];
42 char mpd_str[MPD_BUFFLEN];
43 iconv_t cd;
44 time_t last;
47 struct mpd_context *
48 mpd_context_open()
50 struct mpd_context *ctx;
52 if ((ctx = malloc(sizeof(*ctx))) == NULL)
53 err(EX_SOFTWARE, "malloc(%d) mpd_context", sizeof(*ctx));
55 if ((ctx->cd = iconv_open("", "UTF-8")) == (iconv_t) (-1))
56 err(EX_SOFTWARE, "iconv_open");
58 ctx->conn = NULL;
59 ctx->mpd_str[0] = '\0';
60 ctx->mpd_utf[0] = '\0';
61 ctx->last = time(NULL) - SLEEP;
63 return (ctx);
66 void
67 mpd_context_close(struct mpd_context *ctx)
69 assert(ctx != NULL);
71 if (iconv_close(ctx->cd) == -1)
72 err(EX_SOFTWARE, "iconv_close");
74 if (ctx->conn != NULL)
75 mpd_connection_free(ctx->conn);
77 free(ctx);
80 char *
81 mpd_str(struct mpd_context *ctx)
83 struct mpd_song *song = NULL;
84 struct mpd_status *status = NULL;
85 const char *artist, *title;
86 char *in, *out;
87 size_t inleft, outleft;
88 time_t now;
90 assert(ctx != NULL);
92 now = time(NULL);
93 if ((now - ctx->last) < SLEEP)
94 goto exit;
95 ctx->last = now;
97 if (ctx->conn == NULL) {
98 if ((ctx->conn = mpd_connection_new(NULL, 0, 0)) == NULL) {
99 warnx("mpd_connection_new");
100 strncpy(ctx->mpd_str, NOTAVAILABLE, sizeof(ctx->mpd_str) - 1);
101 ctx->mpd_str[sizeof(ctx->mpd_str) - 1] = '\0';
102 goto exit;
105 assert(ctx->conn != NULL);
107 if ((status = mpd_run_status(ctx->conn)) == NULL) {
108 warnx("mpd_run_status: %s", mpd_connection_get_error_message(ctx->conn));
109 strncpy(ctx->mpd_str, NOTAVAILABLE, sizeof(ctx->mpd_str) - 1);
110 ctx->mpd_str[sizeof(ctx->mpd_str) - 1] = '\0';
112 mpd_connection_free(ctx->conn);
113 ctx->conn = NULL;
114 goto exit;
116 if (mpd_status_get_state(status) != MPD_STATE_PLAY) {
117 ctx->mpd_str[0] = '\0';
118 goto exit;
120 if ((song = mpd_run_current_song(ctx->conn)) == NULL) {
121 strncpy(ctx->mpd_str, NOTAVAILABLE, sizeof(ctx->mpd_str) - 1);
122 ctx->mpd_str[sizeof(ctx->mpd_str) - 1] = '\0';
123 goto exit;
125 if ((artist = mpd_song_get_tag(song, MPD_TAG_ARTIST, 0)) == NULL)
126 artist = NOARTIST;
128 if ((title = mpd_song_get_tag(song, MPD_TAG_TITLE, 0)) == NULL)
129 title = NOTITLE;
131 inleft = tools_catitems(ctx->mpd_utf, sizeof(ctx->mpd_utf), artist, " - ", title, NULL);
133 inleft = inleft < sizeof(ctx->mpd_utf) ? inleft : (sizeof(ctx->mpd_utf) - 1);
134 outleft = sizeof(ctx->mpd_str);
135 in = (char *)ctx->mpd_utf;
136 out = (char *)ctx->mpd_str;
138 if (iconv(ctx->cd, NULL, NULL, &out, &outleft) == (size_t) (-1))
139 err(EX_SOFTWARE, "iconv");
140 while (inleft > 0) {
141 if (iconv(ctx->cd, (const char **)&in, &inleft, &out, &outleft) == (size_t) (-1)) {
142 if (errno == E2BIG)
143 break;
146 *out = '\0';
148 exit:
149 if (song != NULL)
150 mpd_song_free(song);
151 if (status != NULL)
152 mpd_status_free(status);
154 return (ctx->mpd_str);