view src/demac/apev2.c @ 2193:80d7ab8f2ec5

removed some duplicated code
author Eugene Zagidullin <e.asphyx@gmail.com>
date Wed, 28 Nov 2007 16:19:57 +0300
parents 2984f6c7221a
children dfa3c3aa2dc7
line wrap: on
line source

/* 
 * Audacious Monkey's Audio plugin, an APE tag reading stuff
 *
 * Copyright (C) Eugene Zagidullin 2007
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or 
 * (at your option) any later version. 
 *  
 * This program 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 General Public License for more details. 
 *  
 * You should have received a copy of the GNU General Public License 
 * along with this program; if not, write to the Free Software 
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
 *
 */

#include <stdio.h> 
#include <stdlib.h> 
#include <errno.h> 
#include <string.h> 

#include <glib.h>
#include <audacious/vfs.h>
#include <audacious/plugin.h> 

#include "ape.h"
#include "apev2.h"

#define TMP_BUFSIZE 256
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif

static gboolean strcase_equal (gconstpointer v1, gconstpointer v2) {
  return (g_ascii_strcasecmp((gchar *)v1, (gchar *)v2) == 0);
}

static guint strcase_hash (gconstpointer v) {
  gchar *tmp;
  gchar buf[TMP_BUFSIZE+1];
  gchar *p = buf;
  
  for(tmp=(gchar*)v; (*tmp && (p < buf+TMP_BUFSIZE)); tmp++)
    *(p++) = g_ascii_toupper(*tmp);
  *p = '\0';
  return g_str_hash((gconstpointer)buf);
}

GHashTable* parse_apev2_tag(VFSFile *vfd) {
  unsigned char tmp[TMP_BUFSIZE+1];
  unsigned char tmp2[TMP_BUFSIZE+1];
  guint64 signature;
  guint32 tag_version;
  guint32 tag_size, item_size, item_flags;
  guint32 tag_items;
  guint32 tag_flags;
  GHashTable *hash;

  aud_vfs_fseek(vfd, -32, SEEK_END);
  signature = get_le64(vfd);
  if (signature != MKTAG64('A', 'P', 'E', 'T', 'A', 'G', 'E', 'X')) {
#ifdef DEBUG
    fprintf(stderr, "** demac: apev2.c: APE tag not found\n");
#endif
    return NULL;
  }
  
  tag_version = get_le32(vfd);
  tag_size = get_le32(vfd);
  tag_items = get_le32(vfd);
  tag_flags = get_le32(vfd);
#ifdef DEBUG
  fprintf(stderr, "** demac: apev2.c: found APE tag version %d contains %d items, flags %08x\n", tag_version, tag_items, tag_flags);
#endif
  if(tag_items == 0) {
#ifdef DEBUG
    fprintf(stderr, "** demac: apev2.c: found empty tag\n");
#endif
    return NULL;
  }
  
  hash = g_hash_table_new_full(strcase_hash, strcase_equal, g_free, g_free); /* string-keyed table with dynamically allocated keys and items */

  aud_vfs_fseek(vfd, -tag_size, SEEK_END);
  int i;
  unsigned char *p;
  for(i=0; i<tag_items; i++) {
      item_size = get_le32(vfd);
      item_flags = get_le32(vfd);
      
      /* read key */
      for(p = tmp; p <= tmp+TMP_BUFSIZE; p++) {
        aud_vfs_fread(p, 1, 1, vfd);
	if(*p == '\0') break;
      }
      *(p+1) = '\0';

      /* read item */
      aud_vfs_fread(tmp2, 1, MIN(item_size, TMP_BUFSIZE), vfd);
      tmp2[item_size] = '\0';
#ifdef DEBUG
      fprintf(stderr, "%s: \"%s\", f:%08x\n", tmp, tmp2, item_flags);
#endif
      /* APEv2 stores all items in utf-8 */
      gchar *item = ((tag_version == 1000 ) ? aud_str_to_utf8((gchar*)tmp2) : g_strdup((gchar*)tmp2));
      
      g_hash_table_insert (hash, g_strdup((gchar*)tmp), item);
  }
  
  return hash;
}