| 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 | } |