Standardize battery.c
[dwm-status.git] / mpd.c
blob41fc73ab6473f398f7f73bae5b8b93f7edf30115
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 #include <assert.h>
10 #include <err.h>
11 #include <iconv.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <time.h>
16 #include <sysexits.h>
18 #include <mpd/connection.h>
19 #include <mpd/error.h>
20 #include <mpd/player.h>
21 #include <mpd/song.h>
22 #include <mpd/status.h>
23 #include <mpd/tag.h>
25 #include "buffers.h"
26 #include "mpd.h"
28 enum {
29 SLEEP = 5,
32 const char *NOTAVAILABLE = "n/a";
33 const char *NOARTIST = "unknown artist";
34 const char *NOTITLE = "unknown title";
36 struct mpd_context {
37 struct mpd_connection *conn;
38 char mpd_utf[MPD_BUFFLEN];
39 char mpd_str[MPD_BUFFLEN];
40 iconv_t cd;
41 time_t last;
44 struct mpd_context *
45 mpd_context_open()
47 struct mpd_context *ctx;
49 if ((ctx = malloc(sizeof(*ctx))) == NULL)
50 err(EX_SOFTWARE, "malloc(%d) mpd_context", sizeof(*ctx));
52 if ((ctx->cd = iconv_open("", "UTF-8")) == (iconv_t) (-1))
53 err(EX_SOFTWARE, "iconv_open");
55 ctx->conn = NULL;
56 ctx->mpd_str[0] = '\0';
57 ctx->mpd_utf[0] = '\0';
58 ctx->last = time(NULL) - SLEEP;
60 return (ctx);
63 void
64 mpd_context_close(struct mpd_context *ctx)
66 assert(ctx != NULL);
68 if (iconv_close(ctx->cd) == -1)
69 err(EX_SOFTWARE, "iconv_close");
71 if (ctx->conn != NULL)
72 mpd_connection_free(ctx->conn);
74 free(ctx);
77 char *
78 mpd_str(struct mpd_context *ctx)
80 struct mpd_song *song = NULL;
81 struct mpd_status *status = NULL;
82 const char *artist, *title;
83 char *in, *out;
84 size_t inleft, outleft;
85 time_t now;
87 assert(ctx != NULL);
89 now = time(NULL);
90 if ((now - ctx->last) < SLEEP)
91 goto exit;
92 ctx->last = now;
94 if (ctx->conn == NULL) {
95 if ((ctx->conn = mpd_connection_new(NULL, 0, 0)) == NULL) {
96 warnx("mpd_connection_new");
97 strncpy(ctx->mpd_str, NOTAVAILABLE, sizeof(ctx->mpd_str) - 1);
98 ctx->mpd_str[sizeof(ctx->mpd_str) - 1] = '\0';
99 goto exit;
102 assert(ctx->conn != NULL);
104 if ((status = mpd_run_status(ctx->conn)) == NULL) {
105 warnx("mpd_run_status: %s", mpd_connection_get_error_message(ctx->conn));
106 strncpy(ctx->mpd_str, NOTAVAILABLE, sizeof(ctx->mpd_str) - 1);
107 ctx->mpd_str[sizeof(ctx->mpd_str) - 1] = '\0';
109 mpd_connection_free(ctx->conn);
110 ctx->conn = NULL;
111 goto exit;
113 if (mpd_status_get_state(status) != MPD_STATE_PLAY) {
114 ctx->mpd_str[0] = '\0';
115 goto exit;
117 if ((song = mpd_run_current_song(ctx->conn)) == NULL) {
118 strncpy(ctx->mpd_str, NOTAVAILABLE, sizeof(ctx->mpd_str) - 1);
119 ctx->mpd_str[sizeof(ctx->mpd_str) - 1] = '\0';
120 goto exit;
122 if ((artist = mpd_song_get_tag(song, MPD_TAG_ARTIST, 0)) == NULL)
123 artist = NOARTIST;
125 if ((title = mpd_song_get_tag(song, MPD_TAG_TITLE, 0)) == NULL)
126 title = NOTITLE;
128 inleft = snprintf(ctx->mpd_utf, sizeof(ctx->mpd_utf), "%s - %s", artist, title);
130 inleft = inleft < sizeof(ctx->mpd_utf) ? inleft : (sizeof(ctx->mpd_utf) - 1);
131 outleft = sizeof(ctx->mpd_str);
132 in = (char *)ctx->mpd_utf;
133 out = (char *)ctx->mpd_str;
135 if (iconv(ctx->cd, NULL, NULL, &out, &outleft) == (size_t) (-1))
136 err(EX_SOFTWARE, "iconv");
137 while (inleft > 0) {
138 if (iconv(ctx->cd, (const char **)&in, &inleft, &out, &outleft) == (size_t) (-1)) {
139 if (errno == E2BIG)
140 break;
143 *out = '\0';
145 exit:
146 if (song != NULL)
147 mpd_song_free(song);
148 if (status != NULL)
149 mpd_status_free(status);
151 return (ctx->mpd_str);