Пример #1
0
/*
 * As the ID3Tag_Link function of id3lib-3.8.0pre2 returns the ID3v1 tags
 * when a file has both ID3v1 and ID3v2 tags, we first try to explicitely
 * get the ID3v2 tags with ID3Tag_LinkWithFlags and, if we cannot get them,
 * fall back to the ID3v1 tags.
 * (Written by Holger Schemel).
 */
static size_t local__ID3Tag_Link_wrapper(ID3Tag *id3tag, const char *filename)
{
	size_t offset;

#   if ( (ID3LIB_MAJOR >= 3) && (ID3LIB_MINOR >= 8)  )
		/* First, try to get the ID3v2 tags */
		offset = ID3Tag_LinkWithFlags(id3tag, filename, ID3TT_ID3V2);
		if (offset == 0) {
			/* No ID3v2 tags available => try to get the ID3v1 tags */
			offset = ID3Tag_LinkWithFlags(id3tag, filename, ID3TT_ID3V1);
		}
#   else
		/* Function 'ID3Tag_LinkWithFlags' is not defined up to id3lib-.3.7.13 */
		offset = ID3Tag_Link(id3tag, filename);
#   endif
	return offset;
}
Пример #2
0
// Reads ID3v2.x tag
// idea of this come from "tag" by Case <*****@*****.**>
int readtag_id3v2 ( apetag *mem_cnt, char* fileName )
{
    ID3Tag*             tag;
    ID3Frame*           frame;
    ID3TagIterator*     iter;
    char*               item = NULL;
    int                 itemSize;
    char*               value = NULL;
    int                 valueSize;
    unsigned long       flags;

    // first - check of id3tag v2 and init 
    if ( (tag = ID3Tag_New ()) == NULL )
    return 1;
    // on some casses its weerrryyy slooowwwwlyyy 65k file take 2-5 sec 
    ID3Tag_LinkWithFlags ( tag, fileName, ID3TT_ID3V2 );
    
    if ( tag == NULL ) {
    ID3Tag_Delete (tag);
    return 0;
    }

    if ( !ID3Tag_HasTagType ( tag, ID3TT_ID3V2 ) ) {
    ID3Tag_Delete (tag);
    return 0;
    }

    if ( (iter = ID3Tag_CreateIterator (tag)) == NULL ) {
    ID3Tag_Delete (tag);
    return 0;
    }

    while ( (frame = ID3TagIterator_GetNext (iter)) != NULL ) {

    libapetag_convertID3v2toAPE ( frame, &item, &itemSize, &value, &valueSize, &flags);

    if ( !item || !value || item[0] == '\0' || value[0] == '\0' )
        continue;
    
    if ( !value || value[0] != '\0' ) {
        PRINT_D4(">id3v2_read>[i%i]%s: [v%i]'%s'\n",itemSize,item,valueSize,value);
        if ( apefrm_getstr (mem_cnt, item) == NULL ) /* noreplece !!! */
            apefrm_add_bin (mem_cnt, flags, itemSize, item, valueSize ,value);
    }
    free ( value );
    free ( item );
    }

    ID3TagIterator_Delete (iter);
    ID3Tag_Delete (tag);

    return 0;
}
Пример #3
0
/*
 * Read infos into header of first frame
 */
gboolean
Mpeg_Header_Read_File_Info (gchar *filename, ET_File_Info *ETFileInfo)
{
    /*
     * With id3lib, the header frame couldn't be read if the file contains an ID3v2 tag with an APIC frame
     */
    ID3Tag *id3_tag = NULL;    /* Tag defined by the id3lib */
    const Mp3_Headerinfo* headerInfo = NULL;

    g_return_val_if_fail (filename != NULL || ETFileInfo != NULL, FALSE);

    /* Get size of file */
    ETFileInfo->size = Get_File_Size (filename);

    /* Get data from tag */
    if ( (id3_tag = ID3Tag_New()) == NULL )
        return FALSE;

    /* Link the file to the tag (uses ID3TT_ID3V2 to get header if APIC is present in Tag) */
    ID3Tag_LinkWithFlags(id3_tag,filename,ID3TT_ID3V2);

    if ( (headerInfo = ID3Tag_GetMp3HeaderInfo(id3_tag)) )
    {
        switch (headerInfo->version)
        {
            case MPEGVERSION_1:
                ETFileInfo->version = 1;
                ETFileInfo->mpeg25 = FALSE;
                break;
            case MPEGVERSION_2:
                ETFileInfo->version = 2;
                ETFileInfo->mpeg25 = FALSE;
                break;
            case MPEGVERSION_2_5:
                ETFileInfo->mpeg25 = TRUE;
                ETFileInfo->mpeg25 = FALSE;
                break;
            default:
                break;
        }

        switch (headerInfo->layer)
        {
            case MPEGLAYER_I:
                ETFileInfo->layer = 1;
                break;
            case MPEGLAYER_II:
                ETFileInfo->layer = 2;
                break;
            case MPEGLAYER_III:
                ETFileInfo->layer = 3;
                break;
            default:
                break;
        }

        // Samplerate
        ETFileInfo->samplerate = headerInfo->frequency;

        // Mode -> Seems to be detected but incorrect?!
        switch (headerInfo->modeext)
        {
            case MP3CHANNELMODE_STEREO:
                ETFileInfo->mode = 0;
                break;
            case MP3CHANNELMODE_JOINT_STEREO:
                ETFileInfo->mode = 1;
                break;
            case MP3CHANNELMODE_DUAL_CHANNEL:
                ETFileInfo->mode = 2;
                break;
            case MP3CHANNELMODE_SINGLE_CHANNEL:
                ETFileInfo->mode = 3;
                break;
            default:
                break;
        }

        // Bitrate
        if (headerInfo->vbr_bitrate <= 0)
        {
            ETFileInfo->variable_bitrate = FALSE;
            ETFileInfo->bitrate = headerInfo->bitrate/1000;
        }else
        {
            ETFileInfo->variable_bitrate = TRUE;
            ETFileInfo->bitrate = headerInfo->vbr_bitrate/1000;
        }

        // Duration
        ETFileInfo->duration = headerInfo->time;
    }

    /* Free allocated data */
    ID3Tag_Delete(id3_tag);

    return TRUE;
}
Пример #4
0
/*
 * Read infos into header of first frame
 */
gboolean Mpeg_Header_Read_File_Info (gchar *filename, ET_File_Info *ETFileInfo)
{
#if (!USE_ID3LIB_4_HEADER)
    FILE *file;
    gulong filesize;


    if (!filename || !ETFileInfo)
        return FALSE;

    /* Get size of file */
    filesize         = Get_File_Size(filename);
    ETFileInfo->size = filesize;


    /*
     * This part was taken from XMMS
     */
    if ((file = fopen(filename, "rb")) != NULL)
    {
        guint32 head;
        unsigned char tmp[4];
        struct frame frm;
        gboolean id3_found = FALSE;

        if (fread(tmp, 1, 4, file) != 4)
        {
            fclose(file);
            return FALSE;
        }

        // Skip data of the ID3v2.x tag (It may contain data similar to mpeg frame 
        // as, for example, in the id3 APIC frame) (patch from Artur Polaczynski)
        if (tmp[0] == 'I' && tmp[1] == 'D' && tmp[2] == '3' && tmp[3] < 0xFF)
        {
            // ID3v2 tag skipeer $49 44 33 yy yy xx zz zz zz zz [zz size]
            long id3v2size;
            fseek(file, 2, SEEK_CUR); // Size is 6-9 position
            if (fread(tmp, 1, 4, file) != 4) // Read bytes of tag size
            {
                fclose(file);
                return FALSE;
            }
            id3v2size = 10 + ( (long)(tmp[3]) | ((long)(tmp[2]) << 7) | ((long)(tmp[1]) << 14) | ((long)(tmp[0]) << 21) );
            fseek(file, id3v2size, SEEK_SET);
            if (fread(tmp, 1, 4, file) != 4) // Read mpeg header
            {
                fclose(file);
                return FALSE;
            }
        }

        head = ((guint32) tmp[0] << 24) | ((guint32) tmp[1] << 16) | ((guint32) tmp[2] << 8) | (guint32) tmp[3];
        while (!mpg123_head_check(head))
        {
            head <<= 8;
            if (fread(tmp, 1, 1, file) != 1)
            {
                fclose(file);
                return FALSE;
            }
            head |= tmp[0];
        }
        if (mpg123_decode_header(&frm, head))
        {
            guchar *buf;
            gdouble tpf;
            gint pos;
            XHEADDATA xing_header;
            guint32 num_frames;

            buf = g_malloc(frm.framesize + 4);
            fseek(file, -4, SEEK_CUR);
            fread(buf, 1, frm.framesize + 4, file);
            xing_header.toc = NULL;
            tpf = mpg123_compute_tpf(&frm);
            // MPEG and Layer version
            ETFileInfo->mpeg25 = frm.mpeg25;
            if (!ETFileInfo->mpeg25)
                ETFileInfo->version = frm.lsf+1;
            ETFileInfo->layer = frm.lay;
            //if (ETFileInfo->mpeg25) g_print("mpeg_level: MPEG 2.5, layer %d\n",ETFileInfo->layer);
            //else                    g_print("mpeg_level: MPEG %d, layer %d\n",ETFileInfo->version,ETFileInfo->layer);

            pos = ftell(file);
            fseek(file, 0, SEEK_END);
            // Variable bitrate? + bitrate
            if ( (ETFileInfo->variable_bitrate=mpg123_get_xing_header(&xing_header,buf)) )
            {
                num_frames = xing_header.frames;
                ETFileInfo->bitrate = (gint) ((xing_header.bytes * 8) / (tpf * xing_header.frames * 1000));
                //g_print("Bitrate: Variable,\navg. bitrate: %d kb/s\n",ETFileInfo->bitrate);
            } else
            {
                num_frames = ((ftell(file) - pos - (id3_found ? 128 : 0)) / mpg123_compute_bpf(&frm)) + 1;
                ETFileInfo->bitrate = tabsel_123[frm.lsf][frm.lay - 1][frm.bitrate_index];
                //g_print("Bitrate: %d kb/s\n",ETFileInfo->bitrate);
            }
            // Samplerate
            ETFileInfo->samplerate = mpg123_freqs[frm.sampling_frequency];
            // Mode
            ETFileInfo->mode = frm.mode;
            //g_print("Samplerate: %ld Hz\n", mpg123_freqs[frm.sampling_frequency]);
            //g_print("%s\nError protection: %s\nCopyright: %s\nOriginal: %s\nEmphasis: %s\n", channel_mode_name(frm.mode), bool_label[frm.error_protection], bool_label[frm.copyright], bool_label[frm.original], emphasis[frm.emphasis]);
            //g_print("%d frames\nFilesize: %lu B\n", num_frames, ftell(file));
            g_free(buf);
        }

        // Duration
        ETFileInfo->duration = mpg123_get_song_time(file)/1000;
        //g_print("time %s\n",Convert_Duration(ETFileInfo->duration));

        fclose(file);
    }else
    {
        gchar *filename_utf8 = filename_to_display(filename);
        Log_Print(LOG_ERROR,_("ERROR while opening file: '%s' (%s)."),filename_utf8,g_strerror(errno));
        g_free(filename_utf8);
        return FALSE;
    }

#else
    // Needs to uncomment some #include at the beginning

    /*
     * With id3lib, the header frame couldn't be read if the file contains an ID3v2 tag with an APIC frame
     */
    gulong filesize;
    ID3Tag *id3_tag = NULL;    /* Tag defined by the id3lib */
    const Mp3_Headerinfo* headerInfo = NULL;


    if (!filename || !ETFileInfo)
        return FALSE;

    /* Get size of file */
    filesize         = Get_File_Size(filename);
    ETFileInfo->size = filesize;

    /* Get data from tag */
    if ( (id3_tag = ID3Tag_New()) == NULL )
        return FALSE;

    /* Link the file to the tag (uses ID3TT_ID3V2 to get header if APIC is present in Tag) */
    ID3Tag_LinkWithFlags(id3_tag,filename,ID3TT_ID3V2);

    /*ID3_STRUCT(Mp3_Headerinfo)
    {
      Mpeg_Layers layer;
      Mpeg_Version version;
      MP3_BitRates bitrate;
      Mp3_ChannelMode channelmode;
      Mp3_ModeExt modeext;
      Mp3_Emphasis emphasis;
      Mp3_Crc crc;
      uint32 vbr_bitrate;           // avg bitrate from xing header
      uint32 frequency;             // samplerate
      uint32 framesize;
      uint32 frames;                // nr of frames
      uint32 time;                  // nr of seconds in song
      bool privatebit;
      bool copyrighted;
      bool original;
    };*/

    if ( (headerInfo = ID3Tag_GetMp3HeaderInfo(id3_tag)) )
    {
        switch (headerInfo->version)
        {
            case MPEGVERSION_1:
                ETFileInfo->version = 1;
                ETFileInfo->mpeg25 = FALSE;
                break;
            case MPEGVERSION_2:
                ETFileInfo->version = 2;
                ETFileInfo->mpeg25 = FALSE;
                break;
            case MPEGVERSION_2_5:
                ETFileInfo->mpeg25 = TRUE;
                ETFileInfo->mpeg25 = FALSE;
                break;
            default:
                break;
        }

        switch (headerInfo->layer)
        {
            case MPEGLAYER_I:
                ETFileInfo->layer = 1;
                break;
            case MPEGLAYER_II:
                ETFileInfo->layer = 2;
                break;
            case MPEGLAYER_III:
                ETFileInfo->layer = 3;
                break;
            default:
                break;
        }

        // Samplerate
        ETFileInfo->samplerate = headerInfo->frequency;

        // Mode -> Seems to be detected but incorrect?!
        switch (headerInfo->modeext)
        {
            case MP3CHANNELMODE_STEREO:
                ETFileInfo->mode = 0;
                break;
            case MP3CHANNELMODE_JOINT_STEREO:
                ETFileInfo->mode = 1;
                break;
            case MP3CHANNELMODE_DUAL_CHANNEL:
                ETFileInfo->mode = 2;
                break;
            case MP3CHANNELMODE_SINGLE_CHANNEL:
                ETFileInfo->mode = 3;
                break;
            default:
                break;
        }

        // Bitrate
        if (headerInfo->vbr_bitrate <= 0)
        {
            ETFileInfo->variable_bitrate = FALSE;
            ETFileInfo->bitrate = headerInfo->bitrate/1000;
        }else
        {
            ETFileInfo->variable_bitrate = TRUE;
            ETFileInfo->bitrate = headerInfo->vbr_bitrate/1000;
        }

        // Duration
        ETFileInfo->duration = headerInfo->time;
    }

    /* Free allocated data */
    ID3Tag_Delete(id3_tag);

#endif

    return TRUE;
}
Пример #5
0
/* read tags from a file */
FileInfo *filetags_read_file(gchar *filename) 
{
  /* id3lib has some really weird C API. we have to manipulate this
     carefully. also there seems to be code for unicode and stuff liek
     that (esp if you look at libmad). all that is not dealt with
     here.

     the strategy is this: for every file we try to get both v1 and
     v2. we prefer v2 frames over v1 frames (i dont think they are
     called frames in v1). if a v2 frame doesnt exist then we try to
     get it from v1.
  */

  FileInfo *filetag = NULL;
  size_t v1pos = 0, v2pos = 0;
  ID3Tag *id3v1tag = NULL, *id3v2tag = NULL;
  int len = 0;
  char buffer[MAX_STRING_LEN];
  FILE *file = NULL;
  
  /* ok, make sure the file exists first of all. */
  if (!filename) {
    return NULL;
  }

  file = fopen(filename, "r");
  if (file == NULL) {
    return NULL;
  }
  fclose(file);

  /* ok file exists. now get a new tag and link it with filename. */
  filetag = (FileInfo*)g_malloc(sizeof(FileInfo));
  bzero(filetag, sizeof(FileInfo));

  id3v1tag = ID3Tag_New();
  id3v2tag = ID3Tag_New();
  
  v1pos = ID3Tag_LinkWithFlags(id3v1tag, filename, ID3TT_ID3V2);
  v2pos = ID3Tag_LinkWithFlags(id3v2tag, filename, ID3TT_ID3V1);
  
  /* I dont know if we really care about position though. id3lib
   * sources says something about _prepended_bytes. Did I mention I
   * hate C++? id3lib just made it worse. I wonder how libmad's
   * libid3tag would be. */

  /* lets get the following frames: Title, Artist, Album and Time
   * mainly and optionally get things like Genre, Year.
   */

  /* title */
  bzero(buffer, MAX_STRING_LEN*sizeof(char));
  
  len = get_text_field_from_tag(id3v2tag, ID3FID_TITLE, ID3FN_TEXT, buffer, 0);
  if (len == 0) {
    len = get_text_field_from_tag(id3v1tag, ID3FID_TITLE, ID3FN_TEXT, buffer, 0);
  }
  if (len != 0) {
    filetag->title = g_strdup(buffer);
  }

  /* artist: can be one of ID3FID_ORIGARTIST (TOPE), ID3FID_LEADARTIST
     (TPE1), ID3FID_BAND (TPE2), ID3FID_CONDUCTOR (TPE3),
     ID3FID_MIXARTIST (TPE4). We will get it in the order TPE1, TPE2,
     TOPE, TPE3, TPE4. */
  bzero(buffer, MAX_STRING_LEN*sizeof(char));
  len = get_text_field_from_tag(id3v2tag, ID3FID_LEADARTIST,
				ID3FN_TEXT, buffer, 0);
  if (len == 0) {
    len = get_text_field_from_tag(id3v1tag, ID3FID_LEADARTIST,
				  ID3FN_TEXT, buffer, 0);
  }
  if (len != 0) {
    filetag->artist = g_strdup(buffer);
  }
    
  /* album */
  bzero(buffer, MAX_STRING_LEN*sizeof(char));
  len = get_text_field_from_tag(id3v2tag, ID3FID_ALBUM, ID3FN_TEXT, buffer, 0);
  if (len == 0) {
    len = get_text_field_from_tag(id3v1tag, ID3FID_ALBUM, ID3FN_TEXT, buffer, 0);
  }
  if (len != 0) {
    filetag->album = g_strdup(buffer);
  }

  ID3Tag_Delete(id3v1tag);
  ID3Tag_Delete(id3v2tag);
  
  return filetag;
}