/*  id3.cpp
    Functions to read a ID3 tag from a file

    10.08.2001: tk, initial implementation.

    Copyright (c)2000 by Thomas Kindler, thomas.kindler@gmx.de

    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. Read the
    full License at http://www.gnu.org/copyleft for more details.
*/

// include files -----
//
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "id3v1.h"
#include "misc.h"

static const char* id3genres[] = {
  "Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk", "Grunge",
  "Hip-Hop", "Jazz", "Metal", "New Age", "Oldies", "Other", "Pop", "R&B",
  "Rap", "Reggae", "Rock", "Techno", "Industrial", "Alternative", "Ska",
  "Death Metal", "Pranks", "Soundtrack", "Euro-Techno", "Ambient", "Trip-Hop",
  "Vocal", "Jazz+Funk", "Fusion", "Trance", "Classical", "Instrumental",
  "Acid", "House", "Game", "Sound Clip", "Gospel", "Noise", "Alternative Rock",
  "Bass", "Soul", "Punk", "Space", "Meditative", "Instrumental Pop",
  "Instrumental Rock", "Ethnic", "Gothic", "Darkwave", "Techno-Industrial",
  "Electronic", "Pop-Folk", "Eurodance", "Dream", "Southern Rock", "Comedy",
  "Cult", "Gangsta", "Top 40", "Christian Rap", "Pop/Funk", "Jungle",
  "Native American", "Cabaret", "New Wave", "Psychadelic", "Rave", "Showtunes",
  "Trailer", "Lo-Fi", "Tribal", "Acid Punk", "Acid Jazz", "Polka", "Retro",
  "Musical", "Rock & Roll", "Hard Rock", "Folk", "Folk-Rock", "National Folk",
  "Swing", "Fast Fusion", "Bebob", "Latin", "Revival", "Celtic", "Bluegrass",
  "Avantgarde", "Gothic Rock", "Progressive Rock", "Psychedelic Rock",
  "Symphonic Rock", "Slow Rock", "Big Band", "Chorus", "Easy Listening",
  "Acoustic", "Humour", "Speech", "Chanson", "Opera", "Chamber Music",
  "Sonata", "Symphony", "Booty Bass", "Primus", "Porn Groove", "Satire",
  "Slow Jam", "Club", "Tango", "Samba", "Folklore", "Ballad", "Power Ballad",
  "Rhythmic Soul", "Freestyle", "Duet", "Punk Rock", "Drum Solo", "Acapella",
  "Euro-House", "Dance Hall", "Goa", "Drum & Bass", "Club-House", "Hardcore",
  "Terror", "Indie", "BritPop", "Negerpunk", "Polsk Punk", "Beat",
  "Christian Gangsta Rap", "Heavy Metal", "Black Metal", "Crossover",
  "Contemporary Christian", "Christian Rock", "Merengue", "Salsa", "Thrash Metal",
  "Anime", "Jpop", "Synthpop"
};

#define NUMGENRES sizeof(id3genres)/sizeof(char*)


/**
 * Strip trailing spaces from a padded string field.
 * \note  If the string contains the full length of
 *        characters (i.e. there's no space at the end)
 *        there's no '\0' added to the string!
 * \param str      pointer to string
 * \param length   length of padded string field
 */
static void trim(char *str, int length)
{
  for (int i = length-1; i>=0; i--) {
    if (str[i] == ' ' || str[i] == '\0')
      str[i] = '\0';
    else
      break;
  }
}


/**
 * Get string for a id3v1 genre id.
 * \param   genre  genre id
 * \return  pointer to a string containing the genre, or
 *          the string "genre \#id" for unknown id's.
 */
const char* ID3v1_GetGenreString(int genre)
{
  static char unknown[] = "genre #xxxxx";

  if ((genre < 0) || (genre >= NUMGENRES)) {
    assert(
      sprintf(unknown, "genre #%u", genre)
      < sizeof(unknown)
    );
    return unknown;
  }

  return id3genres[genre];
}

/**
 * Read a ID3, version 1 tag from a file. The file position
 * is restored, after the tag has been read from the end
 * of the file. For further information about the I3v1 Tag,
 * see http://www.id3.org
 *
 * \param   f open File handle to read from
 * \param   tag pointer to a ID3v1Tag structure to fill out
 * \returns 0 if there was no tag, 1 when successful
 */
int ID3v1_ReadTag(FILE *f, ID3v1Tag *tag)
{
  bool tagfound = false;
  long oldpos;
  char magic[3];

  memset(tag, 0, sizeof(ID3v1Tag));

  oldpos = ftell(f);
  fseek(f, -128, SEEK_END);

  fread(magic, sizeof(magic), 1, f);
  if (magic[0]=='T' && magic[1]=='A' && magic[2]=='G') {
    fread( tag->title,   30, 1, f);
    fread( tag->artist,  30, 1, f);
    fread( tag->album,   30, 1, f);
    fread( tag->year,     4, 1, f);
    fread( tag->comment, 30, 1, f);
    fread(&tag->genre,    1, 1, f);

    // ID3v1.1 extension for track number
    //
    if (!tag->comment[28] && tag->comment[29]) {
      tag->track = tag->comment[29];
      tag->comment[29] = '\0';
    }
    trim(tag->title,   30);
    trim(tag->artist,  30);
    trim(tag->album,   30);
    trim(tag->year,     4);
    trim(tag->comment, 30);

    tagfound = true;
  }

  fseek(f, oldpos, SEEK_SET);
  return tagfound;
}


