/[sido]/controller.c
ViewVC logotype

Contents of /controller.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 19 - (show annotations)
Sat Oct 17 00:31:21 2009 UTC (7 years, 10 months ago) by ben
File MIME type: text/plain
File size: 6024 byte(s)
only one instance of volume control
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <glib.h>
4 #include <gtk/gtk.h>
5 #include <sys/socket.h>
6 #include <unistd.h>
7 #include <arpa/inet.h>
8 #include <netinet/in.h>
9 #include <netinet/tcp.h>
10 #include <string.h>
11 #include "controller.h"
12
13 /* since we use a persistent connection, we must use a mutex
14 * as we use the same socket for parallel queres
15 */
16 static GStaticMutex TALKING = G_STATIC_MUTEX_INIT;
17
18 /* connects and returns an open socket */
19 int mpd_connect (const char* host, int port) {
20 int sockfd, ret;
21 struct sockaddr_in sock_addr;
22 struct timeval tv;
23 int yes = 1;
24 char reply[16]; /* enough for MPD OK 99.99.99 */
25
26 tv.tv_sec = 1;
27 tv.tv_usec = 0;
28
29 sockfd = socket(AF_INET, SOCK_STREAM, 0);
30 if (-1 == sockfd)
31 return -1;
32 setsockopt (sockfd, SOL_SOCKET, SO_REUSEADDR, (void*)&yes, sizeof(yes));
33 setsockopt (sockfd, SOL_SOCKET, SO_SNDTIMEO, (void*)&tv, sizeof(tv));
34 setsockopt (sockfd, SOL_SOCKET, SO_RCVTIMEO, (void*)&tv, sizeof(tv));
35 #if defined(TCP_NODELAY) && (defined(IPPROTO_TCP) || defined(SOL_TCP))
36 #ifdef SOL_TCP
37 setsockopt(sockfd,SOL_TCP,TCP_NODELAY,(void *)&yes,sizeof(yes));
38 #else
39 #ifdef IPPROTO_TCP
40 setsockopt(sockfd,IPPROTO_TCP,TCP_NODELAY,(void *)&yes,sizeof(yes));
41 #endif
42 #endif
43 #endif
44 sock_addr.sin_family = AF_INET;
45 sock_addr.sin_port = htons(port);
46 sock_addr.sin_addr.s_addr = inet_addr(host);
47 memset(&(sock_addr.sin_zero), '\0', 8);
48
49 ret = connect(sockfd, (struct sockaddr *)&sock_addr,
50 sizeof(struct sockaddr));
51 if (-1 == ret)
52 return -1;
53 /* read the MPD hello messsage */
54 ret = recv (sockfd, reply, 16, MSG_WAITALL); /* should be MSG_WAITALL */
55 if (-1 == ret) {
56 close (sockfd);
57 return -1;
58 } else {
59 return sockfd;
60 }
61 }
62
63 /* disconnect from MPD */
64 void mpd_disconnect (int sockfd) {
65
66 if (sockfd == -1)
67 return;
68 g_static_mutex_lock(&TALKING);
69 send(sockfd, "close\n", 6, 0);
70 close(sockfd);
71 g_static_mutex_unlock(&TALKING);
72 }
73
74 /* send arbitrary command to MPD */
75 gboolean mpd_control(int sockfd, const gchar *ctl) {
76 gchar* msg = NULL;
77 int ret;
78
79 if (sockfd == -1) {
80 return FALSE;
81 }
82
83 msg = g_strdup_printf("%s\n", ctl);
84 ret = send(sockfd, msg, strlen(msg), 0);
85 g_free(msg);
86 if (-1 == ret)
87 return FALSE;
88 return TRUE;
89 }
90
91 /* get current song title and artist */
92 gchar* mpd_get_song(int sockfd) {
93 int i;
94 char* buf = malloc(BUFSIZ);
95 char* b1 = NULL;
96 char* b2 = NULL;
97 char* dsp = NULL;
98 char* title = NULL;
99 char* artist = NULL;
100 int len = 0;
101
102 if (sockfd == -1) {
103 return g_strdup("not connected to MPD");
104 }
105 memset(buf, '\0', BUFSIZ);
106 g_static_mutex_lock(&TALKING);
107 /* send command */
108 len = send(sockfd, "currentsong\n", 12, 0);
109 if (-1 == len) {
110 g_static_mutex_unlock(&TALKING);
111 return g_strdup("MPD not responding");
112 }
113 while ( -1 != (len = recv (sockfd, buf, BUFSIZ, 0))) {
114 /* should be MSG_WAITALL though */
115 if (!strcmp(buf, "OK\n")) { /* empty response */
116 g_static_mutex_unlock(&TALKING);
117 return g_strdup("MPD not playing");
118 }
119 /* else find artist an title */
120 if((b2 = strstr (buf, "Artist:"))) {
121 b1 = strstr(b2, ":")+2; /* skip ': ' */
122 if (!b1)
123 b1 = &buf[len-1];
124 b2 = strstr(b1, "\n");
125 if (!b2)
126 b2 = &buf[len-1];
127 artist = malloc (b2-b1+1);
128 for (i = 0; i < b2-b1; ++i)
129 artist[i] = b1[i];
130 artist[b2-b1] = '\0';
131 }
132 if((b2 = strstr (buf, "Title:"))) {
133 b1 = strstr(b2, ":")+2; /* skip ': ' */
134 if (!b1)
135 b1 = &buf[len-1];
136 b2 = strstr(b1, "\n");
137 if (!b2)
138 b2 = &buf[len-1];
139 title = malloc (b2-b1+1);
140 for (i = 0; i< b2-b1; ++i)
141 title[i] = b1[i];
142 title[b2-b1] = '\0';
143 }
144 if((b2 = strstr (buf, "\nOK"))) break; /* end of reponse */
145 }
146 /* FIXME if artist = NULL : no message */
147 dsp = g_strconcat(artist,": ", title, NULL);
148 free (artist);
149 free (title);
150 g_static_mutex_unlock(&TALKING);
151 return dsp;
152 }
153
154 /* get volume */
155 gint mpd_get_vol(int sockfd) {
156 int ret, vol = 0;
157 char buf [BUFSIZ];
158 char* b1 = NULL;
159
160 if (sockfd == -1) {
161 return 0;
162 }
163
164 memset(buf, '\0', BUFSIZ);
165 g_static_mutex_lock(&TALKING);
166 ret = send(sockfd, "status\n", 7, 0);
167 if (-1 == ret) {
168 g_static_mutex_unlock(&TALKING);
169 return 0;
170 }
171 while (-1 != (ret = recv(sockfd, buf, BUFSIZ, 0))) {
172 if (11 > strlen(buf)) { /* get enough bytes for volume: xxx */
173 continue;
174 }
175 b1 = strstr(buf, "volume: ");
176 if (b1) {
177 b1 += strlen("volume: "); /* position after ': ' */
178 if ((b1-buf) < BUFSIZ) /* avoid reading outside */
179 vol = atoi(b1);
180 }
181 if (strstr(buf, "\nOK")) break; /* end of response reached */
182 }
183 g_static_mutex_unlock(&TALKING);
184 return vol;
185 }
186
187 /* free everything and quit gtk+ loop */
188 void quit(AppData* d) {
189 g_free(d->config_path);
190 g_free(d->ip);
191 gtk_main_quit();
192 }
193
194 /* read configuration file */
195 void read_config (AppData* d) {
196 GKeyFile* kf = NULL;
197 GError* error = NULL;
198
199 kf = g_key_file_new();
200 g_key_file_load_from_file(kf, d->config_path, G_KEY_FILE_NONE, &error);
201 if(error) {
202 g_free(d->ip);
203 d->ip = g_strdup("127.0.0.1");
204 d->port = 6600;
205 write_config(d);
206 g_error_free(error);
207 error = NULL;
208 g_key_file_load_from_file(kf, d->config_path, G_KEY_FILE_NONE, &error);
209 }
210 d->ip = g_strdup(g_key_file_get_value (kf, "mpd", "ip", &error));
211 if(error) {
212 g_warning("read_config: %s\n", error->message);
213 g_error_free(error);
214 error = NULL;
215 }
216 d->port = g_key_file_get_integer(kf, "mpd", "port", &error);
217 if(error) {
218 g_warning("read_config: %s\n", error->message);
219 g_error_free(error);
220 error = NULL;
221 }
222 g_key_file_free(kf);
223 if (!d->ip || d->ip[0] == '\0') {
224 g_free(d->ip);
225 d->ip = g_strdup("127.0.0.1");
226 }
227 if (!d->port) {
228 d->port = 6600;
229 }
230 }
231
232 /* write configuration to file */
233 void write_config (AppData* d) {
234 GKeyFile* kf = NULL;
235 gchar* data = NULL;
236 gsize len;
237 FILE* fp = NULL;
238
239 kf = g_key_file_new();
240 g_key_file_set_value (kf, "mpd", "ip", d->ip);
241 g_key_file_set_integer (kf, "mpd", "port", d->port);
242 data = g_key_file_to_data(kf, &len, NULL);
243 fp = fopen(d->config_path, "w");
244 /* FIXME: check error (disk full, e.g.) */
245 fputs(data, fp);
246 fclose(fp);
247 g_free(data);
248 }
249

  ViewVC Help
Powered by ViewVC 1.1.26