Recognizes if input is ogg or not.
[xiph.git] / vorbis-tools / ogg123 / playlist.c
blob9ece68b56a360e03841dd7096dc4519f3e7693ab
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: playlist.c,v 1.3 2002/07/13 17:57:10 volsung Exp $
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 int playlist_append_directory(playlist_t *list, char *dirname)
125 DIR *dir;
126 int dir_len = strlen(dirname);
127 struct dirent *entry;
128 struct stat stat_buf;
129 char nextfile[NAME_MAX + 1];
131 dir = opendir(dirname);
133 if (dir == NULL) {
134 return 0;
137 entry = readdir(dir);
138 while (entry != NULL) {
139 int sub_len = strlen(entry->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(entry->d_name, ".") != 0
145 && strcmp(entry->d_name, "..") != 0 ) {
147 /* Build the new full pathname */
148 strcpy(nextfile, dirname);
149 strcat(nextfile, "/");
150 strcat(nextfile, entry->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 entry = readdir(dir);
173 closedir(dir);
175 return 1;
179 /* Opens a file containing filenames, one per line, and adds them to the
180 playlist */
181 int playlist_append_from_file(playlist_t *list, char *playlist_filename)
183 FILE *fp;
184 char filename[NAME_MAX+1];
185 struct stat stat_buf;
186 int length;
187 int i;
189 if (strcmp(playlist_filename, "-") == 0)
190 fp = stdin;
191 else
192 fp = fopen(playlist_filename, "r");
194 if (fp == NULL)
195 return 0;
197 while (!feof(fp)) {
199 if ( fgets(filename, NAME_MAX+1 /* no, really! */, fp) == NULL )
200 continue;
202 filename[NAME_MAX] = '\0'; /* Just to make sure */
203 length = strlen(filename);
205 /* Skip blank lines */
206 for (i = 0; i < length && isspace(filename[i]); i++);
207 if (i == length)
208 continue;
210 /* Crop off trailing newlines if present. Handle DOS (\r\n), Unix (\n)
211 * and MacOS<9 (\r) line endings. */
212 if (filename[length - 2] == '\r' && filename[length - 1] == '\n')
213 filename[length - 2] = '\0';
214 else if (filename[length - 1] == '\n' || filename[length - 1] == '\r')
215 filename[length - 1] = '\0';
217 if (stat(filename, &stat_buf) == 0) {
219 if (S_ISDIR(stat_buf.st_mode)) {
220 if (playlist_append_directory(list, filename) == 0)
221 fprintf(stderr,
222 _("Warning from playlist %s: "
223 "Could not read directory %s.\n"), playlist_filename,
224 filename);
225 } else {
226 playlist_append_file(list, filename);
228 } else /* If we can't stat it, it might be a non-disk source */
229 playlist_append_file(list, filename);
233 return 1;
237 /* Return the number of items in the playlist */
238 int playlist_length(playlist_t *list)
240 int length;
241 playlist_element_t *element;
243 element = list->head;
244 length = 0; /* don't count head node */
245 while (element->next != NULL) {
246 length++;
247 element = element->next;
250 return length;
254 /* Convert the playlist to an array of strings. Strings are deep copied.
255 Size will be set to the number of elements in the array. */
256 char **playlist_to_array(playlist_t *list, int *size)
258 char **array;
259 int i;
260 playlist_element_t *element;
262 *size = playlist_length(list);
263 array = calloc(*size, sizeof(char *));
265 if (array == NULL) {
266 fprintf(stderr,
267 _("Error: Out of memory in playlist_to_array().\n"));
268 exit(1);
271 for (i = 0, element = list->head->next;
272 i < *size;
273 i++, element = element->next) {
275 array[i] = strdup(element->filename);
277 if (array[i] == NULL) {
278 fprintf(stderr,
279 _("Error: Out of memory in playlist_to_array().\n"));
280 exit(1);
285 return array;
289 /* Deallocate array and all contained strings created by playlist_to_array. */
290 void playlist_array_destroy(char **array, int size)
292 int i;
294 for (i = 0; i < size; i++)
295 free(array[i]);
297 free(array);