[xiph-cvs] cvs commit: vorbis-tools/ogg123 playlist.c playlist.h Makefile.am ogg123.c

Stan Seibert volsung at xiph.org
Fri Jul 5 20:23:14 PDT 2002



volsung     02/07/05 20:23:14

  Modified:    ogg123   Makefile.am ogg123.c
  Added:       ogg123   playlist.c playlist.h
  Log:
  Playlist support.  Now both files and directories can be specified on the
  command line.  Directories are recursively examined and files added to the
  playlist.

Revision  Changes    Path
1.25      +3 -2      vorbis-tools/ogg123/Makefile.am

Index: Makefile.am
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/ogg123/Makefile.am,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -r1.24 -r1.25
--- Makefile.am	2002/07/02 16:45:15	1.24
+++ Makefile.am	2002/07/06 03:23:13	1.25
@@ -27,10 +27,11 @@
 ogg123_SOURCES = audio.c buffer.c callbacks.c \
                 cfgfile_options.c cmdline_options.c \
                 file_transport.c format.c http_transport.c \
-                ogg123.c oggvorbis_format.c status.c transport.c     \
+                ogg123.c oggvorbis_format.c playlist.c \
+                status.c transport.c \
                 audio.h buffer.h callbacks.h compat.h \
                 cfgfile_options.h cmdline_options.h \
-                format.h ogg123.h status.h transport.h
+                format.h ogg123.h playlist.h status.h transport.h
 
 man_MANS = $(mans) 
 doc_DATA = $(docs)

<p><p>1.62      +53 -20    vorbis-tools/ogg123/ogg123.c

Index: ogg123.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/ogg123/ogg123.c,v
retrieving revision 1.61
retrieving revision 1.62
diff -u -r1.61 -r1.62
--- ogg123.c	2002/06/02 03:07:11	1.61
+++ ogg123.c	2002/07/06 03:23:13	1.62
@@ -14,7 +14,7 @@
  *                                                                  *
  ********************************************************************
 
- last mod: $Id: ogg123.c,v 1.61 2002/06/02 03:07:11 volsung Exp $
+ last mod: $Id: ogg123.c,v 1.62 2002/07/06 03:23:13 volsung Exp $
 
  ********************************************************************/
 
@@ -28,6 +28,8 @@
 #include <signal.h>
 #include <unistd.h>
 #include <sys/time.h>
+#include <sys/stat.h>
+#include <unistd.h>
 #include <locale.h>
 
 #include "audio.h"
@@ -38,6 +40,7 @@
 #include "format.h"
 #include "transport.h"
 #include "status.h"
+#include "playlist.h"
 #include "compat.h"
 
 #include "ogg123.h"
@@ -270,6 +273,11 @@
 int main(int argc, char **argv)
 {
   int optind;
+  char **playlist_array;
+  playlist_t *list = playlist_create();
+  int items;
+  struct stat stat_buf;
+  int i;
 
   setlocale(LC_ALL, "");
   bindtextdomain(PACKAGE, LOCALEDIR);
@@ -286,23 +294,39 @@
   audio_play_arg.devices = options.devices;
   audio_play_arg.stat_format = stat_format;
 
-  /* Don't use status_message until after this point! */
-  status_set_verbosity(options.verbosity);
+  /* 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(list, argv[i]) == 0)
+	  fprintf(stderr, 
+		  _("Warning: Could not read directory %s.\n"), argv[i]);
+      } else {
+	playlist_append_file(list, argv[i]);
+      }
+    } else
+      fprintf(stderr,
+	      _("Warning: Could not access %s.\n"), argv[i]);
 
-  print_audio_devices_info(options.devices);
-
-  /* Setup signal handlers and callbacks */
+  }
 
-  ATEXIT (exit_cleanup);
-  signal (SIGINT, signal_handler);
-  signal (SIGTSTP, signal_handler);
-  signal (SIGCONT, signal_handler);
 
   /* Do we have anything left to play? */
-  if (optind == argc) {
+  if (playlist_length(list) == 0) {
     cmdline_usage();
     exit(1);
+  } else {
+    playlist_array = playlist_to_array(list, &items);
+    playlist_destroy(list);
+    list = 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) {
@@ -324,21 +348,30 @@
     
     srandom(time(NULL));
     
-    for (i = optind; i < argc; i++) {
-      int j = i + random() % (argc - i);
-      char *temp = argv[i];
-      argv[i] = argv[j];
-      argv[j] = temp;
+    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;
     }
   }
 
-  /* Play the files/streams */
+  /* Setup signal handlers and callbacks */
 
-  while (optind < argc && !sig_request.exit) {
-    play(argv[optind]);
-    optind++;
+  ATEXIT (exit_cleanup);
+  signal (SIGINT, signal_handler);
+  signal (SIGTSTP, signal_handler);
+  signal (SIGCONT, 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);
 }

<p><p>1.1                  vorbis-tools/ogg123/playlist.c

Index: playlist.c
===================================================================
/********************************************************************
 *                                                                  *
 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
 * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *
 * THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE.    *
 * PLEASE READ THESE TERMS BEFORE DISTRIBUTING.                     *
 *                                                                  *
 * THE Ogg123 SOURCE CODE IS (C) COPYRIGHT 2000-2001                *
 * by Stan Seibert <volsung at xiph.org> AND OTHER CONTRIBUTORS        *
 * http://www.xiph.org/                                             *
 *                                                                  *
 ********************************************************************

 last mod: $Id: playlist.c,v 1.1 2002/07/06 03:23:13 volsung Exp $

 ********************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include "playlist.h"
#include "i18n.h"

playlist_element_t *playlist_element_create(char *filename)
{
  playlist_element_t *element = (playlist_element_t *) 
                                   malloc(sizeof(playlist_t));

  if (element == NULL) {
      fprintf(stderr,
              _("Error: Out of memory in create_playlist_member().\n"));
      exit(1);
  }

  if (filename == NULL)
    element->filename = NULL;
  else {
    element->filename = strdup(filename);
    
    if (element->filename == NULL) {
        fprintf(stderr,
                _("Error: Out of memory in create_playlist_member().\n"));
        exit(1);
    }
  }
  
  element->next = NULL;
  
  return element;
}

<p>/* Only destroys the current node.  Does not affect linked nodes. */
void playlist_element_destroy(playlist_element_t *element)
{
  free(element->filename);
  free(element);
}

<p><p>playlist_t *playlist_create()
{
  playlist_t *list = (playlist_t *) malloc(sizeof(playlist_t));

  if (list != NULL) {
    list->head = playlist_element_create(NULL);
    list->last = list->head;
  }

  return list;
}

<p>void playlist_destroy(playlist_t *list) {
  playlist_element_t *next_element;

  while (list->head != NULL) {
    next_element = list->head->next;

    playlist_element_destroy(list->head);
    
    list->head = next_element;
  }

  free(list);
}

<p>/* All of the playlist_append_* functions return 
   1 if append was successful
   0 if failure (either directory could not be accessed or playlist on disk
   could not be opened)
*/

<p>/* Add this filename to the playlist.  Filename will be strdup()'ed.  Note
   that this function will never fail. */
int playlist_append_file(playlist_t *list, char *filename)
{
  list->last->next = playlist_element_create(filename);
  list->last = list->last->next;

  return 1; /* No way to fail */
}

/* 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;
}

<p>/* 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];
  int length;
  int i;

  fp = fopen(playlist_filename, "r");

  if (fp == NULL)
    return 0;

  while (!feof(fp)) {
    fgets(filename, NAME_MAX+1 /* no, really! */, fp);

    length = strlen(filename);

    // Skip blank lines
    for (i = 0; i < length && isspace(filename[i]); i++);
    if (i == length)
      continue;

    // Crop off last \n if present
    if (filename[length - 1] == '\n')
      filename[length - 1] = '\0';

    playlist_append_file(list, filename);
  }

  return 1;
}

<p>/* Return the number of items in the playlist */
int playlist_length(playlist_t *list)
{
  int length;
  playlist_element_t *element;

  element = list->head;  
  length = 0; // don't count head node
  while (element->next != NULL) {
    length++;
    element = element->next;
  }
  
  return length;
}

<p>/* Convert the playlist to an array of strings.  Strings are deep copied. 
   Size will be set to the number of elements in the array. */
char **playlist_to_array(playlist_t *list, int *size)
{
  char **array;
  int i;
  playlist_element_t *element;

  *size = playlist_length(list);
  array = calloc(*size, sizeof(char *));

  if (array == NULL) {
    fprintf(stderr,
            _("Error: Out of memory in playlist_to_array().\n"));
    exit(1);
  }

  for (i = 0, element = list->head->next; 
       i < *size; 
       i++, element = element->next) {

    array[i] = strdup(element->filename);

    if (array[i] == NULL) {
      fprintf(stderr,
              _("Error: Out of memory in playlist_to_array().\n"));
      exit(1);
    }
  }

<p>  return array;
}

<p>/* Deallocate array and all contained strings created by playlist_to_array. */
void playlist_array_destroy(char **array, int size)
{
  int i;

  for (i = 0; i < size; i++)
    free(array[i]);

  free(array);
}

<p><p>1.1                  vorbis-tools/ogg123/playlist.h

Index: playlist.h
===================================================================
/********************************************************************
 *                                                                  *
 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
 * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *
 * THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE.    *
 * PLEASE READ THESE TERMS BEFORE DISTRIBUTING.                     *
 *                                                                  *
 * THE Ogg123 SOURCE CODE IS (C) COPYRIGHT 2000-2002                *
 * by Kenneth C. Arnold <ogg at arnoldnet.net> AND OTHER CONTRIBUTORS  *
 * http://www.xiph.org/                                             *
 *                                                                  *
 ********************************************************************

 last mod: $Id: playlist.h,v 1.1 2002/07/06 03:23:13 volsung Exp $

 ********************************************************************/

#ifndef __PLAYLIST_H__
#define __PLAYLIST_H__

typedef struct playlist_element_t {
  char *filename;
  struct playlist_element_t *next;
} playlist_element_t;

/* Actual playlist structure */
typedef struct playlist_t {

  /* Linked list with empty head node */
  playlist_element_t *head;

  /* Keep track of this for speedy appends */
  playlist_element_t *last;
} playlist_t;

playlist_t *playlist_create();
void playlist_destroy(playlist_t *list);

/* All of the playlist_append_* functions return 
   1 if append was successful
   0 if failure (either directory could not be accessed or playlist on disk
   could not be opened)
*/

<p>/* Add this filename to the playlist.  Filename will be strdup()'ed.  Note
   that this function will never fail. */
int playlist_append_file(playlist_t *list, char *filename);

/* Recursively adds files from the directory and subdirectories */
int playlist_append_directory(playlist_t *list, char *dirname);

/* 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);

/* Return the number of items in the playlist */
int playlist_length(playlist_t *list);

/* Convert the playlist to an array of strings.  Strings are deep copied. 
   Size will be set to the number of elements in the array. */
char **playlist_to_array(playlist_t *list, int *size);

/* Deallocate array and all contained strings created by playlist_to_array. */
void playlist_array_destroy(char **array, int size);

<p>#endif /* __PLAYLIST_H__ */

<p><p><p>--- >8 ----
List archives:  http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body.  No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.



More information about the commits mailing list