/* Recursively adds files from the directory and subdirectories */ int playlist_append_directory(playlist_t *list, char *dirname) { DIR *dir; int dir_len = strlen(dirname); struct dirent *entry; struct stat stat_buf; char nextfile[NAME_MAX + 1]; dir = opendir(dirname); if (dir == NULL) { return 0; } entry = readdir(dir); while (entry != NULL) { int sub_len = strlen(entry->d_name); /* Make sure full pathname is within limits and we don't parse the relative directory entries. */ if (dir_len + sub_len + 1 < NAME_MAX && strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0 ) { /* Build the new full pathname */ strcpy(nextfile, dirname); strcat(nextfile, "/"); strcat(nextfile, entry->d_name); if (stat(nextfile, &stat_buf) == 0) { /* Decide what type of entry this is */ if (S_ISDIR(stat_buf.st_mode)) { /* Recursively follow directories */ if ( playlist_append_directory(list, nextfile) == 0 ) { fprintf(stderr, _("Warning: Could not read directory %s.\n"), nextfile); } } else { /* Assume everything else is a file of some sort */ playlist_append_file(list, nextfile); } } } entry = readdir(dir); } closedir(dir); return 1; }
/* Opens a file containing filenames, one per line, and adds them to the playlist */ int playlist_append_from_file(playlist_t *list, char *playlist_filename) { FILE *fp; char filename[NAME_MAX+1]; struct stat stat_buf; int length; int i; if (strcmp(playlist_filename, "-") == 0) fp = stdin; else fp = fopen(playlist_filename, "r"); if (fp == NULL) return 0; while (!feof(fp)) { if ( fgets(filename, NAME_MAX+1 /* no, really! */, fp) == NULL ) continue; filename[NAME_MAX] = '\0'; /* Just to make sure */ length = strlen(filename); /* Skip blank lines */ for (i = 0; i < length && isspace(filename[i]); i++); if (i == length) continue; /* Crop off trailing newlines if present. Handle DOS (\r\n), Unix (\n) * and MacOS<9 (\r) line endings. */ if (filename[length - 2] == '\r' && filename[length - 1] == '\n') filename[length - 2] = '\0'; else if (filename[length - 1] == '\n' || filename[length - 1] == '\r') filename[length - 1] = '\0'; if (stat(filename, &stat_buf) == 0) { if (S_ISDIR(stat_buf.st_mode)) { if (playlist_append_directory(list, filename) == 0) fprintf(stderr, _("Warning from playlist %s: " "Could not read directory %s.\n"), playlist_filename, filename); } else { playlist_append_file(list, filename); } } else /* If we can't stat it, it might be a non-disk source */ playlist_append_file(list, filename); } return 1; }
int main(int argc, char **argv) { int optind; char **playlist_array; int items; struct stat stat_buf; int i; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); ao_initialize(); stat_format = stat_format_create(); options_init(&options); file_options_init(file_opts); parse_std_configs(file_opts); options.playlist = playlist_create(); optind = parse_cmdline_options(argc, argv, &options, file_opts); audio_play_arg.devices = options.devices; audio_play_arg.stat_format = stat_format; /* Add remaining arguments to playlist */ for (i = optind; i < argc; i++) { if (stat(argv[i], &stat_buf) == 0) { if (S_ISDIR(stat_buf.st_mode)) { if (playlist_append_directory(options.playlist, argv[i]) == 0) fprintf(stderr, _("Warning: Could not read directory %s.\n"), argv[i]); } else { playlist_append_file(options.playlist, argv[i]); } } else /* If we can't stat it, it might be a non-disk source */ playlist_append_file(options.playlist, argv[i]); } /* Do we have anything left to play? */ if (playlist_length(options.playlist) == 0) { cmdline_usage(); exit(1); } else { playlist_array = playlist_to_array(options.playlist, &items); playlist_destroy(options.playlist); options.playlist = NULL; } /* Don't use status_message until after this point! */ status_set_verbosity(options.verbosity); print_audio_devices_info(options.devices); /* Setup buffer */ if (options.buffer_size > 0) { audio_buffer = buffer_create(options.buffer_size, options.buffer_size * options.prebuffer / 100, audio_play_callback, &audio_play_arg, AUDIO_CHUNK_SIZE); if (audio_buffer == NULL) { status_error(_("Error: Could not create audio buffer.\n")); exit(1); } } else audio_buffer = NULL; /* Shuffle playlist */ if (options.shuffle) { int i; srandom(time(NULL)); for (i = 0; i < items; i++) { int j = i + random() % (items - i); char *temp = playlist_array[i]; playlist_array[i] = playlist_array[j]; playlist_array[j] = temp; } } /* Setup signal handlers and callbacks */ ATEXIT (exit_cleanup); signal (SIGINT, signal_handler); signal (SIGTSTP, signal_handler); signal (SIGCONT, signal_handler); signal (SIGTERM, signal_handler); /* Play the files/streams */ i = 0; while (i < items && !sig_request.exit) { play(playlist_array[i]); i++; } playlist_array_destroy(playlist_array, items); exit (0); }