Logo Search packages:      
Sourcecode: xmms-scrobbler version File versions  Download package

ape.c

/*
 *   libmetatag - A media file tag-reader library
 *   Copyright (C) 2003, 2004  Pipian
 *
 *   This library is free software; you can redistribute it and/or
 *   modify it under the terms of the GNU Lesser General Public
 *   License as published by the Free Software Foundation; either
 *   version 2.1 of the License, or (at your option) any later version.
 *
 *   This library is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *   Lesser General Public License for more details.
 *
 *   You should have received a copy of the GNU Lesser General Public
 *   License along with this library; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef MAKE_BMP
#include "include/bmp_vfs.h"
#endif
#include "include/ape.h"
#include "include/endian.h"
#include "../fmt.h"
#include "../config.h"
#include "include/unicode.h"
#define BUFFER_SIZE 4096

static ape_t *readItems(FILE *fp, int version)
{
      ape_t *ape = calloc(sizeof(ape_t), 1);
      unsigned char *tag_buffer = NULL, *bp, cToInt[4];
      int size, start, i;
      
      ape->version = version;

      /*
       * Now for the actual reading.
       * APE2 and APE1 tags are identical for all the structure we care about.
       */

      fread(cToInt, 1, 4, fp);
      size = le2int(cToInt);
      fread(cToInt, 1, 4, fp);
      ape->numitems = le2int(cToInt);
      /* pdebug(fmt_vastr("tag size: %d", size));
      pdebug(fmt_vastr("items: %d", ape->numitems)); */
      fread(cToInt, 1, 4, fp);
      /* Is it a footer?  Header? */
      if((cToInt[3] & 0x20) == 0x0 || version == 1000)
            start = 8 - size;
      else
            start = 8;
      fseek(fp, start, SEEK_CUR);

      tag_buffer = realloc(tag_buffer, size);
      fread(tag_buffer, 1, size, fp);
      bp = tag_buffer;
      
      ape->items = realloc(ape->items,
                  (ape->numitems) * sizeof(apefielddata_t *));
      
      for(i = 0; i < ape->numitems && strncmp(bp, "APETAGEX", 8) != 0; i++)
      {
            apefielddata_t *field = calloc(sizeof(apefielddata_t), 1);
            
            memcpy(cToInt, bp, 4);        
            bp += 8;          
            field->len = le2int(cToInt);
            field->name = malloc(strlen(bp) + 1);
            strcpy(field->name, bp);
            bp += strlen(bp) + 1;
            field->data = malloc(field->len + 1);
            memcpy(field->data, bp, field->len);
            *(field->data + field->len) = '\0';
            bp += field->len;
            
            ape->items[i] = field;        
      }
      if(i < ape->numitems && strncmp(bp, "APETAGEX", 8) == 0)
      {
            ape->numitems = i;
            ape->items = realloc(ape->items,
                  (ape->numitems) * sizeof(apefielddata_t *));
      }
            

      free(tag_buffer);
      
      return ape;
}

int findAPE(FILE *fp)
{
      unsigned char *tag_buffer, *bp, cToInt[4];
      int pb = 0, status = 0, pos = 0, i, ape_version;
      
      /* Find the tag header or footer and point the file pointer there. */
      tag_buffer = malloc(BUFFER_SIZE);
      pb += fread(tag_buffer, 1, BUFFER_SIZE, fp);
      bp = tag_buffer;
      while(status == 0)
      {
            for(i = 0; i < BUFFER_SIZE - 8 && status == 0; i++)
            {
                  bp++;
                  if(!strncmp(bp, "APETAGEX", 8))
                        status = 1;
            }
            if(status == 1 || feof(fp))
                  break;
            memmove(tag_buffer, tag_buffer + BUFFER_SIZE - 7, 7);
            pos += BUFFER_SIZE - 7;
            pb += fread(tag_buffer + 7, 1, BUFFER_SIZE - 7, fp);
            bp = tag_buffer;
      }
      if(status == 1)
      {
            fseek(fp, pos + (bp - tag_buffer) + 8, SEEK_SET);

            free(tag_buffer);
            
            /* Get the tag version. */
            fread(cToInt, 1, 4, fp);
            ape_version = le2int(cToInt);
            pdebug(ape_version == 1000 ? "Found APE1 tag..." :
                  ape_version == 2000 ? "Found APE2 tag..." :
                  "Found unknown APE tag...", META_DEBUG);
            
            return ape_version;
      }
      else
      {
            free(tag_buffer);
            return 0;
      }
}

ape_t *readAPE(char *filename)
{
      FILE *fp;
      ape_t *ape;
      int status;
      
      fp = fopen(filename, "r");

      if(!fp)
      {
            pdebug("Couldn't open file!", META_DEBUG);
            return NULL;
      }
      
      fseek(fp, 0, SEEK_SET);
      
      pdebug("Searching for tag...", META_DEBUG);
      status = findAPE(fp);
      if(status == 0)
      {
            fclose(fp);
            return NULL;
      }
      ape = readItems(fp, status);
      
      fclose(fp);
      
      return ape;
}

void freeAPE(ape_t *ape)
{
      int i;
      
      for(i = 0; i < ape->numitems; i++)
      {
            apefielddata_t *field;
            
            field = ape->items[i];
            free(field->name);
            free(field->data);
            free(field);
      }
      free(ape->items);
      free(ape);
}

Generated by  Doxygen 1.6.0   Back to index