From da2f107789effc568777ba21d37ec90641f68a10 Mon Sep 17 00:00:00 2001
From: germeier <germeier>
Date: Sat, 19 Apr 2003 09:32:47 +0000
Subject: added ID3 rewriting support

---
 libmpio/Makefile.am |   6 +-
 libmpio/defs.h      |  10 +-
 libmpio/id3.c       | 284 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 libmpio/id3.h       |  44 ++++++++
 libmpio/mpio.c      |  28 ++++--
 libmpio/mpio.h      |  16 ++-
 6 files changed, 375 insertions(+), 13 deletions(-)
 create mode 100644 libmpio/id3.c
 create mode 100644 libmpio/id3.h

(limited to 'libmpio')

diff --git a/libmpio/Makefile.am b/libmpio/Makefile.am
index edf4f10..df15ff4 100644
--- a/libmpio/Makefile.am
+++ b/libmpio/Makefile.am
@@ -12,7 +12,8 @@ libmpio_la_SOURCES= \
 		directory.c \
 		fat.c \
 		ecc.c \
-		cis.c
+		cis.c \
+		id3.c
 
 pkginclude_HEADERS= \
 		mpio.h \
@@ -25,4 +26,5 @@ noinst_HEADERS= \
 		directory.h \
 		fat.h \
 		ecc.h \
-		cis.h
+		cis.h \
+		id3.h
diff --git a/libmpio/defs.h b/libmpio/defs.h
index 36a7361..44b14e7 100644
--- a/libmpio/defs.h
+++ b/libmpio/defs.h
@@ -1,7 +1,7 @@
 /* -*- linux-c -*- */
 
 /* 
- * $Id: defs.h,v 1.21 2003/04/18 13:53:01 germeier Exp $
+ * $Id: defs.h,v 1.22 2003/04/19 09:32:48 germeier Exp $
  *
  * Library for USB MPIO-*
  *
@@ -108,6 +108,8 @@ typedef BYTE mpio_filename_t[MPIO_FILENAME_LEN];
 #define MPIO_DEVICE "/dev/usb/mpio"
 #define MPIO_CHARSET "ISO-8859-15"
 
+#define MPIO_ID3_FORMAT "%p - %t"
+
 #define SECTOR_SIZE      0x200
 #define SECTOR_ECC       0x040
 #define SECTOR_TRANS     (SECTOR_SIZE + SECTOR_ECC)
@@ -124,7 +126,7 @@ typedef BYTE mpio_filename_t[MPIO_FILENAME_LEN];
 
 #define CMD_SIZE         0x40
 
-#define INFO_LINE        81
+#define INFO_LINE        129
 
 /* error codes */
 typedef struct {
@@ -261,6 +263,10 @@ typedef struct {
   int fd;
   BYTE *charset;                   /* charset used for filename conversion */
 
+  BYTE id3;                        /* enable/disable ID3 rewriting support */
+  BYTE id3_format[INFO_LINE];
+  BYTE id3_temp[INFO_LINE];
+  
   mpio_firmware_t firmware;  
 
   mpio_model_t model;
diff --git a/libmpio/id3.c b/libmpio/id3.c
new file mode 100644
index 0000000..b8cce0c
--- /dev/null
+++ b/libmpio/id3.c
@@ -0,0 +1,284 @@
+/*
+ * $Id: id3.c,v 1.1 2003/04/19 09:32:48 germeier Exp $
+ *
+ *  Library for accessing Digit@lways MPIO players
+ *  Copyright (C) 2003 Markus Germeier
+ *
+ *  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.,g 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <iconv.h>
+
+#include "id3.h"
+#include "debug.h"
+#include "mplib.h"
+
+#ifdef MPLIB
+void
+mpio_id3_get_content(id3_tag *tag, id3_tag *tag2, int field, 
+		       BYTE out[INFO_LINE])
+{
+  id3_content  *content;
+  id3_text_content  *text_content;
+
+  content = mp_get_content(tag, field);
+  if (!content)
+    content = mp_get_content(tag2, field);
+  if (content)
+    {
+      text_content = mp_parse_artist(content);
+      debugn(2, "Found (%d): %s\n", field, text_content->text);    
+      strncpy(out, text_content->text, INFO_LINE);
+    } else {
+      strcpy(out,"");
+    }
+
+}
+
+void
+mpio_id3_copy_tag(BYTE *src, BYTE *dest, int *offset)
+{
+  int i=0;
+  
+  while((*offset<(INFO_LINE-1)) && (src[i]!=0x00))
+    dest[(*offset)++]=src[i++];
+}  
+
+#endif /* MPLIB */
+
+BYTE   
+mpio_id3_set(mpio_t *m, BYTE value)
+{
+#ifdef MPLIB
+  m->id3 = value;
+  return m->id3;
+#else
+  return 0;
+#endif /* MPLIB */
+}
+
+/* query ID3 rewriting support */
+BYTE   
+mpio_id3_get(mpio_t *m)
+{
+#ifdef MPLIB
+  return m->id3;  
+#else
+  return 0;
+#endif /* MPLIB */
+}
+
+/* ID3 rewriting: do the work */
+/* context, src filename, uniq filename template */
+int    
+mpio_id3_do(mpio_t *m, BYTE *src, BYTE *tmp)
+{
+#ifdef MPLIB
+  int fd, in;
+  BYTE buf[BLOCK_SIZE];
+  int r, w;
+  int i, j, t;
+  id3_tag *tag, *tag2, *new_tag;
+  id3_tag_list *tag_list;
+  id3_tag_list  new_tag_list;
+  id3_content  *content;
+  id3_content    new_content;
+  id3_text_content  *text_content;
+  id3v2_tag *v2_tag;  
+  BYTE data_artist[INFO_LINE];
+  BYTE data_title[INFO_LINE];
+  BYTE data_album[INFO_LINE];
+  BYTE data_year[INFO_LINE];
+  BYTE data_genre[INFO_LINE];
+  BYTE data_comment[INFO_LINE];
+  BYTE data_track[INFO_LINE];
+
+  BYTE mpio_tag[INFO_LINE];
+  char   *mpio_tag_unicode; 
+
+  char *uc;
+  iconv_t ic;
+  int fin, fout;
+  char *fback, *back;
+
+  if (!m->id3)
+    return 0;
+  
+  sprintf(tmp, "/tmp/MPIO-XXXXXXXXXXXXXXX", INFO_LINE);
+  
+  fd = mkstemp(tmp);
+  if (fd==-1) return 0;
+    sprintf(m->id3_temp, tmp, INFO_LINE);
+
+  in = open(src, O_RDONLY);    
+  if (in==-1) return 0;
+
+  do {
+    r=read(in, buf, BLOCK_SIZE);
+    if (r>0)
+      w=write(fd, buf, r);
+  } while (r>0);
+  
+  close (in);
+
+  tag_list = mp_get_tag_list_from_fd(fd);
+  if (!tag_list)
+    {
+      debug("no tag list found!\n");
+      return 0;
+    }
+
+  tag  = tag_list->tag;
+  tag2 = NULL;
+  if (tag_list->next)
+    tag2 = tag_list->next->tag;
+
+  /* read tags from file */
+  mpio_id3_get_content(tag, tag2, MP_ARTIST,  data_artist);
+  mpio_id3_get_content(tag, tag2, MP_TITLE,   data_title);
+  mpio_id3_get_content(tag, tag2, MP_ALBUM,   data_album);
+  mpio_id3_get_content(tag, tag2, MP_GENRE,   data_genre);
+  mpio_id3_get_content(tag, tag2, MP_COMMENT, data_comment);
+  mpio_id3_get_content(tag, tag2, MP_YEAR,    data_year);
+  mpio_id3_get_content(tag, tag2, MP_TRACK,   data_track);
+  
+  /* build new tag */
+  mpio_tag[0]=0x00;
+  i=j=t=0;
+  
+  while ((t<(INFO_LINE-1) && m->id3_format[i]!=0))
+  {
+    if (m->id3_format[i] == '%') 
+      {
+	i++;
+	switch(m->id3_format[i])
+	  {
+	  case 'p':
+	    mpio_id3_copy_tag(data_artist, mpio_tag, &t);
+	    break;
+	  case 't':
+	    mpio_id3_copy_tag(data_title, mpio_tag, &t);
+	    break;
+	  case 'a':
+	    mpio_id3_copy_tag(data_album, mpio_tag, &t);
+	    break;
+	  case 'g':
+	    mpio_id3_copy_tag(data_genre, mpio_tag, &t);
+	    break;
+	  case 'c':
+	    mpio_id3_copy_tag(data_comment, mpio_tag, &t);
+	    break;
+	  case 'y':
+	    mpio_id3_copy_tag(data_year, mpio_tag, &t);
+	    break;
+	  case 'n':
+	    mpio_id3_copy_tag(data_track, mpio_tag, &t);
+	    break;
+	  default:
+	    mpio_tag[t] = m->id3_format[i];
+	  }
+      } else {    
+	mpio_tag[t] = m->id3_format[i];
+	t++;
+      }
+
+    i++;
+  }
+  mpio_tag[t]=0x00;
+
+  debugn(2, "new_tag: %s\n", mpio_tag);
+
+  /* convert tag to UNICODELITTLE */
+  fin  = strlen(mpio_tag) + 1;
+  fout = fin*2 + 2;  
+  ic = iconv_open("UNICODELITTLE", "ASCII");
+  fback = mpio_tag;
+  mpio_tag_unicode = (char *)malloc(2*INFO_LINE+3);
+  back  = (char *)mpio_tag_unicode;
+  *back=0x01;
+  back++;
+  *back=0xff;
+  back++;
+  *back=0xfe;
+  back++;
+  
+  debugn(2,"iconv before %s %d %d\n", fback, fin, fout);
+  iconv(ic, (char **)&fback, &fin, (char **)&back, &fout);
+  debugn(2,"iconv after %s %d %d\n", fback, fin, fout);
+  iconv_close(ic);
+  hexdumpn(2, mpio_tag, strlen(mpio_tag));
+  hexdumpn(2, (char *)mpio_tag_unicode, (2*strlen(mpio_tag))+3);
+
+  /* build new ID3 v2 tag with only TXXX field */
+  new_content.length=(2*strlen(mpio_tag))+3;
+  new_content.data = (char *)malloc(new_content.length);
+  new_content.compressed=0;
+  new_content.encrypted=0;
+  memcpy(new_content.data, mpio_tag_unicode, new_content.length);
+
+  new_tag = mp_alloc_tag_with_version (2);
+  mp_set_custom_content(new_tag, "TXXX", &new_content);
+
+  v2_tag = (id3v2_tag *)new_tag->tag;
+  v2_tag->header->unsyncronization=0;
+  v2_tag->header->is_experimental=0;
+  
+  new_tag_list.tag   = new_tag;
+  new_tag_list.next  = NULL;
+  new_tag_list.first = NULL;
+
+  /* delete ID3 v2 tag from file */
+  mp_del_tags_by_ver_from_fd(fd, 2);
+  close (fd);
+  
+  /* write new ID3 v2 tag to file */
+  mp_write_to_file(&new_tag_list, tmp);
+
+  free(mpio_tag_unicode);
+
+  return 1;
+#else
+  return 0;
+#endif /* MPLIB */
+}
+
+int    
+mpio_id3_end(mpio_t *m) 
+{
+#ifdef MPLIB
+  if (m->id3_temp[0])
+    unlink(m->id3_temp);
+  m->id3_temp[0] = 0x00;
+  return 1;
+#else
+  return 0;
+#endif /* MPLIB */
+}
+
+void   
+mpio_id3_format_set(mpio_t *m, BYTE *format)
+{
+  strncpy(m->id3_format, format, INFO_LINE);
+}
+  
+/* get format string for rewriting*/
+void
+mpio_id3_format_get(mpio_t *m, BYTE *format)
+{
+  strncpy(format, m->id3_format, INFO_LINE);
+}
diff --git a/libmpio/id3.h b/libmpio/id3.h
new file mode 100644
index 0000000..7ea8940
--- /dev/null
+++ b/libmpio/id3.h
@@ -0,0 +1,44 @@
+/*
+ * $Id: id3.h,v 1.1 2003/04/19 09:32:48 germeier Exp $
+ *
+ *  Library for accessing Digit@lways MPIO players
+ *  Copyright (C) 2003 Markus Germeier
+ *
+ *  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
+ *
+ */
+
+#ifndef _MPIO_ID3_H_
+#define _MPIO_ID3_H_
+
+#include "defs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ID3 rewriting: do the work */
+/* context, src filename, uniq filename template */
+int    mpio_id3_do(mpio_t *, BYTE *, BYTE *);  
+
+/* ID3: clean up temp file */
+int    mpio_id3_end(mpio_t *);
+
+#ifdef __cplusplus
+}
+#endif 
+
+
+#endif /* _MPIO_ID3_H_ */
diff --git a/libmpio/mpio.c b/libmpio/mpio.c
index 444d328..4bf1082 100644
--- a/libmpio/mpio.c
+++ b/libmpio/mpio.c
@@ -1,6 +1,6 @@
 /* 
  *
- * $Id: mpio.c,v 1.51 2003/04/18 13:53:01 germeier Exp $
+ * $Id: mpio.c,v 1.52 2003/04/19 09:32:48 germeier Exp $
  *
  * Library for USB MPIO-*
  *
@@ -107,7 +107,7 @@ static const int mpio_error_num = sizeof mpio_errors / sizeof(mpio_error_t);
 
 static int _mpio_errno = 0;
 
-#define MPIO_ERR_RETURN(err) { _mpio_errno = err; return -1 ; }
+#define MPIO_ERR_RETURN(err) { mpio_id3_end(m); _mpio_errno = err; return -1 ; }
 
 #define MPIO_CHECK_FILENAME(filename) \
   if (!mpio_check_filename(filename)) { \
@@ -388,7 +388,12 @@ mpio_init(mpio_callback_init_t progress_callback)
 
   /* set default charset for filename conversion */
   new_mpio->charset=strdup(MPIO_CHARSET);
-  
+
+  /* disable ID3 rewriting support */
+  new_mpio->id3=0; 
+  strncpy(new_mpio->id3_format, MPIO_ID3_FORMAT, INFO_LINE);
+  new_mpio->id3_temp[0]=0x00;
+
   return new_mpio;  
 }
 
@@ -652,10 +657,12 @@ mpio_file_put_real(mpio_t *m, mpio_mem_t mem, mpio_filename_t i_filename,
   mpio_fatentry_t   *f, current, firstblock, backup; 
   WORD start;
   BYTE block[BLOCK_SIZE];
+  BYTE use_filename[INFO_LINE];
   int fd, toread;
   struct stat file_stat;
   struct tm tt;
   time_t curr;
+  int id3;
 
   BYTE *p = NULL;
   DWORD filesize, fsize, free, blocks;
@@ -674,8 +681,11 @@ mpio_file_put_real(mpio_t *m, mpio_mem_t mem, mpio_filename_t i_filename,
     {
       fsize=filesize=memory_size;
     } else {      
-      if (stat((const char *)i_filename, &file_stat)!=0) {
-	debug("could not find file: %s\n", i_filename);
+      id3 = mpio_id3_do(m, i_filename, use_filename);
+      if (!id3)
+	strncat(use_filename, i_filename, INFO_LINE);
+      if (stat((const char *)use_filename, &file_stat)!=0) {
+	debug("could not find file: %s\n", use_filename);
 	MPIO_ERR_RETURN(MPIO_ERR_FILE_NOT_FOUND);
       }
       fsize=filesize=file_stat.st_size;
@@ -731,11 +741,11 @@ mpio_file_put_real(mpio_t *m, mpio_mem_t mem, mpio_filename_t i_filename,
 
   if (!memory)
     {      
-      /* open file for writing */
-      fd = open(i_filename, O_RDONLY);    
+      /* open file for reading */
+      fd = open(use_filename, O_RDONLY);    
       if (fd==-1) 
 	{
-	  debug("could not open file: %s\n", i_filename);
+	  debug("could not open file: %s\n", use_filename);
 	  MPIO_ERR_RETURN(MPIO_ERR_FILE_NOT_FOUND);
 	}
     }
@@ -858,6 +868,8 @@ mpio_file_put_real(mpio_t *m, mpio_mem_t mem, mpio_filename_t i_filename,
 		      fsize, start, 0x20);
     }  
 
+  mpio_id3_end(m);
+
   return fsize-filesize;
 }
 
diff --git a/libmpio/mpio.h b/libmpio/mpio.h
index c96888d..64cd113 100644
--- a/libmpio/mpio.h
+++ b/libmpio/mpio.h
@@ -1,7 +1,7 @@
 #/* -*- linux-c -*- */
 
 /* 
- * $Id: mpio.h,v 1.16 2003/04/18 13:53:01 germeier Exp $
+ * $Id: mpio.h,v 1.17 2003/04/19 09:32:48 germeier Exp $
  *
  * Library for USB MPIO-*
  *
@@ -156,6 +156,20 @@ int	mpio_memory_format(mpio_t *, mpio_mem_t, mpio_callback_t);
 /* context, memory bank */
 int	mpio_sync(mpio_t *, mpio_mem_t);
 
+/*
+ * ID3 rewriting support
+ */
+
+/* enable disable ID3 rewriting support */
+BYTE   mpio_id3_set(mpio_t *, BYTE);
+/* query ID3 rewriting support */
+BYTE   mpio_id3_get(mpio_t *);
+
+/* set format string for rewriting*/
+void   mpio_id3_format_set(mpio_t *, BYTE *);
+/* get format string for rewriting*/
+void   mpio_id3_format_get(mpio_t *, BYTE *);
+
 /*
  * "special" functions
  */
-- 
cgit v1.2.3