diff src/demac/apev2.c @ 2182:cc5e9ec110a4

Added initial version of Monkey's Audio plugin
author Eugene Zagidullin <e.asphyx@gmail.com>
date Thu, 22 Nov 2007 02:54:06 +0300
parents
children 2984f6c7221a
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/demac/apev2.c	Thu Nov 22 02:54:06 2007 +0300
@@ -0,0 +1,116 @@
+/* 
+ * 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 "apev2.h"
+
+
+static int read_uint32(VFSFile *vfd, guint32* x) {
+    unsigned char tmp[4];
+    int n;
+
+    n = aud_vfs_fread(tmp, 1, 4, vfd);
+
+    if (n != 4)
+        return -1;
+    
+    /* convert to native endianness */
+    *x = tmp[0] | (tmp[1] << 8) | (tmp[2] << 16) | (tmp[3] << 24);
+
+    return 0;
+}
+
+#define TMP_BUFSIZE 256
+#ifndef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+GHashTable* parse_apev2_tag(VFSFile *vfd) {
+  unsigned char tmp[TMP_BUFSIZE+1];
+  unsigned char tmp2[TMP_BUFSIZE+1];
+  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);
+  aud_vfs_fread(tmp, 1, 8, vfd);
+  if ((tmp[0]!='A')||(tmp[1]!='P')||(tmp[2]!='E')||(tmp[3]!='T')||
+     (tmp[4]!='A')||(tmp[5]!='G')||(tmp[6]!='E')||(tmp[7]!='X')) {
+#ifdef DEBUG
+    fprintf(stderr, "** demac: apev2.c: APE tag not found\n");
+#endif
+    return NULL;
+  }
+  
+  read_uint32(vfd, &tag_version);
+  read_uint32(vfd, &tag_size);
+  read_uint32(vfd, &tag_items);
+  read_uint32(vfd, &tag_flags);
+#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(g_str_hash, g_str_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++) {
+      read_uint32(vfd, &item_size);
+      read_uint32(vfd, &item_flags);
+      
+      /* 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;
+}