[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#110623: marked as done (Ability to read archive files)



Your message dated Sun, 18 Sep 2005 00:09:52 -0500
with message-id <1127020192.4857.15.camel@cerdita>
and subject line Closing
has caused the attached Bug report to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what I am
talking about this indicates a serious mail system misconfiguration
somewhere.  Please contact me immediately.)

Debian bug tracking system administrator
(administrator, Debian Bugs database)

--------------------------------------
Received: (at submit) by bugs.debian.org; 30 Aug 2001 03:49:43 +0000
>From mdz@csh.rit.edu Wed Aug 29 22:49:43 2001
Return-path: <mdz@csh.rit.edu>
Received: from mail303.mail.bellsouth.net (imf03bis.bellsouth.net) [205.152.58.163] 
	by master.debian.org with esmtp (Exim 3.12 1 (Debian))
	id 15cIpr-0005Ut-00; Wed, 29 Aug 2001 22:49:43 -0500
Received: from mizar.alcor.net ([66.156.8.104]) by imf03bis.bellsouth.net
          (InterMail vM.5.01.01.01 201-252-104) with ESMTP
          id <20010830035010.HMWT25554.imf03bis.bellsouth.net@mizar.alcor.net>
          for <submit@bugs.debian.org>; Wed, 29 Aug 2001 23:50:10 -0400
Received: from mdz by mizar.alcor.net with local (Exim 3.32 #1 (Debian))
	id 15cIpL-0001y9-00
	for <submit@bugs.debian.org>; Wed, 29 Aug 2001 23:49:11 -0400
Date: Wed, 29 Aug 2001 23:49:11 -0400
From: Matt Zimmerman <mdz@debian.org>
To: submit@bugs.debian.org
Subject: Ability to read archive files
Message-ID: <20010829234908.G16438@alcor.net>
Mime-Version: 1.0
Content-Type: multipart/mixed; boundary="8X7/QrJGcKSMr1RN"
Content-Disposition: inline
User-Agent: Mutt/1.3.20i
Sender: Matt Zimmerman <mdz@alcor.net>
Delivered-To: submit@bugs.debian.org


--8X7/QrJGcKSMr1RN
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Package: xmms
Severity: wishlist
Tags: patch

I sent this patch upstream a couple of years ago, but never heard any
response back, so I guess they weren't interested.  I'm filing it here so
that if someone else finds it useful, maybe they'll integrate it with the
current version.

-- 
 - mdz

--8X7/QrJGcKSMr1RN
Content-Type: message/rfc822
Content-Disposition: inline

Date: Sat, 11 Dec 1999 05:07:02 -0500
From: Matt Zimmerman <mdz@csh.rit.edu>
To: peter@xmms.org
Subject: XMMS and compressed files/archives
Message-ID: <19991211050702.A23232@csh.rit.edu>
Mime-Version: 1.0
Content-Type: multipart/mixed; boundary="ew6BAiZeqk4r7MaW"
User-Agent: Mutt/1.1.1i


--ew6BAiZeqk4r7MaW
Content-Type: text/plain; charset=us-ascii

I imagine that most people use xmms for playing mp3 files, I think one of its
strengths is the input plugin architecture, allowing it to combine many formats
into a single music collection.  Some non-mp3 formats, such as the various
MOD formats, compress rather well.  Having a number of these in my collection,
I thought it would be nice if xmms could scan the compressed archives and
extract files on-demand.

Attached is a patch (against 0.9.5.1, but I tested it with the latest CVS)
that allows it to do just that.  The changes are basically:

- The addition of an 'archive' module (archive.h, archive.c) with functions
  for testing whether a file is an archive, listing its members, and
  extracting a member into a temporary file

- The __playlist_ins function in playlist.c takes an addional argument, the
  name of the archive file if the specified file is contained in an archive

- The playlist_ins function in playlist.c will check to see if a file is
  an archive, and scan it as appropriate

- The PlaylistEntry structure contains additional elements for holding the
  name of the archive file and the temporary file

- A new playlist_ins_archive function to scan an archive for addition to the
  playlist

- Archive type is determined solely by filename extension.  It may be
  desirable to check for magic numbers, etc. eventually.  Currently,
  .gz, .bz2, .tar.gz, .tar.bz2, .tar, and .zip are supported.  .zip is by far
  the fastest to extract a single member, because of the central directory.

I have been using it for a while now, and it seems to work well.  YMMV.
There are some known issues with it:

- It does not extract each file before running input_check_file() on it.
  I decided this would be too slow.  So, compressed files are not available
  for reading by the input plugins.  This is not a problem for the mikmod
  plugin, but the WAV plugin (and perhaps others) want to read the file.
  Plugins which want to read the file will fail to recognize archive members.

- For the same reason, song titles and durations are not known until the song
  has been selected for playing (and thus extracted).

- I couldn't come up with a good way to determine when the temporary files
  should be deleted, so they hang around until the playlist entry is deleted.
  This also means that if the file is already extracted, it will be reused if
  the song is played again.

- The .m3u playlist format doesn't provide a way to store information about
  archives.  I work around this by only storing the name of the archive, so
  when the playlist is loaded, all files in the archive will be loaded.  It
  would be nice if the playlist could contain only certain files in an archive.

It is a little rough around the edges, but I thought you might be interested in
looking at it.  There is currently no copyright notice on the new module, but
it would be my intention that it would fall under the GPL along with the rest
of the code, if it were merged.  The only critical change I think is necessary
is for it to use mkstemp(3) or some such to create a secure temporary file.
Currently, it extracts the file under its original name in /tmp.

My thanks to you and the rest of the xmms team for a great application.  Feel
free to contact me about these modifications.

-- 
 - mdz

--ew6BAiZeqk4r7MaW
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="xmms-archives.diff"

diff -rc --new-file --exclude=Makefile --exclude=Makefile.in xmms-0.9.5.1/xmms/Makefile.am xmms-0.9.5.1+mdz/xmms/Makefile.am
*** xmms-0.9.5.1/xmms/Makefile.am	Sun Sep  5 02:36:41 1999
--- xmms-0.9.5.1+mdz/xmms/Makefile.am	Wed Dec  1 19:56:48 1999
***************
*** 45,50 ****
--- 45,51 ----
  hints.c hints.h \
  about.c about.h \
  plugin.h \
+ archive.c archive.h \
  xmms.h getopt.c getopt1.c getopt.h
  
  EXTRA_DIST= xmms_logo.xpm
diff -rc --new-file --exclude=Makefile --exclude=Makefile.in xmms-0.9.5.1/xmms/archive.c xmms-0.9.5.1+mdz/xmms/archive.c
*** xmms-0.9.5.1/xmms/archive.c	Wed Dec 31 16:00:00 1969
--- xmms-0.9.5.1+mdz/xmms/archive.c	Fri Dec 10 21:56:47 1999
***************
*** 0 ****
--- 1,260 ----
+ #include <fcntl.h>
+ #include <fnmatch.h>
+ 
+ #include "xmms.h"
+ 
+ #define ARCHIVE_MAX_ARGS 16
+ 
+ typedef struct {
+   /* Shell wildcard pattern */
+   gchar *archive_pattern;
+ 
+   /* Command to list archive members */
+   gchar *list_command[ARCHIVE_MAX_ARGS + 1];
+ 
+   /* offset from beginning of line to filename */
+   gint list_offset;
+ 
+   /* Command to extract one member from an archive */
+   gchar *extract_command[ARCHIVE_MAX_ARGS + 1];
+ 
+ } archive_type;
+ 
+ /* List of recognized archive types */
+ 
+ static const archive_type archive_types[] = {
+   /* gzip'd tar archives */
+   { "*.tar.gz",
+     { "tar", "tzf", "ARCHIVE_NAME", NULL }, 0,
+     { "tar", "xzOf", "ARCHIVE_NAME", "MEMBER_NAME", NULL }
+   },
+ 
+   /* bzip2'd tar archives (requires a recent tar) */
+   { "*.tar.bz2",
+     { "tar", "tIf", "ARCHIVE_NAME", NULL }, 0,
+     { "tar", "xIOf", "ARCHIVE_NAME", "MEMBER_NAME", NULL }
+   },
+ 
+   /* tar archives */
+   { "*.tar",
+     { "tar", "tf", "ARCHIVE_NAME", NULL }, 0,
+     { "tar", "xOf", "ARCHIVE_NAME", "MEMBER_NAME", NULL }
+   },
+ 
+   /* zip archives */
+   { "*.zip",
+     { "unzip", "-qql", "ARCHIVE_NAME", NULL }, 28,
+     { "unzip", "-qqp", "ARCHIVE_NAME", "MEMBER_NAME", NULL }
+   },
+ 
+   /* gzip'd files */
+   { "*.gz",
+     { NULL }, -1, /* Member filename implied by archive filename */
+     { "gzip", "-dqc", "ARCHIVE_NAME", NULL }
+   },
+ 
+   /* bzip2'd files */
+   { "*.bz2",
+     { NULL }, -1, /* Member filename implied by archive filename */
+     { "bzip2", "-dqc", "ARCHIVE_NAME", NULL }
+   },
+ 
+   { NULL, { NULL }, -1, { NULL } }
+ 
+ };
+ 
+ /* Find the associated type for a given (possible) archive file */
+ 
+ static const archive_type *archive_get_type(const gchar *archive)
+ {
+   const archive_type *type;
+ 
+   for(type = archive_types ;
+       type != NULL && type ->archive_pattern != NULL ;
+       ++type) {
+ 
+     if (fnmatch(type->archive_pattern, archive, 0) == 0)
+       return type;
+   }
+ 
+   return NULL;
+ }
+ 
+ /* Is the specified file an archive? */
+ 
+ gboolean archive_isarchive(const gchar *archive)
+ {
+   const archive_type *type = archive_get_type(archive);
+ 
+   return type == NULL ? FALSE : TRUE;
+ }
+ 
+ /* List the members of an archive */
+ 
+ GList *archive_list_members(const gchar *archive)
+ {
+   const archive_type *type = archive_get_type(archive);
+   gchar *list_command[ARCHIVE_MAX_ARGS];
+   guint arg;
+   GList *members = NULL;
+ 
+   if (type == NULL)
+     return NULL;
+ 
+   if (type->list_command[0] == NULL) {
+     /* Member filename implied by removing extension */
+ 
+     /*
+      * XXX - This code makes some assumptions about single-file
+      * archives of this type (e.g. gzip, bzip2):
+      *
+      * 1. The filename does not have a compound extension
+      * (e.g. .tar.gz)
+      *
+      * 2. The filename has an extension (at least one dot in the filename)
+      *
+      * It will fail if these conditions are not met, so if archive
+      * types are added that do not meet these conditions, this will
+      * have to be fixed */
+ 
+     gchar *temp = g_strdup(archive);
+     gchar *ext = strrchr(temp, '.');
+     gchar *slash = strrchr(temp, '/');
+     gchar *member;
+ 
+     if (ext == NULL)
+       return NULL;
+ 
+     *ext = '\0';
+     member = (slash == NULL) ? g_strdup(archive) : g_strdup(slash + 1);
+ 
+     members = g_list_append(members, member);
+ 
+     g_free(temp);
+ 
+     return members;
+   } else {
+     /* Need to execute a command to get the list of memmbers */
+     int commandpipe[2];
+     int waitstatus;
+     char buf[1024];
+ 
+     for(arg = 0 ;
+ 	arg < ARCHIVE_MAX_ARGS && type->list_command[arg] != NULL ;
+ 	++arg) {
+       if (strcmp(type->list_command[arg], "ARCHIVE_NAME") == 0)
+ 	list_command[arg] = g_strdup(archive);
+       else
+ 	list_command[arg] = g_strdup(type->list_command[arg]);
+ 
+     }
+ 
+     list_command[arg] = NULL;
+ 
+     if (pipe(commandpipe) == 0) {
+       if (fork()) {
+ 	FILE *child;
+ 	char *line;
+ 	close(commandpipe[1]);
+ 	
+ 	child = fdopen(commandpipe[0], "r");
+ 	while ( (line = fgets(buf, 1024, child)) != NULL) {
+ 	  char *newline = strrchr(line, '\n');
+ 	  
+ 	  if (newline != NULL)
+ 	    *newline = '\0';
+ 	  
+ 	  if (type->list_offset > 0)
+ 	    line += type->list_offset;
+ 	  
+ 	  members = g_list_append(members, g_strdup(line));
+ 	}
+ 	
+ 	waitstatus = wait(NULL);
+       } else {
+ 	close(commandpipe[0]);
+ 	dup2(commandpipe[1], fileno(stdout));
+ 	execvp(list_command[0], list_command);
+ 	exit(255);
+       }
+       
+     } else {
+       fprintf(stderr, "archive_get_members: error creating pipe (%d)\n",
+ 	      errno);
+     }
+     
+     for(arg = 0 ; list_command[arg] != NULL ; ++arg) {
+       g_free(list_command[arg]);
+     }
+   }
+   
+   return members;
+ }    
+ 
+ /* Extract one member of an archive */
+ 
+ gchar *archive_extract_member(const gchar *archive, const gchar *member)
+ {
+   const archive_type *type = archive_get_type(archive);
+   gchar *extract_command[ARCHIVE_MAX_ARGS];
+   gchar *temp_file = NULL;
+   int temp_file_fd = -1;
+   guint arg;
+   int waitstatus;
+ 
+   if (type == NULL || archive == NULL || member ==  NULL)
+     return NULL;
+ 
+   /* XXX - this should be changed to guarantee uniqueness and be somewhat
+    * more secure
+    */
+   temp_file = g_strdup("/tmp/");
+   temp_file = g_strconcat(temp_file, member, NULL);
+ 
+   unlink(temp_file);
+   temp_file_fd = open(temp_file, O_WRONLY|O_CREAT|O_EXCL, 0600);
+   if (temp_file_fd < 0) {
+     g_free(temp_file);
+     fprintf(stderr,
+ 	    "archive_extract_member: Problems opening temp file %s: %s\n",
+ 	    temp_file, strerror(errno));
+     return NULL;
+   }
+ 
+   for(arg = 0 ;
+       arg < ARCHIVE_MAX_ARGS && type->extract_command[arg] != NULL ;
+       ++arg) {
+     if (strcmp(type->extract_command[arg], "ARCHIVE_NAME") == 0)
+       extract_command[arg] = g_strdup(archive);
+     else if (strcmp(type->extract_command[arg], "TEMP_NAME") == 0)
+       extract_command[arg] = g_strdup(temp_file);
+     else if (strcmp(type->extract_command[arg], "MEMBER_NAME") == 0)
+       extract_command[arg] = g_strdup(member);
+     else
+       extract_command[arg] = g_strdup(type->extract_command[arg]);
+     
+   }
+ 
+   extract_command[arg] = NULL;
+ 
+   if (fork()) {
+     waitstatus = wait(NULL);
+   } else {
+     dup2(temp_file_fd, fileno(stdout));
+     execvp(extract_command[0], extract_command);
+     exit(255);
+   }
+ 
+   for(arg = 0 ; extract_command[arg] != NULL ; ++arg) {
+     g_free(extract_command[arg]);
+   }
+ 
+   if (waitstatus > 0) {
+     return temp_file;
+   } else {
+     g_free(temp_file);
+     fprintf(stderr, "Problem executing extract commend, wait status: %d\n",
+ 	    waitstatus);
+     return NULL;
+   }
+ }
diff -rc --new-file --exclude=Makefile --exclude=Makefile.in xmms-0.9.5.1/xmms/archive.h xmms-0.9.5.1+mdz/xmms/archive.h
*** xmms-0.9.5.1/xmms/archive.h	Wed Dec 31 16:00:00 1969
--- xmms-0.9.5.1+mdz/xmms/archive.h	Thu Dec  2 12:21:06 1999
***************
*** 0 ****
--- 1,5 ----
+ #include "xmms.h"
+ 
+ gboolean archive_isarchive(const gchar *archive);
+ GList *archive_list_members(const gchar *archive);
+ gchar *archive_extract_member(const gchar *archive, const gchar *member);
diff -rc --new-file --exclude=Makefile --exclude=Makefile.in xmms-0.9.5.1/xmms/playlist.c xmms-0.9.5.1+mdz/xmms/playlist.c
*** xmms-0.9.5.1/xmms/playlist.c	Sat Sep 25 06:05:25 1999
--- xmms-0.9.5.1+mdz/xmms/playlist.c	Fri Dec 10 21:51:18 1999
***************
*** 57,62 ****
--- 57,68 ----
  				g_free(entry->filename);
  			if (entry->title)
  				g_free(entry->title);
+ 			if (entry->archive_filename)
+ 			  g_free(entry->archive_filename);
+ 			if (entry->temp_filename) {
+ 			  unlink(entry->temp_filename);
+ 			  g_free(entry->temp_filename);
+ 			}
  			g_free(entry);
  			node = node->next;
  		}
***************
*** 112,121 ****
--- 118,136 ----
  				else
  					playlist_position = NULL;
  			}
+ 
  			if (entry->filename)
  				g_free(entry->filename);
  			if (entry->title)
  				g_free(entry->title);
+ 			if (entry->archive_filename)
+ 			        g_free(entry->archive_filename);
+ 
+ 			if (entry->temp_filename) {
+ 			  unlink(entry->temp_filename);
+ 			  g_free(entry->temp_filename);
+ 			}
+ 
  			playlist = g_list_remove_link(playlist, node);
  			g_free(entry);
  			g_list_free_1(node);
***************
*** 139,150 ****
  
  }
  
! static void __playlist_ins(gchar * filename, glong pos)
  {
  	PlaylistEntry *entry;
  
  	entry = g_malloc0(sizeof (PlaylistEntry));
  	entry->filename = g_strdup(filename);
  	entry->length = -1;
  
  	pthread_mutex_lock(&playlist_mutex);
--- 154,172 ----
  
  }
  
! static void __playlist_ins(gchar * filename, gchar * archive_filename,
! 			   glong pos)
  {
  	PlaylistEntry *entry;
  
  	entry = g_malloc0(sizeof (PlaylistEntry));
  	entry->filename = g_strdup(filename);
+ 	entry->archive_filename = NULL;
+ 	entry->temp_filename = NULL;
+ 	  
+ 	if (archive_filename != NULL)
+ 	  entry->archive_filename = g_strdup(archive_filename);
+ 
  	entry->length = -1;
  
  	pthread_mutex_lock(&playlist_mutex);
***************
*** 162,169 ****
  	if (ext && ((!strcasecmp(ext, ".m3u") || !strcasecmp(ext, ".pls"))))
  		playlist_load_ins(filename, pos);
  	else
  		if (input_check_file(filename))
! 			__playlist_ins(filename, pos);
  }
  
  /*  void playlist_add_dir(gchar * path) */
--- 184,194 ----
  	if (ext && ((!strcasecmp(ext, ".m3u") || !strcasecmp(ext, ".pls"))))
  		playlist_load_ins(filename, pos);
  	else
+ 	  if (archive_isarchive(filename))
+ 	    playlist_ins_archive(filename, pos);
+ 	else
  		if (input_check_file(filename))
! 			__playlist_ins(filename, NULL, pos);
  }
  
  /*  void playlist_add_dir(gchar * path) */
***************
*** 191,197 ****
  		node = list;
  		while (node)
  		{
! 			__playlist_ins(node->data, pos);
  			entries++;
  			if (pos > 0)
  				pos++;
--- 216,222 ----
  		node = list;
  		while (node)
  		{
! 			__playlist_ins(node->data, NULL, pos);
  			entries++;
  			if (pos > 0)
  				pos++;
***************
*** 221,227 ****
  				}
  				else if (input_check_file(filename))
  				{
! 					__playlist_ins(filename, pos);
  					entries++;
  					if (pos > 0)
  						pos++;
--- 246,252 ----
  				}
  				else if (input_check_file(filename))
  				{
! 					__playlist_ins(filename, NULL, pos);
  					entries++;
  					if (pos > 0)
  						pos++;
***************
*** 236,241 ****
--- 261,293 ----
  }
  
  /*
+  * Add all members of an archive to the playlist
+  */
+ guint playlist_ins_archive(gchar *archive, glong pos)
+ {
+   GList *list, *node;
+   guint entries = 0;
+ 
+   if ( (list = archive_list_members(archive)) != NULL) {
+     node = list;
+     while (node != NULL)
+     {
+       if (input_check_file(node->data)) {
+ 	__playlist_ins(node->data, archive, pos);
+ 	entries++;
+ 	if (pos > 0)
+ 	  pos++;
+       }
+ 
+       node = g_list_next(node);
+     }
+   }
+ 
+   return entries;
+ }
+ 	  
+ 
+ /*
   * I'm not sure if this is the correct way to do it but it seems to work fine
   */
  
***************
*** 324,331 ****
  	PL_LOCK();
  	entry = g_list_nth(playlist, get_playlist_position())->data;
  	PL_UNLOCK();
! 	
! 	input_play(entry->filename);
  
  	if (input_get_time() != -1)
  	{
--- 376,399 ----
  	PL_LOCK();
  	entry = g_list_nth(playlist, get_playlist_position())->data;
  	PL_UNLOCK();
! 
! 	if (entry->archive_filename != NULL && entry->temp_filename == NULL) {
! 	  gchar *temp_filename = archive_extract_member(entry->archive_filename,
! 						    entry->filename);
! 	  PL_LOCK();
! 	  entry->temp_filename = temp_filename;
! 	  PL_UNLOCK();
! 	  
! 	  if (entry->temp_filename == NULL) {
! 	    fprintf(stderr, "Failed to unarchive %s from %s!\n",
! 		    entry->filename, entry->archive_filename);
! 	  }
! 	}
! 
! 	if (entry->temp_filename != NULL)
! 	  input_play(entry->temp_filename);
! 	else
! 	  input_play(entry->filename);
  
  	if (input_get_time() != -1)
  	{
***************
*** 608,613 ****
--- 676,684 ----
  	FILE *file;
  	gchar *ext;
  	gboolean is_pls = FALSE;
+ 	GHashTable *archives = NULL;
+ 
+ 	archives = g_hash_table_new(g_str_hash, g_str_equal);
  
  	if ((file = fopen(filename, "w")) != NULL)
  	{
***************
*** 626,639 ****
  		while (node)
  		{
  			entry = (PlaylistEntry *) node->data;
! 			if (is_pls)
  				fprintf(file, "File%d=%s\n", g_list_position(playlist, node) + 1, entry->filename);
! 			else
! 				fprintf(file, "%s\n", entry->filename);
  			node = node->next;
  		}
  		PL_UNLOCK();
  		fclose(file);
  		return TRUE;
  	}
  	return FALSE;
--- 697,725 ----
  		while (node)
  		{
  			entry = (PlaylistEntry *) node->data;
! 			if (is_pls) {
  				fprintf(file, "File%d=%s\n", g_list_position(playlist, node) + 1, entry->filename);
! 				fprintf(file, "ArchiveFile%d=%s\n",
! 					g_list_position(playlist, node) + 1,
! 					entry->archive_filename);
! 			} else {
! 			  if (entry->archive_filename != NULL) {
! 			    /* Only include archives once */
! 			    if (!g_hash_table_lookup(archives, entry->archive_filename)) {
! 			      g_hash_table_insert(archives, entry->archive_filename, entry->archive_filename);
! 			      fprintf(file, "%s\n", entry->archive_filename);
! 			    }
! 			  } else {
! 			    fprintf(file, "%s\n", entry->filename);
! 			  }
! 
! 			}
  			node = node->next;
  		}
  		PL_UNLOCK();
  		fclose(file);
+ 
+ 		g_hash_table_destroy(archives);
  		return TRUE;
  	}
  	return FALSE;
***************
*** 665,680 ****
  			*temp = '\0';
  		else
  		{
! 			__playlist_ins(filename, pos);
  			return;
  		}
  		temp = g_strdup_printf("%s/%s", path, filename);
! 		__playlist_ins(temp, pos);
  		g_free(temp);
  		g_free(path);
  	}
  	else
! 		__playlist_ins(filename, pos);
  }
  
  guint playlist_load_ins(gchar * filename, glong pos)
--- 751,768 ----
  			*temp = '\0';
  		else
  		{
! 			__playlist_ins(filename, NULL, pos);
  			return;
  		}
  		temp = g_strdup_printf("%s/%s", path, filename);
! 		__playlist_ins(temp, NULL, pos);
  		g_free(temp);
  		g_free(path);
  	}
+ 	else if (archive_isarchive(filename))
+ 	  playlist_ins_archive(filename, pos);
  	else
! 		__playlist_ins(filename, NULL, pos);
  }
  
  guint playlist_load_ins(gchar * filename, glong pos)
diff -rc --new-file --exclude=Makefile --exclude=Makefile.in xmms-0.9.5.1/xmms/playlist.h xmms-0.9.5.1+mdz/xmms/playlist.h
*** xmms-0.9.5.1/xmms/playlist.h	Sun Sep 12 14:02:33 1999
--- xmms-0.9.5.1+mdz/xmms/playlist.h	Wed Dec  1 21:45:04 1999
***************
*** 20,26 ****
  
  typedef struct
  {
! 	gchar *filename;
  	gchar *title;
  	gint length;
  	gboolean selected;
--- 20,28 ----
  
  typedef struct
  {
!         gchar *filename; /* Member name, if an archive member */
!         gchar *archive_filename;
!         gchar *temp_filename;
  	gchar *title;
  	gint length;
  	gboolean selected;
***************
*** 35,40 ****
--- 37,43 ----
  /*  void playlist_add_dir(gchar * dir); */
  #define playlist_add_dir(directory) playlist_ins_dir(directory, -1)
  guint playlist_ins_dir(gchar * dir, glong pos);
+ guint playlist_ins_archive(gchar *archive, glong pos);
  /*  void playlist_add_url_string(gchar * string); */
  #define playlist_add_url_string(string) playlist_ins_url_string(string, -1)
  guint playlist_ins_url_string(gchar * string, glong pos);
diff -rc --new-file --exclude=Makefile --exclude=Makefile.in xmms-0.9.5.1/xmms/xmms.h xmms-0.9.5.1+mdz/xmms/xmms.h
*** xmms-0.9.5.1/xmms/xmms.h	Sun Sep  5 02:36:42 1999
--- xmms-0.9.5.1+mdz/xmms/xmms.h	Wed Dec  1 19:57:36 1999
***************
*** 75,80 ****
--- 75,81 ----
  #include "equalizer.h"
  #include "about.h"
  #include "hints.h"
+ #include "archive.h"
  
  #include "config.h"
  

--ew6BAiZeqk4r7MaW--

--8X7/QrJGcKSMr1RN--


---------------------------------------
Received: (at 110623-done) by bugs.debian.org; 18 Sep 2005 05:10:25 +0000
>From damog@debian.org Sat Sep 17 22:10:25 2005
Return-path: <damog@debian.org>
Received: from ns3.jiffynet-hosting.net (server146.jiffynet-hosting.net) [69.57.162.87] 
	by spohr.debian.org with esmtp (Exim 3.36 1 (Debian))
	id 1EGrRZ-00066Z-00; Sat, 17 Sep 2005 22:10:25 -0700
Received: from dsl-201-129-37-187.prod-infinitum.com.mx ([201.129.37.187] helo=[192.168.1.48])
	by server146.jiffynet-hosting.net with asmtp (Exim 4.34)
	id 1EGrRN-0003o5-9g
	for 110623-done@bugs.debian.org; Sun, 18 Sep 2005 01:10:18 -0400
Subject: Closing
From: David Moreno Garza <damog@debian.org>
To: 110623-done@bugs.debian.org
Content-Type: text/plain
Date: Sun, 18 Sep 2005 00:09:52 -0500
Message-Id: <1127020192.4857.15.camel@cerdita>
Mime-Version: 1.0
X-Mailer: Evolution 2.2.3 
Content-Transfer-Encoding: 7bit
X-AntiAbuse: This header was added to track abuse, please include it with any abuse report
X-AntiAbuse: Primary Hostname - server146.jiffynet-hosting.net
X-AntiAbuse: Original Domain - bugs.debian.org
X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12]
X-AntiAbuse: Sender Address Domain - debian.org
X-Source: 
X-Source-Args: 
X-Source-Dir: 
Delivered-To: 110623-done@bugs.debian.org
X-Spam-Checker-Version: SpamAssassin 2.60-bugs.debian.org_2005_01_02 
	(1.212-2003-09-23-exp) on spohr.debian.org
X-Spam-Level: 
X-Spam-Status: No, hits=-2.0 required=4.0 tests=BAYES_00,ONEWORD autolearn=no 
	version=2.60-bugs.debian.org_2005_01_02

I'm closing this bug since:

- The patch attached is no longer able to be applied.
- Last activity on the bug was in 2001.

Cheers,

--
David Moreno Garza <damog@damog.net>   | http://www.damog.net/
                   <damog@debian.org>  |         GPG: C671257D
  Come to where the flavor is.



Reply to: