Logo Search packages:      
Sourcecode: madman version File versions  Download package

int apetag_save ( char *  filename,
apetag mem_cnt,
int  flag 
)

save apetag to file

Parameters:
filename file name
mem_cnt object apetag
flag flags for read/save
Returns:
0 - OK else check atl_return
Warning:
for ape tag v 1 you must add frames in iso-1 for v 2 this must be in utf-8
Todo:
PL: v9 sprawdzac flagi w footer i na tej podstawie zmieniac skipBytes bez domniemywania ze v2 ma zawsze oba

Definition at line 907 of file apetaglib.c.

References ATL_FOPEN, ATL_FWRITE, ATL_MALOC, ATL_NOINIT, _ape_mem_cnt::countTag, _apetag_footer::flags, _apetag_footer::id, _apetag_footer::length, tag::sizeName, tag::sizeValue, _ape_mem_cnt::tag, _apetag_footer::tagCount, and _apetag_footer::version.

{
    FILE *fp;
    struct _id3v1Tag id3v1_tag;
    int id3v1;
    int apeTag, saveApe2;
    int tagCount = 0;
    struct _apetag_footer ape_footer;
    long skipBytes;
    unsigned char *buff, *p;
    struct tag **mTag;
    size_t tagSSize = 32;
    int n;
    char temp[4];
    
    if (mem_cnt==NULL) {
        PRINT_ERR("ERROR->apetaglib>apetag_save::apetag_init()\n");
        return ATL_NOINIT;
    }

    fp = fopen (filename, "rb+");
    if (fp == NULL) {
        PRINT_ERR ( "ERROR->apetaglib->apetag_save::fopen (r+)\n");
        return ATL_FOPEN;
    }
    
    skipBytes = 0;
    id3v1 = is_id3v1 (fp);
    apeTag = is_ape (fp);
    saveApe2 = !(flag & APE_TAG_V1); // (flag & APE_TAG_V2) ? 1 : (flag & APE_TAG_V1);
    
    if (id3v1) {
        fseek (fp, -128, SEEK_END);
        fread (&id3v1_tag, 1, sizeof (struct _id3v1Tag), fp);
        skipBytes += id3v1;
    }
    skipBytes += apeTag;

    if (!(flag & SAVE_NEW_APE_TAG)) {
        apetag_read_fp (mem_cnt, fp, filename, flag);
    }
    
    mTag = (mem_cnt->tag);
    qsort( mTag , mem_cnt->countTag , sizeof(struct tag *),
        (int (*)(const void *,const void *))libapetag_qsort);
    
    for (n = 0; (mem_cnt->countTag) > n; n++) {
        if (mTag[n]->sizeValue != 0) {
            tagSSize += ((long) mTag[n]->sizeName + (long) mTag[n]->sizeValue);
            tagSSize += 4 + 4 + 1 + (saveApe2 ? 0 : 1);    // flag & sizeValue & \0
        }
    }
    if (!!(flag & SAVE_CREATE_ID3V1_TAG )) {
        make_id3v1_tag(mem_cnt, &id3v1_tag);
        tagSSize += 128;
    }
    //PRINT_D4 (">apetaglib>SAVE>>: size %li %i %i %i\n", tagSSize,
    //    mem_cnt->countTag, flag, saveApe2);
    buff = (unsigned char *) malloc (tagSSize + (saveApe2 ? 32 : 0));
    p = buff;
    
    if (buff == NULL) {
        PRINT_ERR ("ERROR->libapetag->apetag_save::malloc");
        return ATL_MALOC;
    }
    memset (ape_footer.id, 0, sizeof (ape_footer));
    memcpy (ape_footer.id, "APETAGEX", sizeof (ape_footer.id));
    long2ape (ape_footer.flags, 0l);
    if (!!(flag & SAVE_CREATE_ID3V1_TAG ))
        long2ape (ape_footer.length, tagSSize-128);
    else
        long2ape (ape_footer.length, tagSSize);
    long2ape (ape_footer.tagCount, mem_cnt->countTag);
    long2ape (ape_footer.version, (saveApe2 ? 2000 : 1000));
    if (saveApe2) {
        long2ape (ape_footer.flags, HEADER_THIS_IS + HEADER_IS + FOOTER_IS);
        memcpy (p, ape_footer.id, sizeof (ape_footer));
        p += sizeof (ape_footer);
    }
    
    mTag = (mem_cnt->tag);
    for (n = 0; (mem_cnt->countTag) > n; n++) {
        if (saveApe2) {
            long2ape (temp, mTag[n]->sizeValue);
        } else {
            /* TODO:convert UTF8 to ASCII mTag[n]->value */
            long2ape (temp, (mTag[n]->sizeValue) + 1);
        }
        
        if (mTag[n]->sizeValue != 0) {
            memcpy (p, temp, 4);
            p += 4;
            long2ape (temp, (saveApe2!=0) ? mTag[n]->flags : 0l );
            memcpy (p, temp, 4);
            p += 4;
            
            memcpy (p, mTag[n]->name, mTag[n]->sizeName);
            p += mTag[n]->sizeName;
            memcpy (p, "\0", 1);
            p++;
            memcpy (p, mTag[n]->value, mTag[n]->sizeValue);
            p += mTag[n]->sizeValue;
            
            if (!saveApe2) {
                memcpy (p, "\0", 1);
                p++;
            }
            tagCount++;
        }
    } /* for */
    
    if (saveApe2)
        long2ape (ape_footer.flags, FOOTER_THIS_IS + FOOTER_IS + HEADER_IS);
        
    memcpy (p, ape_footer.id, sizeof (ape_footer));
    p += sizeof (ape_footer);
    
    if (!!(flag & SAVE_CREATE_ID3V1_TAG )) {
         memcpy (p, &id3v1_tag , sizeof (struct _id3v1Tag));
    }
    
    /* write tag to file and truncate */
    if (!(flag & SAVE_FAKE_SAVE)) {
        size_t fileSize;
        size_t newFileSize;
        size_t writedBytes;
        
        fseek (fp, 0, SEEK_END);
        fileSize = ftell (fp);
        fseek (fp, fileSize - skipBytes, SEEK_SET);
        if (tagCount != 0) {
            newFileSize = (fileSize - skipBytes + tagSSize + (saveApe2 ? 32 : 0));
            writedBytes = fwrite (buff, 1, tagSSize + (saveApe2 ? 32 : 0), fp);
            if (writedBytes != tagSSize + (saveApe2 ? 32 : 0)) {
                PRINT_ERR ("FATAL_ERROR->libapetag->apetag_save::fwrite [data lost]");
                fclose (fp);
                free (buff);
                return ATL_FWRITE;
            }
            fseek (fp, newFileSize, SEEK_SET);
            PRINT_D4 (">apetaglib>SAVE>> write:%i == tag:%i file: %i->%i\n",
                writedBytes, tagSSize + (saveApe2 ? 32 : 0), fileSize, newFileSize);
        } else {
            newFileSize = (fileSize - skipBytes);
        }
        fflush (fp);
        fclose (fp);
        /* ftruncate don't work */ 
        truncate (filename, newFileSize);
    } else { /* !!SAVE_FAKE_SAVE */
        libapetag_print_mem_cnt (mem_cnt);
    }
    free (buff);

    return 0;
}


Generated by  Doxygen 1.6.0   Back to index