Add Russian translation provided by Валерий Крувялис <valkru@mail.ru>
[xiph-mirror.git] / vorbis-tools / ogg123 / playlist.c
blobafcf5d72baac096739784e343be0e806ee818467
1 /********************************************************************
2 * *
3 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *
5 * THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE. *
6 * PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
7 * *
8 * THE Ogg123 SOURCE CODE IS (C) COPYRIGHT 2000-2001 *
9 * by Stan Seibert <volsung@xiph.org> AND OTHER CONTRIBUTORS *
10 * http://www.xiph.org/ *
11 * *
12 ********************************************************************
14 last mod: $Id$
16 ********************************************************************/
18 #ifdef HAVE_CONFIG_H
19 #include <config.h>
20 #endif
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <ctype.h>
26 #include <limits.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <unistd.h>
30 #include <dirent.h>
31 #include "playlist.h"
32 #include "i18n.h"
34 /* Work with *BSD differences */
35 #if !defined(NAME_MAX) && defined(MAXNAMLEN)
36 #define NAME_MAX MAXNAMLEN
37 #endif
39 playlist_element_t *playlist_element_create(char *filename)
41 playlist_element_t *element = (playlist_element_t *)
42 malloc(sizeof(playlist_t));
44 if (element == NULL) {
45 fprintf(stderr,
46 _("ERROR: Out of memory in create_playlist_member().\n"));
47 exit(1);
50 if (filename == NULL)
51 element->filename = NULL;
52 else {
53 element->filename = strdup(filename);
55 if (element->filename == NULL) {
56 fprintf(stderr,
57 _("ERROR: Out of memory in create_playlist_member().\n"));
58 exit(1);
62 element->next = NULL;
64 return element;
68 /* Only destroys the current node. Does not affect linked nodes. */
69 void playlist_element_destroy(playlist_element_t *element)
71 free(element->filename);
72 free(element);
77 playlist_t *playlist_create()
79 playlist_t *list = (playlist_t *) malloc(sizeof(playlist_t));
81 if (list != NULL) {
82 list->head = playlist_element_create(NULL);
83 list->last = list->head;
86 return list;
90 void playlist_destroy(playlist_t *list) {
91 playlist_element_t *next_element;
93 while (list->head != NULL) {
94 next_element = list->head->next;
96 playlist_element_destroy(list->head);
98 list->head = next_element;
101 free(list);
105 /* All of the playlist_append_* functions return
106 1 if append was successful
107 0 if failure (either directory could not be accessed or playlist on disk
108 could not be opened)
112 /* Add this filename to the playlist. Filename will be strdup()'ed. Note
113 that this function will never fail. */
114 int playlist_append_file(playlist_t *list, char *filename)
116 list->last->next = playlist_element_create(filename);
117 list->last = list->last->next;
119 return 1; /* No way to fail */
122 /* Recursively adds files from the directory and subdirectories */
123 #if defined(HAVE_ALPHASORT) && defined(HAVE_SCANDIR)
124 int playlist_append_directory(playlist_t *list, char *dirname)
126 int dir_len = strlen(dirname);
127 int num_entries = 0, i = 0;
128 struct dirent **entries;
129 struct stat stat_buf;
130 char nextfile[NAME_MAX + 1];
132 num_entries = scandir(dirname, &entries, 0, alphasort);
134 if (num_entries < 0) {
135 return 0;
138 for (i=0; i<num_entries; i++) {
139 int sub_len = strlen(entries[i]->d_name);
141 /* Make sure full pathname is within limits and we don't parse the
142 relative directory entries. */
143 if (dir_len + sub_len + 1 < NAME_MAX
144 && strcmp(entries[i]->d_name, ".") != 0
145 && strcmp(entries[i]->d_name, "..") != 0 ) {
147 /* Build the new full pathname */
148 strcpy(nextfile, dirname);
149 strcat(nextfile, "/");
150 strcat(nextfile, entries[i]->d_name);
152 if (stat(nextfile, &stat_buf) == 0) {
154 /* Decide what type of entry this is */
155 if (S_ISDIR(stat_buf.st_mode)) {
157 /* Recursively follow directories */
158 if ( playlist_append_directory(list, nextfile) == 0 ) {
159 fprintf(stderr,
160 _("Warning: Could not read directory %s.\n"),
161 nextfile);
163 } else {
164 /* Assume everything else is a file of some sort */
165 playlist_append_file(list, nextfile);
170 free(entries[i]);
173 free(entries);
175 return 1;
177 #else
178 int playlist_append_directory(playlist_t *list, char *dirname)
180 DIR *dir;
181 int dir_len = strlen(dirname);
182 struct dirent *entry;
183 struct stat stat_buf;
184 char nextfile[NAME_MAX + 1];
186 dir = opendir(dirname);
188 if (dir == NULL) {
189 return 0;
192 entry = readdir(dir);
193 while (entry != NULL) {
194 int sub_len = strlen(entry->d_name);
196 /* Make sure full pathname is within limits and we don't parse the
197 relative directory entries. */
198 if (dir_len + sub_len + 1 < NAME_MAX
199 && strcmp(entry->d_name, ".") != 0
200 && strcmp(entry->d_name, "..") != 0 ) {
202 /* Build the new full pathname */
203 strcpy(nextfile, dirname);
204 strcat(nextfile, "/");
205 strcat(nextfile, entry->d_name);
207 if (stat(nextfile, &stat_buf) == 0) {
209 /* Decide what type of entry this is */
210 if (S_ISDIR(stat_buf.st_mode)) {
212 /* Recursively follow directories */
213 if ( playlist_append_directory(list, nextfile) == 0 ) {
214 fprintf(stderr,
215 _("Warning: Could not read directory %s.\n"),
216 nextfile);
218 } else {
219 /* Assume everything else is a file of some sort */
220 playlist_append_file(list, nextfile);
225 entry = readdir(dir);
228 closedir(dir);
230 return 1;
232 #endif
235 /* Opens a file containing filenames, one per line, and adds them to the
236 playlist */
237 int playlist_append_from_file(playlist_t *list, char *playlist_filename)
239 FILE *fp;
240 char filename[NAME_MAX+1];
241 struct stat stat_buf;
242 int length;
243 int i;
245 if (strcmp(playlist_filename, "-") == 0)
246 fp = stdin;
247 else
248 fp = fopen(playlist_filename, "r");
250 if (fp == NULL)
251 return 0;
253 while (!feof(fp)) {
255 if ( fgets(filename, NAME_MAX+1 /* no, really! */, fp) == NULL )
256 continue;
258 filename[NAME_MAX] = '\0'; /* Just to make sure */
259 length = strlen(filename);
261 /* Skip blank lines */
262 for (i = 0; i < length && isspace(filename[i]); i++);
263 if (i == length)
264 continue;
266 /* Crop off trailing newlines if present. Handle DOS (\r\n), Unix (\n)
267 * and MacOS<9 (\r) line endings. */
268 if (filename[length - 2] == '\r' && filename[length - 1] == '\n')
269 filename[length - 2] = '\0';
270 else if (filename[length - 1] == '\n' || filename[length - 1] == '\r')
271 filename[length - 1] = '\0';
273 if (stat(filename, &stat_buf) == 0) {
275 if (S_ISDIR(stat_buf.st_mode)) {
276 if (playlist_append_directory(list, filename) == 0)
277 fprintf(stderr,
278 _("Warning from playlist %s: "
279 "Could not read directory %s.\n"), playlist_filename,
280 filename);
281 } else {
282 playlist_append_file(list, filename);
284 } else /* If we can't stat it, it might be a non-disk source */
285 playlist_append_file(list, filename);
289 return 1;
293 /* Return the number of items in the playlist */
294 int playlist_length(playlist_t *list)
296 int length;
297 playlist_element_t *element;
299 element = list->head;
300 length = 0; /* don't count head node */
301 while (element->next != NULL) {
302 length++;
303 element = element->next;
306 return length;
310 /* Convert the playlist to an array of strings. Strings are deep copied.
311 Size will be set to the number of elements in the array. */
312 char **playlist_to_array(playlist_t *list, int *size)
314 char **array;
315 int i;
316 playlist_element_t *element;
318 *size = playlist_length(list);
319 array = calloc(*size, sizeof(char *));
321 if (array == NULL) {
322 fprintf(stderr,
323 _("ERROR: Out of memory in playlist_to_array().\n"));
324 exit(1);
327 for (i = 0, element = list->head->next;
328 i < *size;
329 i++, element = element->next) {
331 array[i] = strdup(element->filename);
333 if (array[i] == NULL) {
334 fprintf(stderr,
335 _("ERROR: Out of memory in playlist_to_array().\n"));
336 exit(1);
341 return array;
345 /* Deallocate array and all contained strings created by playlist_to_array. */
346 void playlist_array_destroy(char **array, int size)
348 int i;
350 for (i = 0; i < size; i++)
351 free(array[i]);
353 free(array);