File: | vitunes.c |
Location: | line 521, column 4 |
Description: | Value stored to 'argv' is never read |
1 | /* |
2 | * Copyright (c) 2010, 2011 Ryan Flannery <ryan.flannery@gmail.com> |
3 | * |
4 | * Permission to use, copy, modify, and distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above |
6 | * copyright notice and this permission notice appear in all copies. |
7 | * |
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ |
16 | |
17 | #include "vitunes.h" |
18 | #include "config.h" /* NOTE: must be after vitunes.h */ |
19 | #include "socket.h" |
20 | |
21 | /***************************************************************************** |
22 | * GLOBALS, EXPORTED |
23 | ****************************************************************************/ |
24 | |
25 | /* key playlists to keep track of */ |
26 | playlist *viewing_playlist; |
27 | playlist *playing_playlist; |
28 | |
29 | /* visual mode start position */ |
30 | int visual_mode_start = -1; |
31 | |
32 | /* signal flags */ |
33 | volatile sig_atomic_t VSIG_QUIT = 0; /* 1 = quit vitunes */ |
34 | volatile sig_atomic_t VSIG_RESIZE = 0; /* 1 = resize display */ |
35 | volatile sig_atomic_t VSIG_SIGCHLD = 0; /* 1 = got sigchld */ |
36 | volatile sig_atomic_t VSIG_PLAYER_MONITOR = 0; /* 1 = update player stats */ |
37 | |
38 | /* |
39 | * enum used for QUIT_CAUSE values. Currently only one is used, but might add |
40 | * more. see the end of the main function and the signal_handler for how/why |
41 | * this is used. |
42 | */ |
43 | enum { EXIT_NORMAL, BAD_PLAYER }; |
44 | volatile sig_atomic_t QUIT_CAUSE = EXIT_NORMAL; |
45 | |
46 | /* used with -DDEBUG */ |
47 | FILE *debug_log; |
48 | |
49 | |
50 | /***************************************************************************** |
51 | * GLOBALS, LOCAL |
52 | ****************************************************************************/ |
53 | |
54 | /* location patterns of various things (%s is user's home directory) */ |
55 | const char *VITUNES_DIR_FMT = "%s/.vitunes"; |
56 | const char *CONF_FILE_FMT = "%s/.vitunes/vitunes.conf"; |
57 | const char *DB_FILE_FMT = "%s/.vitunes/vitunes.db"; |
58 | const char *PLAYLIST_DIR_FMT = "%s/.vitunes/playlists"; |
59 | |
60 | /* absolute paths of key stuff */ |
61 | char *vitunes_dir; |
62 | char *conf_file; |
63 | char *db_file; |
64 | char *playlist_dir; |
65 | char *player_backend; |
66 | |
67 | /* program name with directories removed */ |
68 | char *progname; |
69 | |
70 | |
71 | /***************************************************************************** |
72 | * local functions |
73 | ****************************************************************************/ |
74 | |
75 | /* misc. functions */ |
76 | int handle_switches(int argc, char *argv[]); |
77 | void usage(void); |
78 | void signal_handler(int); |
79 | void setup_timer(); |
80 | |
81 | |
82 | int |
83 | main(int argc, char *argv[]) |
84 | { |
85 | char *home; |
86 | int previous_command; |
87 | int input; |
88 | int sock = -1; |
89 | fd_set fds; |
90 | struct passwd *pw; |
91 | |
92 | /* save program name for later use */ |
93 | if ((progname = strrchr(argv[0], '/')) == NULL((void *)0)) |
94 | progname = argv[0]; |
95 | else |
96 | progname++; |
97 | |
98 | #ifdef DEBUG |
99 | if ((debug_log = fopen("vitunes-debug.log", "w")) == NULL((void *)0)) |
100 | err(1, "failed to open debug log"); |
101 | #endif |
102 | |
103 | /*------------------------------------------------------------------------ |
104 | * build paths names needed by vitunes & handle switches |
105 | *----------------------------------------------------------------------*/ |
106 | |
107 | /* get home dir */ |
108 | if ((home = getenv("HOME")) == NULL((void *)0) || *home == '\0') { |
109 | if ((pw = getpwuid(getuid())) == NULL((void *)0)) |
110 | errx(1, "Couldn't determine home directory. Can't find my config files."); |
111 | home = pw->pw_dir; |
112 | } |
113 | |
114 | /* build paths & other needed strings */ |
115 | if (asprintf(&vitunes_dir, VITUNES_DIR_FMT, home) == -1) |
116 | err(1, "main: asprintf failed"); |
117 | if (asprintf(&conf_file, CONF_FILE_FMT, home) == -1) |
118 | err(1, "main: asprintf failed"); |
119 | if (asprintf(&db_file, DB_FILE_FMT, home) == -1) |
120 | err(1, "main: asprintf failed"); |
121 | if (asprintf(&playlist_dir, PLAYLIST_DIR_FMT, home) == -1) |
122 | err(1, "main: asprintf failed"); |
123 | if (asprintf(&player_backend, "%s", DEFAULT_PLAYER_BACKEND) == -1) |
124 | err(1, "main: asprintf failed"); |
125 | |
126 | /* handle command-line switches & e-commands */ |
127 | handle_switches(argc, argv); |
128 | |
129 | if(sock_send_msg(VITUNES_RUNNING"WHOWASPHONE?") != -1) { |
130 | printf("Vitunes appears to be running already. Won't open socket."); |
131 | } else { |
132 | if((sock = sock_listen()) == -1) |
133 | errx(1, "failed to open socket."); |
134 | } |
135 | |
136 | |
137 | /* |
138 | * IF we've reached here, then there were no e-commands. |
139 | * start vitunes normally... |
140 | */ |
141 | |
142 | |
143 | /*------------------------------------------------------------------------ |
144 | * initialize stuff |
145 | *--------------------------------------------------------------------- */ |
146 | |
147 | /* setup signal handlers (XXX must be before player_init) */ |
148 | signal(SIGPIPE13, SIG_IGN(void (*)(int))1); /* broken pipe with child (ignore) */ |
149 | signal(SIGCHLD20, signal_handler); /* child died */ |
150 | signal(SIGHUP1, signal_handler); /* quit */ |
151 | signal(SIGINT2, signal_handler); /* quit */ |
152 | signal(SIGQUIT3, signal_handler); /* quit */ |
153 | signal(SIGTERM15, signal_handler); /* quit */ |
154 | signal(SIGWINCH28, signal_handler); /* resize */ |
155 | setup_timer(); /* periodic timer to update player */ |
156 | |
157 | /* init small stuff (XXX some must be done before medialib_load) */ |
158 | mi_query_init(); /* global query description */ |
159 | mi_sort_init(); /* global sort description */ |
160 | mi_display_init(); /* global display description */ |
161 | ybuffer_init(); /* global yank/copy buffer */ |
162 | toggleset_init(); /* global toggleset (list of toggle-lists) */ |
163 | |
164 | /* load media library (database and all playlists) & sort */ |
165 | medialib_load(db_file, playlist_dir); |
166 | if (mdb.library->nfiles == 0) { |
167 | printf("The vitunes database is currently empty.\n"); |
168 | printf("See 'vitunes -e help add' for how to add files.\n"); |
169 | return 0; |
170 | } |
171 | |
172 | /* apply default sort to library */ |
173 | qsort(mdb.library->files, mdb.library->nfiles, sizeof(meta_info*), mi_compare); |
174 | |
175 | /* start media player child */ |
176 | player_init(player_backend, paint_message, paint_error); |
177 | player_info.mode = DEFAULT_PLAYER_MODE; |
178 | atexit(player_destroy); |
179 | |
180 | /* setup user interface and default colors */ |
181 | kb_init(); |
182 | ui_init(DEFAULT_LIBRARY_WINDOW_WIDTH); |
183 | paint_setup_colors(); |
184 | |
185 | /* basic ui setup to get ui started */ |
186 | setup_viewing_playlist(mdb.library); |
187 | ui.library->nrows = mdb.nplaylists; |
188 | playing_playlist = NULL((void *)0); |
189 | |
190 | /* load config file and run commands in it now */ |
191 | load_config(); |
192 | |
193 | /* initial painting of the display */ |
194 | paint_all(); |
195 | |
196 | /* ----------------------------------------------------------------------- |
197 | * begin input loop |
198 | * -------------------------------------------------------------------- */ |
199 | |
200 | previous_command = -1; |
201 | while (!VSIG_QUIT) { |
202 | struct timeval tv; |
203 | |
204 | /* handle any signal flags */ |
205 | process_signals(); |
206 | |
207 | tv.tv_sec = 1; |
208 | tv.tv_usec = 0; |
209 | |
210 | FD_ZERO(&fds)do { fd_set *_p = (&fds); __size_t _n = (((1024) + ((((unsigned )(sizeof(__fd_mask) * 8))) - 1)) / (((unsigned)(sizeof(__fd_mask ) * 8)))); while (_n > 0) _p->fds_bits[--_n] = 0; } while (0); |
211 | FD_SET(0, &fds)((&fds)->fds_bits[(0) / ((unsigned)(sizeof(__fd_mask) * 8))] |= (1U << ((0) % ((unsigned)(sizeof(__fd_mask) * 8 ))))); |
212 | if(sock > 0) |
213 | FD_SET(sock, &fds)((&fds)->fds_bits[(sock) / ((unsigned)(sizeof(__fd_mask ) * 8))] |= (1U << ((sock) % ((unsigned)(sizeof(__fd_mask ) * 8))))); |
214 | errno(*__errno()) = 0; |
215 | if(select((sock > 0 ? sock : 0) + 1, &fds, NULL((void *)0), NULL((void *)0), &tv) == -1) { |
216 | if(errno(*__errno()) == 0 || errno(*__errno()) == EINTR4) |
217 | continue; |
218 | break; |
219 | } |
220 | |
221 | if(sock > 0) { |
222 | if(FD_ISSET(sock, &fds)((&fds)->fds_bits[(sock) / ((unsigned)(sizeof(__fd_mask ) * 8))] & (1U << ((sock) % ((unsigned)(sizeof(__fd_mask ) * 8)))))) |
223 | sock_recv_and_exec(sock); |
224 | } |
225 | |
226 | if(FD_ISSET(0, &fds)((&fds)->fds_bits[(0) / ((unsigned)(sizeof(__fd_mask) * 8))] & (1U << ((0) % ((unsigned)(sizeof(__fd_mask) * 8)))))) { |
227 | /* handle any available input */ |
228 | if ((input = getch()wgetch(stdscr)) && input != ERR(-1)) { |
229 | if (isdigit(input) && (input != '0' || gnum_get() > 0)) |
230 | gnum_add(input - '0'); |
231 | else if (input == '\n' && gnum_get() > 0 && previous_command >= 0) |
232 | kb_execute(previous_command); |
233 | else |
234 | kb_execute(input); |
235 | } |
236 | } |
237 | } |
238 | |
239 | /* ----------------------------------------------------------------------- |
240 | * cleanup |
241 | * -------------------------------------------------------------------- */ |
242 | |
243 | ui_destroy(); |
244 | player_destroy(); |
245 | medialib_destroy(); |
246 | |
247 | mi_query_clear(); |
248 | ybuffer_free(); |
249 | toggleset_free(); |
250 | |
251 | /* do we have any odd cause for quitting? */ |
252 | if (QUIT_CAUSE != EXIT_NORMAL) { |
253 | switch (QUIT_CAUSE) { |
254 | case BAD_PLAYER: |
255 | warnx("It appears the media player is misbehaving. Apologies."); |
256 | break; |
257 | } |
258 | } |
259 | |
260 | return 0; |
261 | } |
262 | |
263 | /* print proper usage */ |
264 | void |
265 | usage(void) |
266 | { |
267 | fprintf(stderr(&__sF[2]),"\ |
268 | usage: %s [-f config-file] [-d database-file] [-p playlist-dir] [-m player-path] [-e COMMAND ...]\n\ |
269 | See \"%s -e help\" for information about what e-commands are available.\n\ |
270 | ", |
271 | progname, progname); |
272 | exit(1); |
273 | } |
274 | |
275 | /* actual signal handler */ |
276 | void |
277 | signal_handler(int sig) |
278 | { |
279 | switch (sig) { |
280 | case SIGHUP1: |
281 | case SIGINT2: |
282 | case SIGQUIT3: |
283 | case SIGTERM15: |
284 | VSIG_QUIT = 1; |
285 | break; |
286 | case SIGALRM14: |
287 | VSIG_PLAYER_MONITOR = 1; |
288 | break; |
289 | case SIGWINCH28: |
290 | VSIG_RESIZE = 1; |
291 | break; |
292 | case SIGCHLD20: |
293 | VSIG_SIGCHLD = 1; |
294 | break; |
295 | } |
296 | } |
297 | |
298 | /* handle any signal flags */ |
299 | void |
300 | process_signals() |
301 | { |
302 | /* cppcheck-suppress variableScope */ |
303 | static playlist *prev_queue = NULL((void *)0); |
304 | /* cppcheck-suppress variableScope */ |
305 | static int prev_qidx = -1; |
306 | /* cppcheck-suppress variableScope */ |
307 | static bool_Bool prev_is_playing = false0; |
308 | /* cppcheck-suppress variableScope */ |
309 | static float prev_volume = -1; |
310 | |
311 | /* handle resize event */ |
312 | if (VSIG_RESIZE) { |
313 | ui_resize(); |
314 | ui_clear(); |
315 | paint_all(); |
316 | VSIG_RESIZE = 0; |
317 | } |
318 | |
319 | /* monitor player */ |
320 | if (VSIG_PLAYER_MONITOR) { |
321 | player_monitor(); |
322 | |
323 | if (prev_is_playing || player.playing()) |
324 | paint_player(); |
325 | |
326 | /* need to repaint anything else? */ |
327 | if (prev_is_playing != player.playing()) { |
328 | paint_library(); |
329 | paint_playlist(); |
330 | } else if (prev_queue != player_info.queue) { |
331 | paint_library(); |
332 | if (prev_queue == viewing_playlist) { |
333 | paint_playlist(); |
334 | } |
335 | } |
336 | if (player_info.queue == viewing_playlist |
337 | && prev_qidx != player_info.qidx) { |
338 | paint_playlist(); |
339 | } |
340 | if (prev_volume != player.volume()) { |
341 | paint_message("volume: %3.0f%%", player.volume()); |
342 | prev_volume = player.volume(); |
343 | } |
344 | |
345 | prev_queue = player_info.queue; |
346 | prev_qidx = player_info.qidx; |
347 | prev_is_playing = player.playing(); |
348 | VSIG_PLAYER_MONITOR = 0; |
349 | } |
350 | |
351 | /* restart player if needed */ |
352 | if (VSIG_SIGCHLD) { |
353 | if (player.sigchld != NULL((void *)0)) player.sigchld(); |
354 | VSIG_SIGCHLD = 0; |
355 | } |
356 | } |
357 | |
358 | /* setup timer signal handler above */ |
359 | void |
360 | setup_timer() |
361 | { |
362 | struct sigaction sig_act; |
363 | struct itimerval timer; |
364 | |
365 | /* create timer signal handler */ |
366 | if (sigemptyset(&sig_act.sa_mask)(*(&sig_act.sa_mask) = 0, 0) < 0) |
367 | err(1, "setup_timer: sigemptyset failed"); |
368 | |
369 | sig_act.sa_flags = 0; |
370 | sig_act.sa_handler__sigaction_u.__sa_handler = signal_handler; |
371 | if (sigaction(SIGALRM14, &sig_act, NULL((void *)0)) < 0) |
372 | err(1, "setup_timer: sigaction failed"); |
373 | |
374 | /* setup timer details */ |
375 | timer.it_value.tv_sec = 0; |
376 | timer.it_value.tv_usec = 500000; /* 1 half-second */ |
377 | timer.it_interval.tv_sec = 0; |
378 | timer.it_interval.tv_usec = 500000; /* 1 half-second */ |
379 | |
380 | /* register timer */ |
381 | if (setitimer(ITIMER_REAL0, &timer, NULL((void *)0)) < 0) |
382 | err(1, "setup_timer: setitimer failed"); |
383 | } |
384 | |
385 | /* |
386 | * load config file and execute all command-mode commands within. |
387 | * XXX note that this requires mdb, ui, and player to all be loaded/setup |
388 | */ |
389 | void |
390 | load_config() |
391 | { |
392 | const char *errmsg = NULL((void *)0); |
393 | size_t length, linenum; |
394 | FILE *fin; |
395 | char *line; |
396 | char *copy; |
397 | char **argv; |
398 | int argc; |
399 | bool_Bool found; |
400 | int found_idx = 0; |
401 | int num_matches; |
402 | int i, ret; |
403 | |
404 | if ((fin = fopen(conf_file, "r")) == NULL((void *)0)) |
405 | return; |
406 | |
407 | linenum = 0; |
408 | while (!feof(fin)(!__isthreaded ? (((fin)->_flags & 0x0020) != 0) : (feof )(fin))) { |
409 | |
410 | /* get next line */ |
411 | if ((line = fparseln(fin, &length, &linenum, NULL((void *)0), 0)) == NULL((void *)0)) { |
412 | if (ferror(fin)(!__isthreaded ? (((fin)->_flags & 0x0040) != 0) : (ferror )(fin))) |
413 | err(1, "error reading config file '%s'", conf_file); |
414 | else |
415 | break; |
416 | } |
417 | |
418 | /* skip whitespace */ |
419 | copy = line; |
420 | copy += strspn(copy, " \t\n"); |
421 | if (copy[0] == '\0') { |
422 | free(line); |
423 | continue; |
424 | } |
425 | |
426 | /* parse line into argc/argv */ |
427 | if (str2argv(copy, &argc, &argv, &errmsg) != 0) { |
428 | endwin(); |
429 | errx(1, "%s line %zd: parse error: %s", conf_file, linenum, errmsg); |
430 | } |
431 | |
432 | /* run command */ |
433 | found = false0; |
434 | num_matches = 0; |
435 | for (i = 0; i < CommandPathSize; i++) { |
436 | if (match_command_name(argv[0], CommandPath[i].name)) { |
437 | found = true1; |
438 | found_idx = i; |
439 | num_matches++; |
440 | } |
441 | } |
442 | |
443 | if (found && num_matches == 1) { |
444 | if ((ret = (CommandPath[found_idx].func)(argc, argv)) != 0) { |
445 | endwin(); |
446 | errx(1, "%s line %zd: error with command '%s' [%i]", |
447 | conf_file, linenum, argv[0], ret); |
448 | } |
449 | } else if (num_matches > 1) { |
450 | endwin(); |
451 | errx(1, "%s line %zd: ambiguous abbreviation '%s'", |
452 | conf_file, linenum, argv[0]); |
453 | } else { |
454 | endwin(); |
455 | errx(1, "%s line %zd: unknown command '%s'", |
456 | conf_file, linenum, argv[0]); |
457 | } |
458 | |
459 | argv_free(&argc, &argv); |
460 | free(line); |
461 | } |
462 | |
463 | fclose(fin); |
464 | } |
465 | |
466 | /* |
467 | * parse the command line and handle all switches. |
468 | * this also handles all of the e-commands. |
469 | */ |
470 | int |
471 | handle_switches(int argc, char *argv[]) |
472 | { |
473 | int ch; |
474 | |
475 | while ((ch = getopt(argc, argv, "he:f:d:p:m:c:")) != -1) { |
476 | switch (ch) { |
477 | case 'c': |
478 | if(sock_send_msg(optarg) == -1) |
479 | errx(1, "Failed to send message. Vitunes not running?"); |
480 | exit(0); |
481 | |
482 | case 'd': |
483 | free(db_file); |
484 | if ((db_file = strdup(optarg)) == NULL((void *)0)) |
485 | err(1, "handle_switches: strdup db_file failed"); |
486 | break; |
487 | |
488 | case 'e': |
489 | /* an e-command */ |
490 | argc -= optind - 1; |
491 | argv += optind - 1; |
492 | |
493 | exit(ecmd_exec(optarg, argc, argv)); |
494 | |
495 | case 'f': |
496 | free(conf_file); |
497 | if ((conf_file = strdup(optarg)) == NULL((void *)0)) |
498 | err(1, "handle_switches: strdup conf_file failed"); |
499 | break; |
500 | |
501 | case 'm': |
502 | free(player_backend); |
503 | if ((player_backend = strdup(optarg)) == NULL((void *)0)) |
504 | err(1, "handle_switches: strdup player_backend failed"); |
505 | break; |
506 | |
507 | case 'p': |
508 | free(playlist_dir); |
509 | if ((playlist_dir = strdup(optarg)) == NULL((void *)0)) |
510 | err(1, "handle_switches: strdup playlist_dir failed"); |
511 | break; |
512 | |
513 | case 'h': |
514 | case '?': |
515 | default: |
516 | usage(); |
517 | /* NOT REACHED */ |
518 | } |
519 | } |
520 | argc -= optind; |
521 | argv += optind; |
Value stored to 'argv' is never read | |
522 | |
523 | if (argc) |
524 | usage(); |
525 | |
526 | return 0; |
527 | } |