Add xterm-white.theme
[cmus.git] / main.c
blobc01cf63aa80db0cde7837b37ede0decd7cecc424
1 /*
2 * Copyright 2005-2006 Timo Hirvonen
3 */
5 #include <prog.h>
6 #include <file.h>
7 #include <path.h>
8 #include <xmalloc.h>
9 #include "config/version.h"
11 #include <unistd.h>
12 #include <fcntl.h>
13 #include <sys/un.h>
14 #include <sys/types.h>
15 #include <sys/socket.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <stdarg.h>
19 #include <errno.h>
21 static int sock;
22 static int raw_args = 0;
24 static void remote_connect(const char *server)
26 struct sockaddr_un addr;
28 sock = socket(PF_UNIX, SOCK_STREAM, 0);
29 if (sock == -1)
30 die_errno("socket");
31 addr.sun_family = AF_UNIX;
32 strncpy(addr.sun_path, server, sizeof(addr.sun_path) - 1);
33 if (connect(sock, (struct sockaddr *)&addr, sizeof(addr))) {
34 if (errno == ENOENT || errno == ECONNREFUSED) {
35 /* "cmus-remote -C" can be used to check if cmus is running */
36 if (!raw_args)
37 warn("cmus is not running\n");
38 exit(1);
40 die_errno("connect");
44 static void write_line(const char *line)
46 if (write_all(sock, line, strlen(line)) == -1)
47 die_errno("write");
50 static void send_cmd(const char *format, ...)
52 char buf[512];
53 va_list ap;
55 va_start(ap, format);
56 vsnprintf(buf, sizeof(buf), format, ap);
57 va_end(ap);
59 write_line(buf);
62 static char *file_url_absolute(const char *str)
64 char *absolute;
66 if (strncmp(str, "http://", 7) == 0)
67 return xstrdup(str);
69 absolute = path_absolute(str);
70 if (absolute == NULL)
71 die_errno("get_current_dir_name");
72 return absolute;
75 enum flags {
76 FLAG_SERVER,
77 FLAG_HELP,
78 FLAG_VERSION,
80 FLAG_PLAY,
81 FLAG_PAUSE,
82 FLAG_STOP,
83 FLAG_NEXT,
84 FLAG_PREV,
85 FLAG_FILE,
86 FLAG_REPEAT,
87 FLAG_SHUFFLE,
88 FLAG_VOLUME,
89 FLAG_SEEK,
91 FLAG_LIBRARY,
92 FLAG_PLAYLIST,
93 FLAG_QUEUE,
94 FLAG_CLEAR,
96 FLAG_RAW
97 #define NR_FLAGS (FLAG_RAW + 1)
100 static struct option options[NR_FLAGS + 1] = {
101 { 0, "server", 1 },
102 { 0, "help", 0 },
103 { 0, "version", 0 },
105 { 'p', "play", 0 },
106 { 'u', "pause", 0 },
107 { 's', "stop", 0 },
108 { 'n', "next", 0 },
109 { 'r', "prev", 0 },
110 { 'f', "file", 1 },
111 { 'R', "repeat", 0 },
112 { 'S', "shuffle", 0 },
113 { 'v', "volume", 1 },
114 { 'k', "seek", 1 },
116 { 'l', "library", 0 },
117 { 'P', "playlist", 0 },
118 { 'q', "queue", 0 },
119 { 'c', "clear", 0 },
121 { 'C', "raw", 0 },
122 { 0, NULL, 0 }
125 static int flags[NR_FLAGS] = { 0, };
127 static const char *usage =
128 "Usage: %s [OPTION]... [FILE|DIR|PLAYLIST]...\n"
129 " or: %s -C COMMAND...\n"
130 " or: %s\n"
131 "Control cmus through socket.\n"
132 "\n"
133 " --server SOCKET connect using socket SOCKET instead of /tmp/cmus-$USER\n"
134 " --help display this help and exit\n"
135 " --version " VERSION "\n"
136 "\n"
137 "Cooked mode:\n"
138 " -p, --play player-play\n"
139 " -u, --pause player-pause\n"
140 " -s, --stop player-stop\n"
141 " -n, --next player-next\n"
142 " -r, --prev player-prev\n"
143 " -f, --file player-play FILE\n"
144 " -R, --repeat toggle repeat\n"
145 " -S, --shuffle toggle shuffle\n"
146 " -v, --volume VOL vol VOL\n"
147 " -k, --seek SEEK seek SEEK\n"
148 "\n"
149 " -l, --library modify library instead of playlist\n"
150 " -P, --playlist modify playlist (default)\n"
151 " -q, --queue modify play queue instead of playlist\n"
152 " -c, --clear clear playlist, library (-l) or play queue (-q)\n"
153 "\n"
154 " Add FILE/DIR/PLAYLIST to playlist, library (-l) or play queue (-q).\n"
155 "\n"
156 "Raw mode:\n"
157 " -C, --raw treat arguments (instead of stdin) as raw commands\n"
158 "\n"
159 " By default cmus-remote reads raw commands from stdin (one command per line).\n"
160 "\n"
161 "Report bugs to <cmus-devel@lists.sourceforge.net>.\n";
163 int main(int argc, char *argv[])
165 char server_buf[256];
166 char *server = NULL;
167 char *play_file = NULL;
168 char *volume = NULL;
169 char *seek = NULL;
170 int i, nr_cmds = 0;
171 int context = 'p';
173 program_name = argv[0];
174 argv++;
175 while (1) {
176 int idx;
177 char *arg;
179 idx = get_option(&argv, options, &arg);
180 if (idx < 0)
181 break;
183 flags[idx] = 1;
184 switch ((enum flags)idx) {
185 case FLAG_HELP:
186 printf(usage, program_name, program_name, program_name);
187 return 0;
188 case FLAG_VERSION:
189 printf("cmus " VERSION "\nCopyright 2004-2006 Timo Hirvonen\n");
190 return 0;
191 case FLAG_SERVER:
192 server = arg;
193 break;
194 case FLAG_VOLUME:
195 volume = arg;
196 nr_cmds++;
197 break;
198 case FLAG_SEEK:
199 seek = arg;
200 nr_cmds++;
201 break;
202 case FLAG_FILE:
203 play_file = arg;
204 nr_cmds++;
205 break;
206 case FLAG_LIBRARY:
207 context = 'l';
208 break;
209 case FLAG_PLAYLIST:
210 context = 'p';
211 break;
212 case FLAG_QUEUE:
213 context = 'q';
214 break;
215 case FLAG_PLAY:
216 case FLAG_PAUSE:
217 case FLAG_STOP:
218 case FLAG_NEXT:
219 case FLAG_PREV:
220 case FLAG_REPEAT:
221 case FLAG_SHUFFLE:
222 case FLAG_CLEAR:
223 nr_cmds++;
224 break;
225 case FLAG_RAW:
226 raw_args = 1;
227 break;
231 if (nr_cmds && raw_args)
232 die("don't mix raw and cooked stuff\n");
234 if (server == NULL) {
235 const char *home = getenv("HOME");
237 if (!home)
238 die("error: environment variable HOME not set\n");
239 snprintf(server_buf, sizeof(server_buf), "%s/.cmus/socket", home);
240 server = server_buf;
243 remote_connect(server);
245 if (raw_args) {
246 while (*argv)
247 send_cmd("%s\n", *argv++);
248 return 0;
251 if (nr_cmds == 0 && argv[0] == NULL) {
252 char line[512];
254 while (fgets(line, sizeof(line), stdin))
255 write_line(line);
256 return 0;
259 if (flags[FLAG_CLEAR])
260 send_cmd("clear -%c\n", context);
261 for (i = 0; argv[i]; i++) {
262 char *filename = file_url_absolute(argv[i]);
264 send_cmd("add -%c %s\n", context, filename);
265 free(filename);
267 if (flags[FLAG_REPEAT])
268 send_cmd("toggle repeat\n");
269 if (flags[FLAG_SHUFFLE])
270 send_cmd("toggle shuffle\n");
271 if (flags[FLAG_STOP])
272 send_cmd("player-stop\n");
273 if (flags[FLAG_NEXT])
274 send_cmd("player-next\n");
275 if (flags[FLAG_PREV])
276 send_cmd("player-prev\n");
277 if (flags[FLAG_PLAY])
278 send_cmd("player-play\n");
279 if (flags[FLAG_PAUSE])
280 send_cmd("player-pause\n");
281 if (flags[FLAG_FILE])
282 send_cmd("player-play %s\n", file_url_absolute(play_file));
283 if (volume)
284 send_cmd("vol %s\n", volume);
285 if (seek)
286 send_cmd("seek %s\n", seek);
287 return 0;