void GetTestTag(void)
{
  ID3_Tag  myTag("dummy.tag");
  ID3_Frame *myFrame;

  if (myFrame = myTag.Find(ID3FID_PICTURE))
  {
    cout << "Found a picture frame!\r\n" << endl;

    char *dada = "output.jpg";

    myFrame->Field(ID3FN_DATA).ToFile(dada);
  }

  if (myFrame = myTag.Find(ID3FID_USERTEXT, ID3FN_DESCRIPTION, "example #1"))
  {
    cout << "Found a user text frame!\r\n" << endl;

    char textBuff[1024];

    myFrame->Field(ID3FN_DESCRIPTION).Get(textBuff, 1024);
    cout << "Desc: " << textBuff << endl;

    myFrame->Field(ID3FN_TEXT).Get(textBuff, 1024);
    cout << "Text: " << textBuff << endl;
  }

  for (luint i = 0; i < myTag.NumFrames(); i++)
    if (myFrame = myTag[i])
      cout << "Frame " << i << " has ID " << (luint) myFrame->GetID() << endl;

  return;
}
Exemple #2
0
ID3_Frame		*ID3_Tag::Find( ID3_FrameID id, ID3_FieldID fld, wchar_t *data )
{
	ID3_Frame	*frame	= NULL;
	ID3_Elem	*cur	= findCursor;
	bool		done	= false;

	if	( cur == NULL )
		findCursor = cur = frameList;

	while	( ! done && cur )
	{
		if	( cur->frame && ( cur->frame->GetID() == id ) )
		{
			frame = cur->frame;

			if	( data && wcslen ( data ) && BS_ISSET ( frame->fieldBits, fld ) )
			{
				wchar_t	*buffer;
				luint	size;

				size = frame->Field ( fld ).BinSize();

#ifdef _DEBUG
				//ASSERT( size < MAX_ALLOC ); // PL
#endif
				buffer = new wchar_t[size];
				{
					frame->Field ( fld ).Get(buffer, size);

					if(wcscmp(buffer, data) != 0 )
					{
						frame = NULL;
						cur = cur->next;
					}

					delete[] buffer;
				}
			}

			if	( frame )
			{
				findCursor = cur->next;
				break;
			}
		}
		else
			cur = cur->next;

		if	( cur == NULL )
			cur = frameList;

		if	( cur == findCursor )
			done = true;
	}

	return frame;
}
Exemple #3
0
ID3_Frame* ID3_AddComment(ID3_Tag *tag, const char *sComment,
                          const char *sDescription, bool bReplace)
{
  ID3_Frame* pFrame = NULL;
  if (NULL != tag          &&
      NULL != sComment     &&
      NULL != sDescription && 
      strlen(sComment) > 0)
  {
    bool bAdd = true;
    if (bReplace)
    {
      ID3_RemoveComments(tag, sDescription);
    }
    else
    {
      // See if there is already a comment with this description
      for (size_t nCount = 0; nCount < tag->NumFrames(); nCount++)
      {
        pFrame = tag->GetFrameNum(nCount);
        if (pFrame->GetID() == ID3FID_COMMENT)
        {
          char *sDesc = ID3_GetString(pFrame, ID3FN_DESCRIPTION);
          if (strcmp(sDesc, sDescription) == 0)
          {
            bAdd = false;
          }
          delete [] sDesc;
          if (!bAdd)
          {
            break;
          }
        }
      }
    }
    if (bAdd)
    {
      pFrame = new ID3_Frame(ID3FID_COMMENT);
      if (NULL != pFrame)
      {
        pFrame->Field(ID3FN_LANGUAGE) = "eng";
        pFrame->Field(ID3FN_DESCRIPTION) = sDescription;
        pFrame->Field(ID3FN_TEXT) = sComment;
        tag->AttachFrame(pFrame);
      }
    }
  }
  return pFrame;
}
Exemple #4
0
ID3_Frame* ID3_AddGenre(ID3_Tag *tag, size_t ucGenre, bool bReplace)
{
  ID3_Frame* pFrame = NULL;
  if (NULL != tag && 0xFF != ucGenre)
  {
    if (bReplace)
    {
      ID3_RemoveGenres(tag);
    }
    if (bReplace || NULL == tag->Find(ID3FID_CONTENTTYPE))
    {
      pFrame = new ID3_Frame(ID3FID_CONTENTTYPE);
      if (NULL != pFrame)
      {
        char sGenre[6];
        sprintf(sGenre, "(%lu)", (luint) ucGenre);

        pFrame->Field(ID3FN_TEXT) = sGenre;
        tag->AttachFrame(pFrame);
      }
    }
  }
  
  return pFrame;
}
Exemple #5
0
ID3_Frame* ID3_AddArtist(ID3_Tag *tag, const char *text, bool bReplace)
{
  ID3_Frame* pFrame = NULL;
  if (NULL != tag && NULL != text && strlen(text) > 0)
  {
    if (bReplace)
    {
      ID3_RemoveArtists(tag);
    }
    if (bReplace ||
        (tag->Find(ID3FID_LEADARTIST) == NULL &&
         tag->Find(ID3FID_BAND)       == NULL &&
         tag->Find(ID3FID_CONDUCTOR)  == NULL &&
         tag->Find(ID3FID_COMPOSER)   == NULL))
    {
      pFrame = new ID3_Frame(ID3FID_LEADARTIST);
      if (pFrame)
      {
        pFrame->Field(ID3FN_TEXT) = text;
        tag->AttachFrame(pFrame);
      }
    }
  }

  return pFrame;
}
Exemple #6
0
int CMP4Tag::ReadAacTag(char *Filename)
{
char	*buf=NULL;
ID3_Tag id3Tag;
ID3_Frame *Frame;

	if(!id3Tag.Link(Filename))
	{
	char buf[25+MAX_PATH+1];
		sprintf(buf,"ReadAacTag: can't open \"%s\"",Filename);
		MessageBox(NULL,buf,NULL,MB_OK);
		return 1;
	}

	GET_FIELD_STR(id3Tag,ID3FID_ENCODEDBY,ID3FN_TEXT,copyright);

	GET_FIELD_STR(id3Tag,ID3FID_LEADARTIST,ID3FN_TEXT,artist);
	GET_FIELD_STR(id3Tag,ID3FID_COMPOSER,ID3FN_TEXT,writer);
	GET_FIELD_STR(id3Tag,ID3FID_TITLE,ID3FN_TEXT,title);
	GET_FIELD_STR(id3Tag,ID3FID_ALBUM,ID3FN_TEXT,album);

	GET_FIELD_STR(id3Tag,ID3FID_TRACKNUM,ID3FN_TEXT,buf);
	if(buf)
		trackno=atoi(buf);
	FREE_ARRAY(buf);
	GET_FIELD_STR(id3Tag,ID3FID_YEAR,ID3FN_TEXT,year);
	GET_FIELD_STR(id3Tag,ID3FID_CONTENTTYPE,ID3FN_TEXT,genre);
	GET_FIELD_STR(id3Tag,ID3FID_COMMENT,ID3FN_TEXT,comment);

	if(Frame=id3Tag.Find(ID3FID_PICTURE))
	{
		art.size=Frame->Field(ID3FN_DATA).Size();
		FREE_ARRAY(art.data);
		if(art.data=(char *)malloc(art.size))
			memcpy(art.data,Frame->Field(ID3FN_DATA).GetBinary(),art.size);

		GET_FIELD_STR(id3Tag,ID3FID_PICTURE,ID3FN_MIMETYPE,art.mimeType);
		GET_FIELD_STR(id3Tag,ID3FID_PICTURE,ID3FN_DESCRIPTION,art.description);
		GET_FIELD_STR(id3Tag,ID3FID_PICTURE,ID3FN_IMAGEFORMAT,art.format);
		art.pictureType=Frame->Field(ID3FN_PICTURETYPE).Get();
/*
	FILE *f=fopen("D:\\prova.jpg","wb");
		fwrite(artFile,1,artSize,f);
		fclose(f);*/
	}
	return 0;
}
Exemple #7
0
ID3_Frame* ID3_AddSyncLyrics(ID3_Tag *tag, const char *lang, const char *desc,
                             const uchar *text, size_t textsize, bool bReplace)
{
  ID3_Frame* pFrame = NULL;
  // language and descriptor should be mandatory
  if ((NULL == lang) || (NULL == desc))
  {
    return NULL;
  }

  // check if a SYLT frame of this language or descriptor already exists
  ID3_Frame* pFrameExist = tag->Find(ID3FID_SYNCEDLYRICS, ID3FN_LANGUAGE, 
                                     (char *) lang);
  if (!pFrameExist)
  {
    pFrameExist = tag->Find(ID3FID_SYNCEDLYRICS, ID3FN_DESCRIPTION, 
                            (char *) desc);
  }

  if (NULL != tag && NULL != text)
  {
    if (bReplace && pFrameExist)
    {
      tag->RemoveFrame (pFrameExist);
      pFrameExist = NULL;
    }

    // if the frame still exist, cannot continue
    if (pFrameExist)
    {
      return NULL;
    }

    ID3_Frame* pFrame = new ID3_Frame(ID3FID_SYNCEDLYRICS);
    if (NULL == pFrame)
    {
      ID3_THROW(ID3E_NoMemory);
    }

    pFrame->Field(ID3FN_LANGUAGE) = lang;
    pFrame->Field(ID3FN_DESCRIPTION) = desc;
    pFrame->Field(ID3FN_DATA).Set(text, textsize);
    tag->AttachFrame(pFrame);
  }

  return pFrame;
}
void ID3_AddLyrics( ID3_Tag *tag, char *text )
{
	if	( tag->Find ( ID3FID_UNSYNCEDLYRICS ) == NULL && strlen ( text ) > 0 )
	{
		ID3_Frame	*lyricsFrame;

		if	( lyricsFrame = new ID3_Frame )
		{
			lyricsFrame->SetID ( ID3FID_UNSYNCEDLYRICS );
			lyricsFrame->Field ( ID3FN_LANGUAGE ) = "eng";
			lyricsFrame->Field ( ID3FN_TEXT ) = text;
			tag->AddFrame ( lyricsFrame, true );
		}
		else
			ID3_THROW ( ID3E_NoMemory );
	}

	return;
}
Exemple #9
0
ID3_Frame *ID3_GetSyncLyricsInfo(const ID3_Tag *tag, const char *lang, 
                                 const char *desc, size_t& stampformat, 
                                 size_t& type, size_t& size)
{
  // check if a SYLT frame of this language or descriptor exists
  ID3_Frame* pFrameExist = NULL;
  if (NULL != lang)
  {
    // search through language
    pFrameExist = tag->Find(ID3FID_SYNCEDLYRICS, ID3FN_LANGUAGE, lang);
  }
  else if (NULL != desc)
  {
    // search through descriptor
    pFrameExist = tag->Find(ID3FID_SYNCEDLYRICS, ID3FN_DESCRIPTION, desc);
  }
  else
  {
    // both language and description not specified, search the first SYLT frame
    pFrameExist = tag->Find(ID3FID_SYNCEDLYRICS);
  }
  
  if (!pFrameExist)
  {
    return NULL;
  }
  
  // get the lyrics time stamp format
  stampformat = pFrameExist->Field (ID3FN_TIMESTAMPFORMAT).Get ();
  
  // get the lyrics content type
  type = pFrameExist->Field (ID3FN_CONTENTTYPE).Get ();
  
  // get the lyrics size
  size = pFrameExist->Field (ID3FN_DATA).Size ();
  
  // return the frame pointer for further uses
  return pFrameExist;
}
Exemple #10
0
ID3_Frame* ID3_AddLyrics(ID3_Tag *tag, const char *text, bool bReplace)
{
  ID3_Frame* pFrame = NULL;
  if (NULL != tag && strlen(text) > 0)
  {
    if (bReplace)
    {
      ID3_RemoveLyrics(tag);
    }
    if (bReplace || tag->Find(ID3FID_UNSYNCEDLYRICS) == NULL)
    {
      pFrame = new ID3_Frame(ID3FID_UNSYNCEDLYRICS);
      if (NULL != pFrame)
      {
        pFrame->Field(ID3FN_LANGUAGE) = "eng";
        pFrame->Field(ID3FN_TEXT) = text;
        tag->AttachFrame(pFrame);
      }
    }
  }
  
  return pFrame;
}
Exemple #11
0
ID3_Frame *ID3_GetSyncLyrics(const ID3_Tag *tag, const char *lang, 
                             const char *desc, const uchar *pData, size_t& size)
{
  // check if a SYLT frame of this language or descriptor exists
  ID3_Frame* pFrameExist = NULL;
  if (NULL != lang)
  {
    // search through language
    pFrameExist = tag->Find(ID3FID_SYNCEDLYRICS, ID3FN_LANGUAGE, lang);
  }
  else if (NULL != desc)
  {
    // search through descriptor
    pFrameExist = tag->Find(ID3FID_SYNCEDLYRICS, ID3FN_DESCRIPTION, desc);
  }
  else
  {
    // both language and description not specified, search the first SYLT frame
    pFrameExist = tag->Find(ID3FID_SYNCEDLYRICS);
  }

  if (NULL == pFrameExist)
  {
    return NULL;
  }
  
  // get the lyrics size
  size_t datasize = pFrameExist->Field(ID3FN_DATA).Size();
  size = MIN(size, datasize);

  // get the lyrics data
  pData = pFrameExist->Field (ID3FN_DATA).GetBinary();

  // return the frame pointer for further uses
  return pFrameExist;
}
Exemple #12
0
ID3_Frame* ID3_AddMCDI(ID3_Tag *tag, const char *text, bool bReplace)
{
    ID3_Frame* pFrame = NULL;
    if (NULL != tag && NULL != text && strlen(text) > 0)
    {
        if (bReplace)
        {
            ID3_RemoveMCDI(tag);
        }
        if (bReplace || tag->Find(ID3FID_CDID) == NULL)
        {
            pFrame = new ID3_Frame( ID3FID_CDID );
            if (pFrame)
            {
                const int nMaxTagLength = 804;

                size_t nStrLen = strlen( text );

                uchar *temp = new uchar[ nMaxTagLength + 1 ];

                memset( temp, sizeof( temp ), 0 );
                if ( NULL == temp )
                {
                    // AF ID3_THROW( ID3E_NoMemory );
                }

                memset( temp, 0x00, sizeof( temp ) );

                //fixes 99 tracks bug
                if( nStrLen > nMaxTagLength / 2 )
                {
                    nStrLen = nMaxTagLength / 2;
                }

//                mbstoucs( (unicode_t *)temp, text, nStrLen + 1 );

                pFrame->Field(ID3FN_DATA).Set(	temp,
                                                nMaxTagLength );

//                delete[] temp;

                tag->AttachFrame( pFrame );
            }
        }
    }

    return pFrame;
}
Exemple #13
0
void			ID3_AddAlbum					( ID3_Tag *tag, char *text )
{
	if	( tag->Find ( ID3FID_ALBUM ) == NULL && strlen ( text ) > 0 )
	{
		ID3_Frame	*albumFrame;

		if	( albumFrame = new ID3_Frame )
		{
			albumFrame->SetID ( ID3FID_ALBUM );
			albumFrame->Field ( ID3FN_TEXT ) = text;
			tag->AddFrame ( albumFrame, true );
		}
		else
			ID3_THROW ( ID3E_NoMemory );
	}

	return;
}
Exemple #14
0
void			ID3_AddTitle					( ID3_Tag *tag, char *text )
{
	if	( tag->Find ( ID3FID_TITLE ) == NULL && strlen ( text ) > 0 )
	{
		ID3_Frame	*titleFrame;

		if	( titleFrame = new ID3_Frame )
		{
			titleFrame->SetID ( ID3FID_TITLE );
			titleFrame->Field ( ID3FN_TEXT ) = text;
			tag->AddFrame ( titleFrame, true );
		}
		else
			ID3_THROW ( ID3E_NoMemory );
	}

	return;
}
Exemple #15
0
ID3_Frame* ID3_AddSongLen(ID3_Tag *tag, const char *text, bool bReplace)
{
    ID3_Frame* pFrame = NULL;
    if (NULL != tag && NULL != text && strlen(text) > 0)
    {
        if (bReplace)
        {
            ID3_RemoveSongLen( tag );
        }
        if (bReplace || tag->Find(ID3FID_SONGLEN) == NULL)
        {
            pFrame = new ID3_Frame(ID3FID_SONGLEN);
            if (pFrame)
            {
                pFrame->Field(ID3FN_TEXT) = text;
                tag->AttachFrame(pFrame);
            }
        }
    }

    return pFrame;
}
Exemple #16
0
void			ID3_AddArtist					( ID3_Tag *tag, char *text )
{
	if	( tag->Find ( ID3FID_LEADARTIST ) == NULL &&
		  tag->Find ( ID3FID_BAND ) == NULL &&
		  tag->Find ( ID3FID_CONDUCTOR ) == NULL &&
		  tag->Find ( ID3FID_COMPOSER ) == NULL &&
		  strlen ( text ) > 0 )
		{
			ID3_Frame	*artistFrame;

			if	( artistFrame = new ID3_Frame )
			{
				artistFrame->SetID ( ID3FID_LEADARTIST );
				artistFrame->Field ( ID3FN_TEXT ) = text;
				tag->AddFrame ( artistFrame, true );
			}
			else
				ID3_THROW ( ID3E_NoMemory );
		}

	return;
}
Exemple #17
0
char *ID3_GetMCDI(const ID3_Tag *tag)
{
    char *sComment = NULL;
    uchar temp[ 805 ];

    memset( temp, 0, sizeof( temp ) );

    if (NULL == tag)
    {
        return sComment;
    }

    ID3_Frame *pFrame = tag->Find(ID3FID_CDID);
    if (pFrame != NULL)
    {
        int nStrLen = 0;
        //sComment = ID3_GetString(pFrame, ID3FN_TEXT);


        char *sComment = new char[ 805 ];

        memset( sComment, sizeof( sComment ), 0 );

        if ( NULL == temp )
        {
            // AF ID3_THROW(ID3E_NoMemory);
        }

        pFrame->Field(ID3FN_DATA).Get(	temp,
                                        804 );

        nStrLen = ucslen( (unicode_t *) temp );


//	ucstombs( sComment, (unicode_t *)temp, nStrLen + 1 );

    }
    return sComment;
}
Exemple #18
0
ID3_Frame		*ID3_Tag::Find					( ID3_FrameID id, ID3_FieldID fld, luint data )
{
	ID3_Frame	*frame	= NULL;
	ID3_Elem	*cur	= findCursor;
	bool		done	= false;

	if	( cur == NULL )
		findCursor = cur = frameList;

	while	( ! done && cur )
	{
		if	( cur->frame && ( cur->frame->GetID() == id ) )
		{
			frame = cur->frame;

			if	( frame->Field ( fld ).Get() != data )
			{
				frame = NULL;
				cur = cur->next;
			}

			if	( frame )
			{
				findCursor = cur->next;
				break;
			}
		}
		else
			cur = cur->next;

		if	( cur == NULL )
			cur = frameList;

		if	( cur == findCursor )
			done = true;
	}

	return frame;
}
Exemple #19
0
ID3_Frame* ID3_AddLyricist(ID3_Tag *tag, const char *text, bool bReplace)
{
  ID3_Frame* pFrame = NULL;
  if (NULL != tag && NULL != text && strlen(text) > 0)
  {
    if (bReplace)
    {
      ID3_RemoveLyricist(tag);
    }
    if (bReplace || (tag->Find(ID3FID_LYRICIST) == NULL))
    {    
      pFrame = new ID3_Frame(ID3FID_LYRICIST);
      if (pFrame)
      {
        pFrame->Field(ID3FN_TEXT) = text;
        tag->AttachFrame(pFrame);
      }
    }
  }

  return pFrame;
}
Exemple #20
0
ID3_Frame* ID3_AddEncodedBy(ID3_Tag *tag, const char *text, bool bReplace)
{
    ID3_Frame* pFrame = NULL;
    if (NULL != tag && NULL != text && strlen(text) > 0)
    {
        if (bReplace)
        {
            ID3_RemoveEncodedBy(tag);
        }
        if (bReplace || tag->Find(ID3FID_ENCODEDBY) == NULL)
        {
            pFrame = new ID3_Frame(ID3FID_ENCODEDBY);
            if (pFrame)
            {
                pFrame->Field(ID3FN_TEXT) = text;
                tag->AttachFrame(pFrame);
            }
        }
    }

    return pFrame;
}
Exemple #21
0
ID3_Frame* ID3_AddTrack(ID3_Tag *tag, uchar ucTrack, uchar ucTotal, bool bReplace)
{
  ID3_Frame* pFrame = NULL;
  if (NULL != tag && ucTrack > 0)
  {
    if (bReplace)
    {
      ID3_RemoveTracks(tag);
    }
    if (bReplace || NULL == tag->Find(ID3FID_TRACKNUM))
    {
      ID3_Frame *trackFrame = new ID3_Frame(ID3FID_TRACKNUM);
      if (trackFrame)
      {
        char *sTrack = NULL;
        if (0 == ucTotal)
        {
          sTrack = new char[4];
          sprintf(sTrack, "%lu", (luint) ucTrack);
        }
        else
        {
          sTrack = new char[8];
          sprintf(sTrack, "%lu/%lu", (luint) ucTrack, (luint) ucTotal);
        }
        
        trackFrame->Field(ID3FN_TEXT) = sTrack;
        tag->AttachFrame(trackFrame);

        delete [] sTrack;
      }
    }
  }
  
  return pFrame;
}
Exemple #22
0
int main( int argc, char *argv[])
{
  int iOpt;
  int argCounter = 0;
  int ii;
  char tmp[TMPSIZE];
  FILE * fp;
  
  struct frameInfo {
    enum ID3_FrameID id;
    char *data;
  } frameList[MAXNOFRAMES];
  
  int frameCounter = 0;
  
  while (true)
  {
    int option_index = 0;
    int iLongOpt = 0;
    int optFrameID = ID3FID_NOFRAME;
    static struct option long_options[] = 
    { 
    // help and info
      { "help",    no_argument,       &iLongOpt, 'h' },
      { "list-frames",
                   no_argument,       &iLongOpt, 'f' },
      { "list-genres",   
                  no_argument,        &iLongOpt, 'L' },
      { "version", no_argument,       &iLongOpt, 'v' },

    // list / remove / convert
      { "list",   no_argument,        &iLongOpt, 'l' },
      { "list-rfc822",   
                   no_argument,       &iLongOpt, 'R' },
      { "delete-v2",  no_argument,    &iLongOpt, 'd' },
      { "delete-v1",  
                   no_argument,       &iLongOpt, 's' },
      { "delete-all",  
                   no_argument,       &iLongOpt, 'D' },
      { "convert", no_argument,       &iLongOpt, 'C' },
      { "id3v1-only", no_argument,       &iLongOpt, '1' },
      { "id3v2-only", no_argument,       &iLongOpt, '2' },

    // infomation to tag
      { "artist",  required_argument, &iLongOpt, 'a' },
      { "album",   required_argument, &iLongOpt, 'A' },
      { "song",    required_argument, &iLongOpt, 't' },
      { "comment", required_argument, &iLongOpt, 'c' },
      { "genre",   required_argument, &iLongOpt, 'g' },
      { "year",    required_argument, &iLongOpt, 'y' },
      { "track",   required_argument, &iLongOpt, 'T' },
      { "AENC",    required_argument, &optFrameID, ID3FID_AUDIOCRYPTO },
      { "APIC",    required_argument, &optFrameID, ID3FID_PICTURE },
      { "COMM",    required_argument, &optFrameID, ID3FID_COMMENT },
    /* COMR too complex */
      { "ENCR",    required_argument, &optFrameID, ID3FID_CRYPTOREG },
      { "EQUA",    required_argument, &optFrameID, ID3FID_EQUALIZATION },
      { "ETCO",    required_argument, &optFrameID, ID3FID_EVENTTIMING },
      { "GEOB",    required_argument, &optFrameID, ID3FID_GENERALOBJECT },
      { "GRID",    required_argument, &optFrameID, ID3FID_GROUPINGREG },
      { "IPLS",    required_argument, &optFrameID, ID3FID_INVOLVEDPEOPLE },
      { "LINK",    required_argument, &optFrameID, ID3FID_LINKEDINFO },
      { "MCDI",    required_argument, &optFrameID, ID3FID_CDID },
      { "MLLT",    required_argument, &optFrameID, ID3FID_MPEGLOOKUP },
      { "OWNE",    required_argument, &optFrameID, ID3FID_OWNERSHIP },
      { "PRIV",    required_argument, &optFrameID, ID3FID_PRIVATE },
      { "PCNT",    required_argument, &optFrameID, ID3FID_PLAYCOUNTER },
      { "POPM",    required_argument, &optFrameID, ID3FID_POPULARIMETER },
      { "POSS",    required_argument, &optFrameID, ID3FID_POSITIONSYNC },
      { "RBUF",    required_argument, &optFrameID, ID3FID_BUFFERSIZE },
      { "RVAD",    required_argument, &optFrameID, ID3FID_VOLUMEADJ },
      { "RVRB",    required_argument, &optFrameID, ID3FID_REVERB },
      { "SYLT",    required_argument, &optFrameID, ID3FID_SYNCEDLYRICS },
      { "SYTC",    required_argument, &optFrameID, ID3FID_SYNCEDTEMPO },
      { "TALB",    required_argument, &optFrameID, ID3FID_ALBUM },
      { "TBPM",    required_argument, &optFrameID, ID3FID_BPM },
      { "TCOM",    required_argument, &optFrameID, ID3FID_COMPOSER },
      { "TCON",    required_argument, &optFrameID, ID3FID_CONTENTTYPE },
      { "TCOP",    required_argument, &optFrameID, ID3FID_COPYRIGHT },
      { "TDAT",    required_argument, &optFrameID, ID3FID_DATE },
      { "TDLY",    required_argument, &optFrameID, ID3FID_PLAYLISTDELAY },
      { "TENC",    required_argument, &optFrameID, ID3FID_ENCODEDBY },
      { "TEXT",    required_argument, &optFrameID, ID3FID_LYRICIST },
      { "TFLT",    required_argument, &optFrameID, ID3FID_FILETYPE },
      { "TIME",    required_argument, &optFrameID, ID3FID_TIME },
      { "TIT1",    required_argument, &optFrameID, ID3FID_CONTENTGROUP },
      { "TIT2",    required_argument, &optFrameID, ID3FID_TITLE },
      { "TIT3",    required_argument, &optFrameID, ID3FID_SUBTITLE },
      { "TKEY",    required_argument, &optFrameID, ID3FID_INITIALKEY },
      { "TLAN",    required_argument, &optFrameID, ID3FID_LANGUAGE },
      { "TLEN",    required_argument, &optFrameID, ID3FID_SONGLEN },
      { "TMED",    required_argument, &optFrameID, ID3FID_MEDIATYPE },
      { "TOAL",    required_argument, &optFrameID, ID3FID_ORIGALBUM },
      { "TOFN",    required_argument, &optFrameID, ID3FID_ORIGFILENAME },
      { "TOLY",    required_argument, &optFrameID, ID3FID_ORIGLYRICIST },
      { "TOPE",    required_argument, &optFrameID, ID3FID_ORIGARTIST },
      { "TORY",    required_argument, &optFrameID, ID3FID_ORIGYEAR },
      { "TOWN",    required_argument, &optFrameID, ID3FID_FILEOWNER },
      { "TPE1",    required_argument, &optFrameID, ID3FID_LEADARTIST },
      { "TPE2",    required_argument, &optFrameID, ID3FID_BAND },
      { "TPE3",    required_argument, &optFrameID, ID3FID_CONDUCTOR },
      { "TPE4",    required_argument, &optFrameID, ID3FID_MIXARTIST },
      { "TPOS",    required_argument, &optFrameID, ID3FID_PARTINSET },
      { "TPUB",    required_argument, &optFrameID, ID3FID_PUBLISHER },
      { "TRCK",    required_argument, &optFrameID, ID3FID_TRACKNUM },
      { "TRDA",    required_argument, &optFrameID, ID3FID_RECORDINGDATES },
      { "TRSN",    required_argument, &optFrameID, ID3FID_NETRADIOSTATION },
      { "TRSO",    required_argument, &optFrameID, ID3FID_NETRADIOOWNER },
      { "TSIZ",    required_argument, &optFrameID, ID3FID_SIZE },
      { "TSRC",    required_argument, &optFrameID, ID3FID_ISRC },
      { "TSSE",    required_argument, &optFrameID, ID3FID_ENCODERSETTINGS },
      { "TXXX",    required_argument, &optFrameID, ID3FID_USERTEXT },
      { "TYER",    required_argument, &optFrameID, ID3FID_YEAR },
      { "UFID",    required_argument, &optFrameID, ID3FID_UNIQUEFILEID },
      { "USER",    required_argument, &optFrameID, ID3FID_TERMSOFUSE },
      { "USLT",    required_argument, &optFrameID, ID3FID_UNSYNCEDLYRICS },
      { "WCOM",    required_argument, &optFrameID, ID3FID_WWWCOMMERCIALINFO },
      { "WCOP",    required_argument, &optFrameID, ID3FID_WWWCOPYRIGHT },
      { "WOAF",    required_argument, &optFrameID, ID3FID_WWWAUDIOFILE },
      { "WOAR",    required_argument, &optFrameID, ID3FID_WWWARTIST },
      { "WOAS",    required_argument, &optFrameID, ID3FID_WWWAUDIOSOURCE },
      { "WORS",    required_argument, &optFrameID, ID3FID_WWWRADIOPAGE },
      { "WPAY",    required_argument, &optFrameID, ID3FID_WWWPAYMENT },
      { "WPUB",    required_argument, &optFrameID, ID3FID_WWWPUBLISHER },
      { "WXXX",    required_argument, &optFrameID, ID3FID_WWWUSER },
      { 0, 0, 0, 0 }
    };
    iOpt = getopt_long (argc, argv, "12hfLvlRdsDCa:A:t:c:g:y:T:",
                        long_options, &option_index);

    if (iOpt == -1  && argCounter == 0)
    {
      PrintUsage(argv[0]);
      exit(0);
    } 
    else if (iOpt == -1)
      break;
    argCounter++;

    if (iOpt == 0) iOpt = iLongOpt;
//    if (iOpt == 0) iOpt = optFrameID;

#ifdef SORT_RUNTIME
    InitGenres();
#endif  // SORT_RUNTIME

    switch (iOpt)
    {
      case 0:
                frameList[frameCounter].id   = (enum ID3_FrameID)optFrameID;
                frameList[frameCounter].data = optarg;
                frameCounter++;
                break;
      case '?': 
      case 'h': PrintUsage(argv[0]);    exit (0);
      case 'f': PrintFrameHelp(argv[0]);exit (0);
      case 'L': PrintGenreList();       exit (0);
      case 'v': PrintVersion(argv[0]);  exit (0);

    // listing / remove / convert -- see list.cpp and convert.cpp
      case 'l': ListTag(argc, argv, optind, 0);    
                                        exit (0);
      case 'R': ListTag(argc, argv, optind, 1);    
                                        exit (0);
      case 'd': DeleteTag(argc, argv, optind, 2);    
                                        exit (0);
      case 's': DeleteTag(argc, argv, optind, 1);    
                                        exit (0);
      case 'D': DeleteTag(argc, argv, optind, 0);    
                                        exit (0);
      case 'C': ConvertTag(argc, argv, optind);    
                                        exit (0);
      case '1':
		UpdFlags = ID3TT_ID3V1;
		break;
      case '2':
		UpdFlags = ID3TT_ID3V2;
		break;
    // Tagging stuff 
      case 'a': 
                frameList[frameCounter].id   = ID3FID_LEADARTIST;
                frameList[frameCounter].data = optarg;
                frameCounter++;
                break;
      case 'A': 
                frameList[frameCounter].id   = ID3FID_ALBUM;
                frameList[frameCounter].data = optarg;
                frameCounter++;
                break;
      case 't': 
                frameList[frameCounter].id   = ID3FID_TITLE;
                frameList[frameCounter].data = optarg;
                frameCounter++;
                break;
      case 'c': 
                frameList[frameCounter].id   = ID3FID_COMMENT;
                frameList[frameCounter].data = optarg;
                frameCounter++;
                break;
      case 'g': 
          {
                int genre_id = 255;
                char *genre_str;
                sscanf(optarg, "%d", &genre_id);
                if (genre_id == 255)
                    genre_id = GetNumFromGenre(optarg);
                if (genre_id == 255)
                    genre_str = optarg;
                else {
                    sprintf(tmp, "(%d)", genre_id);
                    genre_str = tmp;
                }
                frameList[frameCounter].id   = ID3FID_CONTENTTYPE;
                frameList[frameCounter].data = genre_str;
                frameCounter++;
          }
                break;
      case 'y': 
                frameList[frameCounter].id   = ID3FID_YEAR;
                frameList[frameCounter].data = optarg;
                frameCounter++;
                break;
      case 'T': 
                frameList[frameCounter].id   = ID3FID_TRACKNUM;
                frameList[frameCounter].data = optarg;
                frameCounter++;
                break;
    // other tags
    
      default:
		std::cerr << "This isn't supposed to happen" << std::endl;
                exit(1);
    }
  }
  
  // loop thru the files
  if (optind == argc) 
  {
	  std::cerr << "No file to work on." << std::endl;
    exit(1);
  }
  
  for (size_t nIndex = optind; (unsigned int) nIndex < argc; nIndex++)
  {
    ID3_Tag myTag;
    struct stat filestat;
    
    // std::cout << "Tagging " << argv[nIndex] << ": ";

    // fix me - not checking to see if we can link to it
    
    
    if (stat(argv[nIndex], &filestat)) 
    {
      std::cerr << "Couldn't stat file '" << argv[nIndex] << "'\n";
      break;
    }
    
    /* cludgy to check if we have the proper perms */
    fp = fopen(argv[nIndex], "r+");
    if (fp == NULL) { /* file didn't open */
      fprintf(stderr, "fopen: %s: ", argv[nIndex]);
      perror("id3v2");
      continue;
    }
    fclose(fp);

    size_t ret;
    ret = myTag.Link(argv[nIndex] /*, ID3TT_ID3V2 */);

    // loop thru the frames we need to add/modify
    for (ii = 0; ii < frameCounter; ii++) 
    {
      ID3_Frame *myFrame;
      myFrame = new ID3_Frame;
      if (NULL == myFrame)
      {
         std::cout << "\nOut of memory\n" << std::endl;
         exit(1);
      }
      
      myFrame->SetID(frameList[ii].id);
      
      ID3_Frame *pFrame;
      pFrame = myTag.Find(frameList[ii].id);
                          
      switch (frameList[ii].id)
      {
      //  strings
        case ID3FID_ALBUM:
        case ID3FID_BPM:
        case ID3FID_COMPOSER:
        case ID3FID_CONTENTTYPE:
        case ID3FID_COPYRIGHT:
        case ID3FID_DATE:
        case ID3FID_PLAYLISTDELAY:
        case ID3FID_ENCODEDBY:
        case ID3FID_LYRICIST:
        case ID3FID_FILETYPE:
        case ID3FID_TIME:
        case ID3FID_CONTENTGROUP:
        case ID3FID_TITLE:
        case ID3FID_SUBTITLE:
        case ID3FID_INITIALKEY:
        case ID3FID_LANGUAGE:
        case ID3FID_SONGLEN:
        case ID3FID_MEDIATYPE:
        case ID3FID_ORIGALBUM:
        case ID3FID_ORIGFILENAME:
        case ID3FID_ORIGLYRICIST:
        case ID3FID_ORIGARTIST:
        case ID3FID_ORIGYEAR:
        case ID3FID_FILEOWNER:
        case ID3FID_LEADARTIST:
        case ID3FID_BAND:
        case ID3FID_CONDUCTOR:
        case ID3FID_MIXARTIST:
        case ID3FID_PARTINSET:
        case ID3FID_PUBLISHER:
        case ID3FID_RECORDINGDATES:
        case ID3FID_NETRADIOSTATION:
        case ID3FID_NETRADIOOWNER:
        case ID3FID_SIZE:
        case ID3FID_ISRC:
        case ID3FID_ENCODERSETTINGS:
        case ID3FID_YEAR:
        {
          if (pFrame != NULL) 
          {
            myTag.RemoveFrame(pFrame);
          }
          if (strlen(frameList[ii].data) > 0) {
            myFrame->Field(ID3FN_TEXT) = frameList[ii].data;
            myTag.AttachFrame(myFrame);
          }
          break;
        }
        case ID3FID_TRACKNUM:
        {
          // this ought to check if there is a total track number and
          // combine it with the given track number, but it doesn't.
          char *currentTrackNum = NULL;
          char *newTrackNum = NULL;

          if (pFrame != NULL) 
          {
            currentTrackNum = ID3_GetString(pFrame, ID3FN_TEXT);
            if (*currentTrackNum == '/') 
            {
              newTrackNum = (char *)malloc(strlen(currentTrackNum) 
                                   + strlen(frameList[ii].data)); 
              strcpy(newTrackNum, frameList[ii].data);
              strcat(newTrackNum, currentTrackNum);
            }
            else
            {
              myTag.RemoveFrame(pFrame);
            }
          }
          
          myFrame->Field(ID3FN_TEXT) = frameList[ii].data;
          myTag.AttachFrame(myFrame);

          free(newTrackNum);
          break;
        }
        case ID3FID_USERTEXT:
        {
          if (pFrame != NULL) 
          {
            myTag.RemoveFrame(pFrame);
          }

          // split the string at the ':' remember if no : then leave
          // descrip empty
          char *text;
          text = strchr(frameList[ii].data, ':');
          if (text == NULL) 
          {
            myFrame->Field(ID3FN_TEXT) = frameList[ii].data;
          } else {
            *text = '\0';
            text++;
            myFrame->Field(ID3FN_DESCRIPTION) = frameList[ii].data;
            myFrame->Field(ID3FN_TEXT) = text;
          }
          if (strlen(ID3_GetString(myFrame, ID3FN_TEXT)) > 0) {
            myTag.AttachFrame(myFrame);
          }
          
          break;
        }
        case ID3FID_COMMENT:
        case ID3FID_UNSYNCEDLYRICS:
        {
          // split the string at the ':' remember if no : then leave
          // descrip/lang empty
          char *text;
          text = strchr(frameList[ii].data, ':');
          if (text == NULL) 
          {
            myFrame->Field(ID3FN_TEXT) = frameList[ii].data;
          } else {
         	*text = '\0';
          	text++;
          	char *lang;
          	lang = strchr(text, ':');
          	if (lang == NULL) 
          	{
          	  myFrame->Field(ID3FN_DESCRIPTION) = frameList[ii].data;
          	  myFrame->Field(ID3FN_TEXT) = text;
          	} else {
          	  *lang = '\0';
          	  lang++;
          	  myFrame->Field(ID3FN_DESCRIPTION) = frameList[ii].data;
              myFrame->Field(ID3FN_TEXT) = text;
              myFrame->Field(ID3FN_LANGUAGE) = lang;
            }
          }
          /* debug
          std::cout << ID3_GetString(myFrame, ID3FN_DESCRIPTION) << std::endl
               << ID3_GetString(myFrame, ID3FN_TEXT) << std::endl
               << ID3_GetString(myFrame, ID3FN_LANGUAGE) << std::endl;
          */

          // now try and find a comment/lyrics with the same descript 
          // and lang as what we have
          ID3_Frame *pFirstFrame = NULL;
          do {
            // if pFrame is NULL, either there were no comments/lyrics 
            // to begin with, or we removed them all in the process          
            if (pFrame == NULL) break;
            
            if (pFirstFrame == NULL) 
            {
              pFirstFrame = pFrame;
            }

            char *tmp_desc = ID3_GetString(pFrame, ID3FN_DESCRIPTION);
            char *tmp_my_desc = ID3_GetString(myFrame, ID3FN_DESCRIPTION);
            char *tmp_lang = ID3_GetString(pFrame, ID3FN_LANGUAGE);
            char *tmp_my_lang = ID3_GetString(myFrame, ID3FN_LANGUAGE);
            if ((strcmp(tmp_desc, tmp_my_desc) == 0) &&
                (strcmp(tmp_lang, tmp_my_lang) == 0)) 
            {
              myTag.RemoveFrame(pFrame);
              if (pFrame == pFirstFrame) 
              {
                pFirstFrame = NULL;
              }
            }
            delete [] tmp_desc;
            delete [] tmp_my_desc;
            delete [] tmp_lang;
            delete [] tmp_my_lang;
            
            // get the next frame until it wraps around
          } while ((pFrame = myTag.Find(frameList[ii].id)) != pFirstFrame);
          
          if (strlen(ID3_GetString(myFrame, ID3FN_TEXT)) > 0) {
            myTag.AttachFrame(myFrame);
          }
          
          break;
        }
        case ID3FID_WWWAUDIOFILE:
        case ID3FID_WWWARTIST:
        case ID3FID_WWWAUDIOSOURCE:
        case ID3FID_WWWCOMMERCIALINFO:
        case ID3FID_WWWCOPYRIGHT:
        case ID3FID_WWWPUBLISHER:
        case ID3FID_WWWPAYMENT:
        case ID3FID_WWWRADIOPAGE:
        {
          if (pFrame != NULL) 
          {
            char *sURL = ID3_GetString(pFrame, ID3FN_URL);
            if (strcmp(frameList[ii].data, sURL) == 0)
              myTag.RemoveFrame(pFrame);  
          }

          if (strlen(frameList[ii].data) > 0) {
            myFrame->Field(ID3FN_URL) = frameList[ii].data;
            myTag.AttachFrame(myFrame);
          }
                  
          break;
                                
        }
        case ID3FID_WWWUSER:
        {
          char 
            *sURL = ID3_GetString(myFrame, ID3FN_URL),
            *sDesc = ID3_GetString(myFrame, ID3FN_DESCRIPTION);
          std::cout << "(" << sDesc << "): " << sURL << std::endl;
          delete [] sURL;
          delete [] sDesc;
          break;
        }
        case ID3FID_INVOLVEDPEOPLE:
        {
          // This isn't the right way to do it---will only get first person
          size_t nItems = myFrame->Field(ID3FN_TEXT).GetNumTextItems();
          for (size_t nIndex = 1; nIndex <= nItems; nIndex++)
          {
            char *sPeople = ID3_GetString(myFrame, ID3FN_TEXT, nIndex);
            std::cout << sPeople;
            delete [] sPeople;
            if (nIndex < nItems)
            { 
              std::cout << ", ";
            }
          }
          std::cout << std::endl;
          break;
        }
        case ID3FID_PICTURE:
        {
          myFrame->Field(ID3FN_DATA).FromFile(frameList[ii].data);
          myTag.AttachFrame(myFrame);
          break;
        }
        case ID3FID_GENERALOBJECT:
        {
          char 
            *sMimeType = ID3_GetString(myFrame, ID3FN_TEXT), 
            *sDesc = ID3_GetString(myFrame, ID3FN_DESCRIPTION), 
            *sFileName = ID3_GetString(myFrame, ID3FN_FILENAME);
          size_t 
          nDataSize = myFrame->Field(ID3FN_DATA).Size();
          std::cout << "(" << sDesc << ")[" 
              << sFileName << "]: " << sMimeType << ", " << nDataSize
              << " bytes" << std::endl;
          delete [] sMimeType;
          delete [] sDesc;
          delete [] sFileName;
          break;
        }
        case ID3FID_UNIQUEFILEID:
        {
          if (pFrame != NULL) 
          {       
            char *sOwner = ID3_GetString(pFrame, ID3FN_TEXT);
            size_t nDataSize = pFrame->Field(ID3FN_DATA).Size();
            std::cout << sOwner << ", " << nDataSize
                 << " bytes" << std::endl;
            delete [] sOwner;
          }
          break;
        }
        case ID3FID_PLAYCOUNTER:
        {
          if (pFrame != NULL) 
          {
            size_t nCounter = pFrame->Field(ID3FN_COUNTER).Get();
            std::cout << nCounter << std::endl;
          }
          break;
        }
        case ID3FID_POPULARIMETER:
        {
          if (pFrame != NULL)
          {
            char *sEmail = ID3_GetString(pFrame, ID3FN_EMAIL);
            size_t
              nCounter = pFrame->Field(ID3FN_COUNTER).Get(),
              nRating = pFrame->Field(ID3FN_RATING).Get();
            std::cout << sEmail << ", counter=" 
                 << nCounter << " rating=" << nRating;
            delete [] sEmail;
          }
          break;
        }
        case ID3FID_CRYPTOREG:
        case ID3FID_GROUPINGREG:
        {
          char *sOwner = ID3_GetString(myFrame, ID3FN_OWNER);
          size_t 
            nSymbol = myFrame->Field(ID3FN_ID).Get(),
            nDataSize = myFrame->Field(ID3FN_DATA).Size();
          std::cout << "(" << nSymbol << "): " << sOwner
               << ", " << nDataSize << " bytes";
          break;
        }
        case ID3FID_AUDIOCRYPTO:
        case ID3FID_EQUALIZATION:
        case ID3FID_EVENTTIMING:
        case ID3FID_CDID:
        case ID3FID_MPEGLOOKUP:
        case ID3FID_OWNERSHIP:
        case ID3FID_PRIVATE:
        case ID3FID_POSITIONSYNC:
        case ID3FID_BUFFERSIZE:
        case ID3FID_VOLUMEADJ:
        case ID3FID_REVERB:
        case ID3FID_SYNCEDLYRICS:
        case ID3FID_SYNCEDTEMPO:
        case ID3FID_METACRYPTO:
        {
          std::cout << " (unimplemented)" << std::endl;
          break;
        }
        default:
        {
          std::cout << " frame" << std::endl;
          break;
        }
      }
    }  // steping thru frames
   
    luint nTags = myTag.Update(UpdFlags);

    /* update file with old mode */
    if (chmod(argv[nIndex], filestat.st_mode)) 
    {
	    std::cerr << "Couldn't reset permissions on '" << argv[nIndex] << "'\n";
    }    
  }

  return 0;
}