~ft/aacdec

b5330cb64af703185462b3a28eb0d1ee16f36789 — menno 17 years ago b9ec5d0
New winamp plugin:
Now uses mp4ff library instead of mp4v2 from mpeg4ip.
M common/mp4ff/mp4ff.h => common/mp4ff/mp4ff.h +3 -1
@@ 22,7 22,7 @@
** Commercial non-GPL licensing of this software is possible.
** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
**
** $Id: mp4ff.h,v 1.20 2004/03/27 11:14:49 menno Exp $
** $Id: mp4ff.h,v 1.21 2004/09/03 19:38:58 menno Exp $
**/

#ifndef MP4FF_H


@@ 98,6 98,8 @@ int mp4ff_meta_get_comment(const mp4ff_t *f, char **value);
int mp4ff_meta_get_genre(const mp4ff_t *f, char **value);
int mp4ff_meta_get_track(const mp4ff_t *f, char **value);
int mp4ff_meta_get_disc(const mp4ff_t *f, char **value);
int mp4ff_meta_get_totaltracks(const mp4ff_t *f, char **value);
int mp4ff_meta_get_totaldiscs(const mp4ff_t *f, char **value);
int mp4ff_meta_get_compilation(const mp4ff_t *f, char **value);
int mp4ff_meta_get_tempo(const mp4ff_t *f, char **value);
int32_t mp4ff_meta_get_coverart(const mp4ff_t *f, char **value);

M common/mp4ff/mp4meta.c => common/mp4ff/mp4meta.c +11 -1
@@ 22,7 22,7 @@
** Commercial non-GPL licensing of this software is possible.
** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
**
** $Id: mp4meta.c,v 1.14 2004/03/27 11:14:49 menno Exp $
** $Id: mp4meta.c,v 1.15 2004/09/03 19:38:58 menno Exp $
**/

#ifdef USE_TAGGING


@@ 393,11 393,21 @@ int32_t mp4ff_meta_get_track(const mp4ff_t *f, char **value)
    return mp4ff_meta_find_by_name(f, "track", value);
}

int32_t mp4ff_meta_get_totaltracks(const mp4ff_t *f, char **value)
{
    return mp4ff_meta_find_by_name(f, "totaltracks", value);
}

int32_t mp4ff_meta_get_disc(const mp4ff_t *f, char **value)
{
    return mp4ff_meta_find_by_name(f, "disc", value);
}

int32_t mp4ff_meta_get_totaldiscs(const mp4ff_t *f, char **value)
{
    return mp4ff_meta_find_by_name(f, "totaldiscs", value);
}

int32_t mp4ff_meta_get_compilation(const mp4ff_t *f, char **value)
{
    return mp4ff_meta_find_by_name(f, "compilation", value);

M plugins/in_mp4/in_mp4.c => plugins/in_mp4/in_mp4.c +358 -396
@@ 22,7 22,7 @@
** Commercial non-GPL licensing of this software is possible.
** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
**
** $Id: in_mp4.c,v 1.51 2004/03/04 19:06:01 menno Exp $
** $Id: in_mp4.c,v 1.52 2004/09/03 19:38:32 menno Exp $
**/

//#define DEBUG_OUTPUT


@@ 32,16 32,18 @@
#include <commctrl.h>
#include <commdlg.h>
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include <math.h>
#include <neaacdec.h>
#include <mp4.h>
#define USE_TAGGING
#include <mp4ff.h>

#include "resource.h"
#include "in2.h"
#include "utils.h"
#include "config.h"
#include "aacinfo.h"
#include "aac2mp4.h"

const char *long_ext_list = "MP4\0MPEG-4 Files (*.MP4)\0M4A\0MPEG-4 Files (*.M4A)\0AAC\0AAC Files (*.AAC)\0";
const char *short_ext_list = "MP4\0MPEG-4 Files (*.MP4)\0M4A\0MPEG-4 Files (*.M4A)\0";


@@ 96,10 98,12 @@ typedef struct state
    __int64 last_offset;

    /* MP4 stuff */
    MP4FileHandle mp4file;
    mp4ff_t *mp4file;
    int mp4track;
    MP4SampleId numSamples;
    MP4SampleId sampleId;
    long numSamples;
    long sampleId;
    mp4ff_callback_t mp4cb;
    FILE *mp4File;

    /* AAC stuff */
    FILE *aacfile;


@@ 135,26 139,35 @@ DWORD WINAPI MP4PlayThread(void *b); // the decode thread procedure
DWORD WINAPI AACPlayThread(void *b); // the decode thread procedure


typedef struct tag
uint32_t read_callback(void *user_data, void *buffer, uint32_t length)
{
    char *item;
    char *value;
    size_t len;
} tag;
    return fread(buffer, 1, length, (FILE*)user_data);
}

uint32_t seek_callback(void *user_data, uint64_t position)
{
    return fseek((FILE*)user_data, position, SEEK_SET);
}

typedef struct medialib_tags
uint32_t write_callback(void *user_data, void *buffer, uint32_t length)
{
    struct tag *tags;
    unsigned int count;
} medialib_tags;
    return fwrite(buffer, 1, length, (FILE*)user_data);
}

uint32_t truncate_callback(void *user_data)
{
    _chsize(fileno((FILE*)user_data), ftell((FILE*)user_data));
    return 1;
}


int tag_add_field(medialib_tags *tags, const char *item, const char *value, size_t v_len)
int tag_add_field(mp4ff_metadata_t *tags, const char *item, const char *value, size_t v_len)
{
    void *backup = (void *)tags->tags;

    if (!item || (item && !*item) || !value) return 0;

    tags->tags = (struct tag *)realloc(tags->tags, (tags->count+1) * sizeof(tag));
    tags->tags = (mp4ff_tag_t *)realloc(tags->tags, (tags->count+1) * sizeof(mp4ff_tag_t));
    if (!tags->tags) {
        if (backup) free(backup);
        return 0;


@@ 180,14 193,14 @@ int tag_add_field(medialib_tags *tags, const char *item, const char *value, size
        memcpy(tags->tags[tags->count].value, value, v_len);
        tags->tags[tags->count].item[i_len] = '\0';
        tags->tags[tags->count].value[v_len] = '\0';
        tags->tags[tags->count].len = v_len;
//        tags->tags[tags->count].len = v_len;

        tags->count++;
        return 1;
    }
}

int tag_set_field(medialib_tags *tags, const char *item, const char *value, size_t v_len)
int tag_set_field(mp4ff_metadata_t *tags, const char *item, const char *value, size_t v_len)
{
    unsigned int i;



@@ 209,7 222,7 @@ int tag_set_field(medialib_tags *tags, const char *item, const char *value, size

            memcpy(tags->tags[i].value, value, v_len);
            tags->tags[i].value[v_len] = '\0';
            tags->tags[i].len = v_len;
//            tags->tags[i].len = v_len;

            return 1;
        }


@@ 218,7 231,7 @@ int tag_set_field(medialib_tags *tags, const char *item, const char *value, size
    return tag_add_field(tags, item, value, v_len);
}

int tag_delete(medialib_tags *tags)
int tag_delete(mp4ff_metadata_t *tags)
{
    unsigned int i;



@@ 234,9 247,8 @@ int tag_delete(medialib_tags *tags)
    tags->count = 0;
}

int ReadMP4Tag(MP4FileHandle file, medialib_tags *tags)
int ReadMP4Tag(mp4ff_t *file, mp4ff_metadata_t *tags)
{
    unsigned __int32 valueSize;
    unsigned __int8 *pValue;
    char *pName;
    unsigned int i = 0;


@@ 244,195 256,62 @@ int ReadMP4Tag(MP4FileHandle file, medialib_tags *tags)
    do {
        pName = 0;
        pValue = 0;
        valueSize = 0;

        MP4GetMetadataByIndex(file, i, (const char **)&pName, &pValue, &valueSize);

        if (valueSize > 0)
        if (mp4ff_meta_get_by_index(file, i, (char **)&pName, &pValue))
        {
            char *val = (char *)malloc(valueSize+1);
            char *val = (char *)strdup(pValue);
            if (!val) return 0;
            memcpy(val, pValue, valueSize);
            val[valueSize] = '\0';

            if (pName[0] == '�')
            {
                if (memcmp(pName, "�nam", 4) == 0)
                {
                    tag_add_field(tags, "title", val, valueSize);
                    tag_add_field(tags, "title", val, strlen(val));
                } else if (memcmp(pName, "�ART", 4) == 0) {
                    tag_add_field(tags, "artist", val, valueSize);
                    tag_add_field(tags, "artist", val, strlen(val));
                } else if (memcmp(pName, "�wrt", 4) == 0) {
                    tag_add_field(tags, "writer", val, valueSize);
                    tag_add_field(tags, "writer", val, strlen(val));
                } else if (memcmp(pName, "�alb", 4) == 0) {
                    tag_add_field(tags, "album", val, valueSize);
                    tag_add_field(tags, "album", val, strlen(val));
                } else if (memcmp(pName, "�day", 4) == 0) {
                    tag_add_field(tags, "date", val, valueSize);
                    tag_add_field(tags, "date", val, strlen(val));
                } else if (memcmp(pName, "�too", 4) == 0) {
                    tag_add_field(tags, "tool", val, valueSize);
                    tag_add_field(tags, "tool", val, strlen(val));
                } else if (memcmp(pName, "�cmt", 4) == 0) {
                    tag_add_field(tags, "comment", val, valueSize);
                    tag_add_field(tags, "comment", val, strlen(val));
                } else if (memcmp(pName, "�gen", 4) == 0) {
                    tag_add_field(tags, "genre", val, valueSize);
                    tag_add_field(tags, "genre", val, strlen(val));
                } else {
                    tag_add_field(tags, pName, val, valueSize);
                    tag_add_field(tags, pName, val, strlen(val));
                }
            } else if (memcmp(pName, "covr", 4) == 0) {
                tag_add_field(tags, "cover", val, valueSize);
                tag_add_field(tags, "cover", val, strlen(val));
            } else if (memcmp(pName, "gnre", 4) == 0) {
                char *t=0;
                if (MP4GetMetadataGenre(file, &t))
                {
                    tag_add_field(tags, "genre", t, 0);
                }
                tag_add_field(tags, "genre", val, strlen(val));
            } else if (memcmp(pName, "trkn", 4) == 0) {
                unsigned __int16 trkn = 0, tot = 0;
                char t[200];
                if (MP4GetMetadataTrack(file, &trkn, &tot))
                {
                    if (tot > 0)
                        wsprintf(t, "%d/%d", trkn, tot);
                    else
                        wsprintf(t, "%d", trkn);
                    tag_add_field(tags, "tracknumber", t, 0);
                }
                tag_add_field(tags, "tracknumber", val, strlen(val));
            } else if (memcmp(pName, "disk", 4) == 0) {
                unsigned __int16 disk = 0, tot = 0;
                char t[200];
                if (MP4GetMetadataDisk(file, &disk, &tot))
                {
                    if (tot > 0)
                        wsprintf(t, "%d/%d", disk, tot);
                    else
                        wsprintf(t, "%d", disk);
                    tag_add_field(tags, "disc", t, 0);
                }
                tag_add_field(tags, "disc", val, strlen(val));
            } else if (memcmp(pName, "cpil", 4) == 0) {
                unsigned __int8 cpil = 0;
                char t[200];
                if (MP4GetMetadataCompilation(file, &cpil))
                {
                    wsprintf(t, "%d", cpil);
                    tag_add_field(tags, "compilation", t, 0);
                }
                tag_add_field(tags, "compilation", val, strlen(val));
            } else if (memcmp(pName, "tmpo", 4) == 0) {
                unsigned __int16 tempo = 0;
                char t[200];
                if (MP4GetMetadataTempo(file, &tempo))
                {
                    wsprintf(t, "%d BPM", tempo);
                    tag_add_field(tags, "tempo", t, 0);
                }
                tag_add_field(tags, "tempo", val, strlen(val));
            } else if (memcmp(pName, "NDFL", 4) == 0) {
                /* Removed */
            } else {
                tag_add_field(tags, pName, val, valueSize);
                tag_add_field(tags, pName, val, strlen(val));
            }

            free(val);
        }

        i++;
    } while (valueSize > 0);
    } while (pValue != NULL);

    return 1;
}

int mp4_set_metadata(MP4FileHandle file, const char *item, const char *val, size_t v_len)
{
    if (!item || (item && !*item) || !val) return 0;

    if (!stricmp(item, "track") || !stricmp(item, "tracknumber"))
    {
        unsigned __int16 trkn, tot;
        int t1 = 0, t2 = 0;
        sscanf(val, "%d/%d", &t1, &t2);
        trkn = t1, tot = t2;
        if (!trkn) return 1;
        if (MP4SetMetadataTrack(file, trkn, tot)) return 1;
    }
    else if (!stricmp(item, "disc") || !stricmp(item, "disknumber"))
    {
        unsigned __int16 disk, tot;
        int t1 = 0, t2 = 0;
        sscanf(val, "%d/%d", &t1, &t2);
        disk = t1, tot = t2;
        if (!disk) return 1;
        if (MP4SetMetadataDisk(file, disk, tot)) return 1;
    }
    else if (!stricmp(item, "compilation"))
    {
        unsigned __int8 cpil = atoi(val);
        if (!cpil) return 1;
        if (MP4SetMetadataCompilation(file, cpil)) return 1;
    }
    else if (!stricmp(item, "tempo"))
    {
        unsigned __int16 tempo = atoi(val);
        if (!tempo) return 1;
        if (MP4SetMetadataTempo(file, tempo)) return 1;
    }
    else if (!stricmp(item, "artist"))
    {
        if (MP4SetMetadataArtist(file, val)) return 1;
    }
    else if (!stricmp(item, "writer"))
    {
        if (MP4SetMetadataWriter(file, val)) return 1;
    }
    else if (!stricmp(item, "title"))
    {
        if (MP4SetMetadataName(file, val)) return 1;
    }
    else if (!stricmp(item, "album"))
    {
        if (MP4SetMetadataAlbum(file, val)) return 1;
    }
    else if (!stricmp(item, "date") || !stricmp(item, "year"))
    {
        if (MP4SetMetadataYear(file, val)) return 1;
    }
    else if (!stricmp(item, "comment"))
    {
        if (MP4SetMetadataComment(file, val)) return 1;
    }
    else if (!stricmp(item, "genre"))
    {
        if (MP4SetMetadataGenre(file, val)) return 1;
    }
    else if (!stricmp(item, "tool"))
    {
        if (MP4SetMetadataTool(file, val)) return 1;
    }
    else if (!stricmp(item, "cover"))
    {
        if (MP4SetMetadataCoverArt(file, val, v_len)) return 1;
    }
    else
    {
        if (MP4SetMetadataFreeForm(file, (char *)item, (u_int8_t *)val, (u_int32_t)v_len)) return 1;
    }

    return 0;
}

int WriteMP4Tag(MP4FileHandle file, const medialib_tags *tags)
{
    unsigned int i;

    for (i = 0; i < tags->count; i++)
    {
        const char *item = tags->tags[i].item;
        const char *value = tags->tags[i].value;
        size_t len = tags->tags[i].len;

        if (value && len > 0)
        {
            mp4_set_metadata(file, item, value, len);
        }
    }
}


#ifdef DEBUG_OUTPUT
void in_mp4_DebugOutput(char *message)


@@ 756,15 635,55 @@ UINT uGetDlgItemText(HWND hwnd, int id, char *str, int max)
    return len;
}

static void mp4fileinfo(mp4ff_t *mp4, char *info, size_t len)
{
    char *ot[6] = { "NULL", "MAIN AAC", "LC AAC", "SSR AAC", "LTP AAC", "HE AAC" };
    long samples;
    float f = 1024.0;
    float seconds;
    int track;

    mp4AudioSpecificConfig mp4ASC = {0};
    unsigned char *buffer = NULL;
    int buffer_size = 0;

    if ((track = GetAACTrack(mp4)) < 0)
    {
        info[0] = '\0';
        return;
    }

    samples = mp4ff_num_samples(mp4, track);

    mp4ff_get_decoder_config(mp4, track, &buffer, &buffer_size);
    if (buffer)
    {
        if (NeAACDecAudioSpecificConfig(buffer, buffer_size, &mp4ASC) >= 0)
        {
            if (mp4ASC.frameLengthFlag == 1) f = 960.0;
            if (mp4ASC.sbr_present_flag == 1) f *= 2;
        }
        free(buffer);
    }

    seconds = (float)samples*(float)(f-1.0)/(float)mp4ASC.samplingFrequency;

    wsprintf(info, "%s\t%d.%d secs, %d ch, %d Hz\n\n", ot[(mp4ASC.objectTypeIndex > 5)?0:mp4ASC.objectTypeIndex],
        (int)(seconds), (int)(seconds*1000.0 + 0.5) % 1000, mp4ASC.channelsConfiguration, mp4ASC.samplingFrequency);
}

BOOL CALLBACK mp4_info_dialog_proc(HWND hwndDlg, UINT message,
                                   WPARAM wParam, LPARAM lParam)
{
    char *file_info;
    MP4FileHandle file;
    char *pVal, dummy1[1024], dummy3;
    short dummy, dummy2;
    char file_info[1024];
    mp4ff_t *file;
    FILE *mp4File;
    mp4ff_callback_t mp4cb = {0};
    char *pVal;
    mp4ff_metadata_t tags;
    char dummy1[1024];
    char temp[1024];
    struct medialib_tags tags;
    int dummy, dummy2, dummy3;
    tags.count = 0;
    tags.tags = NULL;



@@ 781,87 700,85 @@ BOOL CALLBACK mp4_info_dialog_proc(HWND hwndDlg, UINT message,
        EnableWindow(GetDlgItem(hwndDlg,IDC_CONVERT2), FALSE);
        ShowWindow(GetDlgItem(hwndDlg,IDC_CONVERT2), SW_HIDE);

        file = MP4Read(info_fn, 0);
        mp4File = fopen(info_fn, "rb");
        mp4cb.read = read_callback;
        mp4cb.seek = seek_callback;
        mp4cb.user_data = mp4File;


        if (file == MP4_INVALID_FILE_HANDLE)
        file = mp4ff_open_read(&mp4cb);
        if (file == NULL)
            return FALSE;

        file_info = MP4Info(file, MP4_INVALID_TRACK_ID);
        mp4fileinfo(file, file_info, 1024);
        SetDlgItemText(hwndDlg, IDC_INFOTEXT, file_info);
        free(file_info);

        /* get Metadata */

        pVal = NULL;
        if (MP4GetMetadataName(file, &pVal))
        if (mp4ff_meta_get_title(file, &pVal))
            uSetDlgItemText(hwndDlg,IDC_METANAME, pVal);

        pVal = NULL;
        if (MP4GetMetadataArtist(file, &pVal))
        if (mp4ff_meta_get_artist(file, &pVal))
            uSetDlgItemText(hwndDlg,IDC_METAARTIST, pVal);

        pVal = NULL;
        if (MP4GetMetadataWriter(file, &pVal))
        if (mp4ff_meta_get_writer(file, &pVal))
            uSetDlgItemText(hwndDlg,IDC_METAWRITER, pVal);

        pVal = NULL;
        if (MP4GetMetadataComment(file, &pVal))
        if (mp4ff_meta_get_comment(file, &pVal))
            uSetDlgItemText(hwndDlg,IDC_METACOMMENTS, pVal);

        pVal = NULL;
        if (MP4GetMetadataAlbum(file, &pVal))
        if (mp4ff_meta_get_album(file, &pVal))
            uSetDlgItemText(hwndDlg,IDC_METAALBUM, pVal);

        pVal = NULL;
        if (MP4GetMetadataGenre(file, &pVal))
        if (mp4ff_meta_get_genre(file, &pVal))
            uSetDlgItemText(hwndDlg,IDC_METAGENRE, pVal);

        dummy = 0;
        MP4GetMetadataTempo(file, &dummy);
        if (dummy)
        pVal = NULL;
        if (mp4ff_meta_get_track(file, &pVal))
        {
            wsprintf(dummy1, "%d", dummy);
            SetDlgItemText(hwndDlg,IDC_METATEMPO, dummy1);
        }
            SetDlgItemText(hwndDlg,IDC_METATRACK1, pVal);

        dummy = 0; dummy2 = 0;
        MP4GetMetadataTrack(file, &dummy, &dummy2);
        if (dummy)
        {
            wsprintf(dummy1, "%d", dummy);
            SetDlgItemText(hwndDlg,IDC_METATRACK1, dummy1);
        }
        if (dummy2)
        {
            wsprintf(dummy1, "%d", dummy2);
            SetDlgItemText(hwndDlg,IDC_METATRACK2, dummy1);
            //pVal = NULL;
            //mp4ff_meta_get_totaltracks(file, &pVal);
            //SetDlgItemText(hwndDlg, IDC_METATRACK2, pVal);
        }

        dummy = 0; dummy2 = 0;
        MP4GetMetadataDisk(file, &dummy, &dummy2);
        if (dummy)
        {
            wsprintf(dummy1, "%d", dummy);
            SetDlgItemText(hwndDlg,IDC_METADISK1, dummy1);
        }
        if (dummy2)
        pVal = NULL;
        if (mp4ff_meta_get_disc(file, &pVal))
        {
            wsprintf(dummy1, "%d", dummy2);
            SetDlgItemText(hwndDlg,IDC_METADISK2, dummy1);
            SetDlgItemText(hwndDlg,IDC_METADISK1, pVal);

            //pVal = NULL;
            //mp4ff_meta_get_totaldiscs(file, &pVal);
            //SetDlgItemText(hwndDlg,IDC_METADISK2, pVal);
        }

        pVal = NULL;
        if (MP4GetMetadataYear(file, &pVal))
        if (mp4ff_meta_get_date(file, &pVal))
            uSetDlgItemText(hwndDlg,IDC_METAYEAR, pVal);

        dummy3 = 0;
        MP4GetMetadataCompilation(file, &dummy3);
        if (dummy3)
            SendMessage(GetDlgItem(hwndDlg, IDC_METACOMPILATION), BM_SETCHECK, BST_CHECKED, 0);
#if 0
        /* WERKT NIET */
#endif
        pVal = NULL;
        if (mp4ff_meta_get_compilation(file, &pVal))
        {
            if (strcmp(pVal, "1") == 0)
            {
                SendMessage(GetDlgItem(hwndDlg, IDC_METACOMPILATION), BM_SETCHECK, BST_CHECKED, 0);
            }
        }

        /* ! Metadata */

        MP4Close(file);
        mp4ff_close(file);
        fclose(mp4File);

        return TRUE;



@@ 883,74 800,75 @@ BOOL CALLBACK mp4_info_dialog_proc(HWND hwndDlg, UINT message,
            /* save Metadata changes */

            tag_delete(&tags);
            file = MP4Read(info_fn, 0);
            if (file != MP4_INVALID_FILE_HANDLE)
            {
                ReadMP4Tag(file, &tags);
                MP4Close(file);

                file = MP4Modify(info_fn, 0, 0);
                if (file != MP4_INVALID_FILE_HANDLE)
                {
                    MP4MetadataDelete(file);
                    MP4Close(file);
                }
            }
            mp4File = fopen(info_fn, "rb");
            mp4cb.read = read_callback;
            mp4cb.seek = seek_callback;
            mp4cb.write = write_callback;
            mp4cb.truncate = truncate_callback;
            mp4cb.user_data = mp4File;


            file = MP4Modify(info_fn, 0, 0);
            if (file == MP4_INVALID_FILE_HANDLE)
            file = mp4ff_open_read(&mp4cb);
            if (file != NULL)
            {
                tag_delete(&tags);
                EndDialog(hwndDlg, wParam);
                return FALSE;
                ReadMP4Tag(file, &tags);
                mp4ff_close(file);
                fclose(mp4File);
            }

            mp4File = fopen(info_fn, "rb+");
            mp4cb.read = read_callback;
            mp4cb.seek = seek_callback;
            mp4cb.write = write_callback;
            mp4cb.truncate = truncate_callback;
            mp4cb.user_data = mp4File;


            uGetDlgItemText(hwndDlg, IDC_METANAME, dummy1, 1024);
            tag_set_field(&tags, "title", dummy1, 0);
            tag_set_field(&tags, "title", dummy1, strlen(dummy1));

            uGetDlgItemText(hwndDlg, IDC_METAWRITER, dummy1, 1024);
            tag_set_field(&tags, "writer", dummy1, 0);
            tag_set_field(&tags, "writer", dummy1, strlen(dummy1));

            uGetDlgItemText(hwndDlg, IDC_METAARTIST, dummy1, 1024);
            tag_set_field(&tags, "artist", dummy1, 0);
            tag_set_field(&tags, "artist", dummy1, strlen(dummy1));

            uGetDlgItemText(hwndDlg, IDC_METAALBUM, dummy1, 1024);
            tag_set_field(&tags, "album", dummy1, 0);
            tag_set_field(&tags, "album", dummy1, strlen(dummy1));

            uGetDlgItemText(hwndDlg, IDC_METACOMMENTS, dummy1, 1024);
            tag_set_field(&tags, "comment", dummy1, 0);
            tag_set_field(&tags, "comment", dummy1, strlen(dummy1));

            uGetDlgItemText(hwndDlg, IDC_METAGENRE, dummy1, 1024);
            tag_set_field(&tags, "genre", dummy1, 0);
            tag_set_field(&tags, "genre", dummy1, strlen(dummy1));

            uGetDlgItemText(hwndDlg, IDC_METAYEAR, dummy1, 1024);
            tag_set_field(&tags, "year", dummy1, 0);
            tag_set_field(&tags, "year", dummy1, strlen(dummy1));

            GetDlgItemText(hwndDlg, IDC_METATRACK1, dummy1, 1024);
            dummy = atoi(dummy1);
            GetDlgItemText(hwndDlg, IDC_METATRACK2, dummy1, 1024);
            dummy2 = atoi(dummy1);
            wsprintf(temp, "%d/%d", dummy, dummy2);
            tag_set_field(&tags, "track", temp, 0);
            //GetDlgItemText(hwndDlg, IDC_METATRACK2, dummy1, 1024);
            //dummy2 = atoi(dummy1);
            //wsprintf(temp, "%d/%d", dummy, dummy2);
            wsprintf(temp, "%d", dummy);
            tag_set_field(&tags, "track", temp, strlen(dummy1));

            GetDlgItemText(hwndDlg, IDC_METADISK1, dummy1, 1024);
            dummy = atoi(dummy1);
            GetDlgItemText(hwndDlg, IDC_METADISK2, dummy1, 1024);
            dummy2 = atoi(dummy1);
            wsprintf(temp, "%d/%d", dummy, dummy2);
            tag_set_field(&tags, "disc", temp, 0);

            GetDlgItemText(hwndDlg, IDC_METATEMPO, dummy1, 1024);
            tag_set_field(&tags, "tempo", dummy1, 0);
            //GetDlgItemText(hwndDlg, IDC_METADISK2, dummy1, 1024);
            //dummy2 = atoi(dummy1);
            //wsprintf(temp, "%d/%d", dummy, dummy2);
            wsprintf(temp, "%d", dummy);
            tag_set_field(&tags, "disc", temp, strlen(dummy1));

            dummy3 = SendMessage(GetDlgItem(hwndDlg, IDC_METACOMPILATION), BM_GETCHECK, 0, 0);
            tag_set_field(&tags, "compilation", (dummy3 ? "1" : "0"), 0);
            tag_set_field(&tags, "compilation", (dummy3 ? "1" : "0"), 1);

            WriteMP4Tag(file, &tags);
            mp4ff_meta_update(&mp4cb, &tags);

            MP4Close(file);
            fclose(mp4File);

            MP4Optimize(info_fn, NULL, 0);
            /* ! */

            EndDialog(hwndDlg, wParam);


@@ 1011,11 929,10 @@ BOOL CALLBACK aac_info_dialog_proc(HWND hwndDlg, UINT message,
        ShowWindow(GetDlgItem(hwndDlg,IDC_METACOMMENTS), SW_HIDE);
        ShowWindow(GetDlgItem(hwndDlg,IDC_METAALBUM), SW_HIDE);
        ShowWindow(GetDlgItem(hwndDlg,IDC_METAGENRE), SW_HIDE);
        ShowWindow(GetDlgItem(hwndDlg,IDC_METATEMPO), SW_HIDE);
        ShowWindow(GetDlgItem(hwndDlg,IDC_METATRACK1), SW_HIDE);
        ShowWindow(GetDlgItem(hwndDlg,IDC_METATRACK2), SW_HIDE);
        //ShowWindow(GetDlgItem(hwndDlg,IDC_METATRACK2), SW_HIDE);
        ShowWindow(GetDlgItem(hwndDlg,IDC_METADISK1), SW_HIDE);
        ShowWindow(GetDlgItem(hwndDlg,IDC_METADISK2), SW_HIDE);
        //ShowWindow(GetDlgItem(hwndDlg,IDC_METADISK2), SW_HIDE);
        ShowWindow(GetDlgItem(hwndDlg,IDC_METAYEAR), SW_HIDE);
        ShowWindow(GetDlgItem(hwndDlg,IDC_METACOMPILATION), SW_HIDE);



@@ 1051,38 968,6 @@ BOOL CALLBACK aac_info_dialog_proc(HWND hwndDlg, UINT message,
    case WM_COMMAND:
        switch (LOWORD(wParam))
        {
        case IDC_CONVERT:
            {
                char mp4FileName[256];
                char *extension;
                OPENFILENAME ofn;

                lstrcpy(mp4FileName, info_fn);
                extension = strrchr(mp4FileName, '.');
                lstrcpy(extension, ".mp4");

                memset(&ofn, 0, sizeof(OPENFILENAME));
                ofn.lStructSize = sizeof(OPENFILENAME);
                ofn.hwndOwner = hwndDlg;
                ofn.hInstance = module.hDllInstance;
                ofn.nMaxFileTitle = 31;
                ofn.lpstrFile = (LPSTR)mp4FileName;
                ofn.nMaxFile = _MAX_PATH;
                ofn.lpstrFilter = "MP4 Files (*.mp4)\0*.mp4\0";
                ofn.lpstrDefExt = "mp4";
                ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY;
                ofn.lpstrTitle = "Select Output File";

                if (GetSaveFileName(&ofn))
                {
                    if (covert_aac_to_mp4(info_fn, mp4FileName))
                    {
                        MessageBox(hwndDlg, "An error occured while converting AAC to MP4!", "An error occured!", MB_OK);
                        return FALSE;
                    }
                }
                return TRUE;
            }
        case IDCANCEL:
        case IDOK:
            EndDialog(hwndDlg, wParam);


@@ 1111,7 996,7 @@ int infoDlg(char *fn, HWND hwndParent)
}

/* Get the title from the file */
void ConstructTitle(MP4FileHandle file, char *filename, char *title, char *format)
void ConstructTitle(mp4ff_t *file, char *filename, char *title, char *format)
{
    char temp[4096];
    int some_info = 0;


@@ 1138,17 1023,17 @@ void ConstructTitle(MP4FileHandle file, char *filename, char *title, char *forma
        switch (*in++)
        {
        case '0':
            dummy = 0; dummy2 = 0;
            if (MP4GetMetadataTrack(file, &dummy, &dummy2))
            pVal = NULL;
            if (mp4ff_meta_get_track(file, &pVal))
            {
                out += wsprintf(out, "%d", (int)dummy);
                out += wsprintf(out, "%s", pVal);
                some_info = 1;
            }
            break;

        case '1':
            pVal = NULL;
            if (MP4GetMetadataArtist(file, &pVal))
            if (mp4ff_meta_get_artist(file, &pVal))
            {
                out += wsprintf(out, "%s", pVal);
                some_info = 1;


@@ 1157,7 1042,7 @@ void ConstructTitle(MP4FileHandle file, char *filename, char *title, char *forma

        case '2':
            pVal = NULL;
            if (MP4GetMetadataName(file, &pVal))
            if (mp4ff_meta_get_title(file, &pVal))
            {
                out += wsprintf(out, "%s", pVal);
                some_info = 1;


@@ 1166,7 1051,7 @@ void ConstructTitle(MP4FileHandle file, char *filename, char *title, char *forma

        case '3':
            pVal = NULL;
            if (MP4GetMetadataAlbum(file, &pVal))
            if (mp4ff_meta_get_album(file, &pVal))
            {
                out += wsprintf(out, "%s", pVal);
                some_info = 1;


@@ 1175,7 1060,7 @@ void ConstructTitle(MP4FileHandle file, char *filename, char *title, char *forma

        case '4':
            pVal = NULL;
            if (MP4GetMetadataYear(file, &pVal))
            if (mp4ff_meta_get_date(file, &pVal))
            {
                out += wsprintf(out, "%s", pVal);
                some_info = 1;


@@ 1184,7 1069,7 @@ void ConstructTitle(MP4FileHandle file, char *filename, char *title, char *forma

        case '5':
            pVal = NULL;
            if (MP4GetMetadataComment(file, &pVal))
            if (mp4ff_meta_get_comment(file, &pVal))
            {
                out += wsprintf(out, "%s", pVal);
                some_info = 1;


@@ 1193,7 1078,7 @@ void ConstructTitle(MP4FileHandle file, char *filename, char *title, char *forma

        case '6':
            pVal = NULL;
            if (MP4GetMetadataGenre(file, &pVal))
            if (mp4ff_meta_get_genre(file, &pVal))
            {
                out += wsprintf(out, "%s", pVal);
                some_info = 1;


@@ 1461,6 1346,8 @@ int play(char *fn)
    unsigned char *buffer;
    int buffer_size;
    NeAACDecConfigurationPtr config;
    unsigned char header[8];
    FILE *hMP4File;

#ifdef DEBUG_OUTPUT
    in_mp4_DebugOutput("play");


@@ 1470,13 1357,16 @@ int play(char *fn)

    lstrcpy(mp4state.filename, fn);

    if (!(mp4state.mp4file = MP4Read(mp4state.filename, 0)))
    hMP4File = fopen(mp4state.filename, "rb");
    if (!hMP4File)
    {
        mp4state.filetype = 1;
    } else {
        MP4Close(mp4state.mp4file);
        mp4state.filetype = 0;
        return -1;
    }
    fread(header, 1, 8, hMP4File);
    fclose(hMP4File);
    mp4state.filetype = 1;
    if (header[4] == 'f' && header[5] == 't' && header[6] == 'y' && header[7] == 'p')
        mp4state.filetype = 0;

    if (mp4state.filetype)
    {


@@ 1640,7 1530,13 @@ int play(char *fn)
        config->downMatrix = m_downmix;
        NeAACDecSetConfiguration(mp4state.hDecoder, config);

        mp4state.mp4file = MP4Read(mp4state.filename, 0);
        mp4state.mp4File = fopen(mp4state.filename, "rb");
        mp4state.mp4cb.read = read_callback;
        mp4state.mp4cb.seek = seek_callback;
        mp4state.mp4cb.user_data = mp4state.mp4File;


        mp4state.mp4file = mp4ff_open_read(&mp4state.mp4cb);
        if (!mp4state.mp4file)
        {
            show_error(module.hMainWindow, "Unable to open file.");


@@ 1652,18 1548,20 @@ int play(char *fn)
        {
            show_error(module.hMainWindow, "Unsupported Audio track type.");
            NeAACDecClose(mp4state.hDecoder);
            MP4Close(mp4state.mp4file);
            mp4ff_close(mp4state.mp4file);
            fclose(mp4state.mp4File);
            return -1;
        }

        buffer = NULL;
        buffer_size = 0;
        MP4GetTrackESConfiguration(mp4state.mp4file, mp4state.mp4track,
        mp4ff_get_decoder_config(mp4state.mp4file, mp4state.mp4track,
            &buffer, &buffer_size);
        if (!buffer)
        {
            NeAACDecClose(mp4state.hDecoder);
            MP4Close(mp4state.mp4file);
            mp4ff_close(mp4state.mp4file);
            fclose(mp4state.mp4File);
            return -1;
        }



@@ 1672,7 1570,8 @@ int play(char *fn)
        {
            /* If some error initializing occured, skip the file */
            NeAACDecClose(mp4state.hDecoder);
            MP4Close(mp4state.mp4file);
            mp4ff_close(mp4state.mp4file);
            fclose(mp4state.mp4File);
            if (buffer) free (buffer);
            return -1;
        }


@@ 1681,7 1580,7 @@ int play(char *fn)
        {
            mp4AudioSpecificConfig mp4ASC;

            mp4state.timescale = MP4GetTrackTimeScale(mp4state.mp4file, mp4state.mp4track);
            mp4state.timescale = mp4ff_time_scale(mp4state.mp4file, mp4state.mp4track);
            mp4state.framesize = 1024;
            mp4state.useAacLength = 0;



@@ 1697,11 1596,10 @@ int play(char *fn)

        free(buffer);

        avg_bitrate = MP4GetTrackIntegerProperty(mp4state.mp4file, mp4state.mp4track,
            "mdia.minf.stbl.stsd.mp4a.esds.decConfigDescr.avgBitrate");
        avg_bitrate = mp4ff_get_avg_bitrate(mp4state.mp4file, mp4state.mp4track);

        mp4state.numSamples = MP4GetTrackNumberOfSamples(mp4state.mp4file, mp4state.mp4track);
        mp4state.sampleId = 1;
        mp4state.numSamples = mp4ff_num_samples(mp4state.mp4file, mp4state.mp4track);
        mp4state.sampleId = 0;

        module.is_seekable = 1;
    }


@@ 1712,8 1610,10 @@ int play(char *fn)
        NeAACDecClose(mp4state.hDecoder);
        if (mp4state.filetype)
            fclose(mp4state.aacfile);
        else
            MP4Close(mp4state.mp4file);
        else {
            mp4ff_close(mp4state.mp4file);
            fclose(mp4state.mp4File);
        }
        return -1;
    }



@@ 1728,8 1628,10 @@ int play(char *fn)
        NeAACDecClose(mp4state.hDecoder);
        if (mp4state.filetype)
            fclose(mp4state.aacfile);
        else
            MP4Close(mp4state.mp4file);
        else {
            mp4ff_close(mp4state.mp4file);
            fclose(mp4state.mp4File);
        }
        return -1;
    }



@@ 1765,7 1667,8 @@ int play(char *fn)
        {
            show_error(module.hMainWindow, "Cannot create playback thread");
            NeAACDecClose(mp4state.hDecoder);
            MP4Close(mp4state.mp4file);
            mp4ff_close(mp4state.mp4file);
            fclose(mp4state.mp4File);
            return -1;
        }
    }


@@ 1855,8 1758,10 @@ void stop()
    NeAACDecClose(mp4state.hDecoder);
    if (mp4state.filetype)
        fclose(mp4state.aacfile);
    else
        MP4Close(mp4state.mp4file);
    else {
        mp4ff_close(mp4state.mp4file);
        fclose(mp4state.mp4File);
    }

    module.outMod->Close();
    module.SAVSADeInit();


@@ 1871,25 1776,34 @@ int getsonglength(const char *fn)
    if(!stricmp(fn + strlen(fn) - 3,"MP4") || !stricmp(fn + strlen(fn) - 3,"M4A"))
    {
        int track;
        MP4Duration length;
        MP4FileHandle file;
        int64_t length;
        FILE *mp4File;
        mp4ff_t *file;
        mp4ff_callback_t mp4cb = {0};

        mp4File = fopen(fn, "rb");
        mp4cb.read = read_callback;
        mp4cb.seek = seek_callback;
        mp4cb.user_data = mp4File;


        file = MP4Read(fn, 0);
        if (!file)
        file = mp4ff_open_read(&mp4cb);
        if (file == NULL)
            return 0;

        if ((track = GetAACTrack(file)) < 0)
        {
            MP4Close(file);
            mp4ff_close(file);
            fclose(mp4File);
            return -1;
        }

        length = MP4GetTrackDuration(file, track);
        length = mp4ff_get_track_duration(file, track);

        msDuration = MP4ConvertFromTrackDuration(file, track,
            length, MP4_MSECS_TIME_SCALE);
        msDuration = (long)((float)length / (float)mp4ff_time_scale(file, track) + 0.5);

        MP4Close(file);
        mp4ff_close(file);
        fclose(mp4File);

        return msDuration;
    } else {


@@ 2001,17 1915,16 @@ int getlength()
    {
        int track;
        long msDuration;
        MP4Duration length;
        long length;

        if ((track = GetAACTrack(mp4state.mp4file)) < 0)
        {
            return -1;
        }

        length = MP4GetTrackDuration(mp4state.mp4file, track);
        length = mp4ff_get_track_duration(mp4state.mp4file, track);

        msDuration = MP4ConvertFromTrackDuration(mp4state.mp4file, track,
            length, MP4_MSECS_TIME_SCALE);
        msDuration = (long)(length*1000.0 / (float)mp4ff_time_scale(mp4state.mp4file, track) + 0.5);

        return msDuration;
    } else {


@@ 2060,17 1973,40 @@ void getfileinfo(char *filename, char *title, int *length_in_ms)

        if (title)
        {
            MP4FileHandle file = MP4_INVALID_FILE_HANDLE;
            if (!(file = MP4Read(filename, 0)))
            unsigned char header[8];
            FILE *hMP4File = fopen(filename, "rb");
            if (!hMP4File)
            {
                return;
            }
            fread(header, 1, 8, hMP4File);
            fclose(hMP4File);

            if (header[4] == 'f' && header[5] == 't' && header[6] == 'y' && header[7] == 'p')
            {
                FILE *mp4File;
                mp4ff_t *file;
                mp4ff_callback_t mp4cb = {0};

                mp4File = fopen(filename, "rb");
                mp4cb.read = read_callback;
                mp4cb.seek = seek_callback;
                mp4cb.user_data = mp4File;

                file = mp4ff_open_read(&mp4cb);
                if (file == NULL)
                    return;

                ConstructTitle(file, filename, title, titleformat);

                mp4ff_close(file);
                fclose(mp4File);
            } else {
                char *tmp2;
                char *tmp = PathFindFileName(filename);
                strcpy(title, tmp);
                tmp2 = strrchr(title, '.');
                tmp2[0] = '\0';
            } else {
                ConstructTitle(file, filename, title, titleformat);
                MP4Close(file);
            }
        }
    }


@@ 2180,13 2116,13 @@ DWORD WINAPI MP4PlayThread(void *b)
        /* seeking */
        if (mp4state.seek_needed != -1)
        {
            MP4Duration duration;
            int64_t duration;
            int32_t skip_samples = 0;

            module.outMod->Flush(mp4state.decode_pos_ms);
            duration = MP4ConvertToTrackDuration(mp4state.mp4file,
                mp4state.mp4track, mp4state.seek_needed, MP4_MSECS_TIME_SCALE);
            mp4state.sampleId = MP4GetSampleIdFromTime(mp4state.mp4file,
                mp4state.mp4track, duration, 0);
            duration = (int64_t)(mp4state.seek_needed/1000.0 * mp4state.samplerate + 0.5);
            mp4state.sampleId = mp4ff_find_sample_use_offsets(mp4state.mp4file,
                mp4state.mp4track, duration, &skip_samples);

            mp4state.decode_pos_ms = mp4state.seek_needed;
            mp4state.seek_needed = -1;


@@ 2214,7 2150,7 @@ DWORD WINAPI MP4PlayThread(void *b)

                /* for gapless decoding */
                char *buf;
                MP4Duration dur;
                long dur;
                unsigned int sample_count;
                unsigned int delay = 0;



@@ 2222,10 2158,10 @@ DWORD WINAPI MP4PlayThread(void *b)
                buffer = NULL;
                buffer_size = 0;

                rc = MP4ReadSample(mp4state.mp4file, mp4state.mp4track,
                    mp4state.sampleId++, &buffer, &buffer_size,
                    NULL, &dur, NULL, NULL);
                if (mp4state.sampleId-1 == 1) dur = 0;
                dur = mp4ff_get_sample_duration(mp4state.mp4file, mp4state.mp4track, mp4state.sampleId);
                rc = mp4ff_read_sample(mp4state.mp4file, mp4state.mp4track, mp4state.sampleId++, &buffer,  &buffer_size);

                if (mp4state.sampleId == 1) dur = 0;
                if (rc == 0 || buffer == NULL)
                {
                    mp4state.last_frame = 1;


@@ 2638,18 2574,17 @@ __declspec(dllexport) In_Module* winampGetInModule2()

/* new Media Library interface */

int mp4_get_metadata(MP4FileHandle file, const char *item, char *dest, int dlen)
int mp4_get_metadata(mp4ff_t *file, const char *item, char *dest, int dlen)
{
    char *pVal = NULL, dummy1[4096];
    short dummy = 0, dummy2 = 0;

    if (dlen < 1) return 0;

    if (!stricmp(item, "track") || !stricmp(item, "tracknumber"))
    {
        if (MP4GetMetadataTrack(file, &dummy, &dummy2))
        if (mp4ff_meta_get_track(file, &pVal))
        {
            wsprintf(dummy1, "%d", (int)dummy);
            wsprintf(dummy1, "%s", pVal);
            strncpy(dest, dummy1, dlen-1);
            dest[dlen-1] = '\0';
            return 1;


@@ 2657,9 2592,9 @@ int mp4_get_metadata(MP4FileHandle file, const char *item, char *dest, int dlen)
    }
    else if (!stricmp(item, "disc") || !stricmp(item, "disknumber"))
    {
        if (MP4GetMetadataDisk(file, &dummy, &dummy2))
        if (mp4ff_meta_get_disc(file, &pVal))
        {
            wsprintf(dummy1, "%d", (int)dummy);
            wsprintf(dummy1, "%s", pVal);
            strncpy(dest, dummy1, dlen-1);
            dest[dlen-1] = '\0';
            return 1;


@@ 2667,10 2602,10 @@ int mp4_get_metadata(MP4FileHandle file, const char *item, char *dest, int dlen)
    }
    else if (!stricmp(item, "compilation"))
    {
        u_int8_t cpil = 0;
        if (MP4GetMetadataCompilation(file, &cpil))
        uint8_t cpil = 0;
        if (mp4ff_meta_get_compilation(file, &pVal))
        {
            wsprintf(dummy1, "%d", (int)cpil);
            wsprintf(dummy1, "%s", pVal);
            strncpy(dest, dummy1, dlen-1);
            dest[dlen-1] = '\0';
            return 1;


@@ 2678,10 2613,9 @@ int mp4_get_metadata(MP4FileHandle file, const char *item, char *dest, int dlen)
    }
    else if (!stricmp(item, "tempo"))
    {
        u_int16_t tempo = 0;
        if (MP4GetMetadataTempo(file, &tempo))
        if (mp4ff_meta_get_tempo(file, &pVal))
        {
            wsprintf(dummy1, "%d", (int)tempo);
            wsprintf(dummy1, "%s", pVal);
            strncpy(dest, dummy1, dlen-1);
            dest[dlen-1] = '\0';
            return 1;


@@ 2689,7 2623,7 @@ int mp4_get_metadata(MP4FileHandle file, const char *item, char *dest, int dlen)
    }
    else if (!stricmp(item, "artist"))
    {
        if (MP4GetMetadataArtist(file, &pVal))
        if (mp4ff_meta_get_artist(file, &pVal))
        {
            strncpy(dest, pVal, dlen-1);
            dest[dlen-1] = '\0';


@@ 2698,7 2632,7 @@ int mp4_get_metadata(MP4FileHandle file, const char *item, char *dest, int dlen)
    }
    else if (!stricmp(item, "writer"))
    {
        if (MP4GetMetadataWriter(file, &pVal))
        if (mp4ff_meta_get_writer(file, &pVal))
        {
            strncpy(dest, pVal, dlen-1);
            dest[dlen-1] = '\0';


@@ 2707,7 2641,7 @@ int mp4_get_metadata(MP4FileHandle file, const char *item, char *dest, int dlen)
    }
    else if (!stricmp(item, "title"))
    {
        if (MP4GetMetadataName(file, &pVal))
        if (mp4ff_meta_get_title(file, &pVal))
        {
            strncpy(dest, pVal, dlen-1);
            dest[dlen-1] = '\0';


@@ 2716,7 2650,7 @@ int mp4_get_metadata(MP4FileHandle file, const char *item, char *dest, int dlen)
    }
    else if (!stricmp(item, "album"))
    {
        if (MP4GetMetadataAlbum(file, &pVal))
        if (mp4ff_meta_get_album(file, &pVal))
        {
            strncpy(dest, pVal, dlen-1);
            dest[dlen-1] = '\0';


@@ 2725,7 2659,7 @@ int mp4_get_metadata(MP4FileHandle file, const char *item, char *dest, int dlen)
    }
    else if (!stricmp(item, "date") || !stricmp(item, "year"))
    {
        if (MP4GetMetadataYear(file, &pVal))
        if (mp4ff_meta_get_date(file, &pVal))
        {
            strncpy(dest, pVal, dlen-1);
            dest[dlen-1] = '\0';


@@ 2734,7 2668,7 @@ int mp4_get_metadata(MP4FileHandle file, const char *item, char *dest, int dlen)
    }
    else if (!stricmp(item, "comment"))
    {
        if (MP4GetMetadataComment(file, &pVal))
        if (mp4ff_meta_get_comment(file, &pVal))
        {
            strncpy(dest, pVal, dlen-1);
            dest[dlen-1] = '\0';


@@ 2743,7 2677,7 @@ int mp4_get_metadata(MP4FileHandle file, const char *item, char *dest, int dlen)
    }
    else if (!stricmp(item, "genre"))
    {
        if (MP4GetMetadataGenre(file, &pVal))
        if (mp4ff_meta_get_genre(file, &pVal))
        {
            strncpy(dest, pVal, dlen-1);
            dest[dlen-1] = '\0';


@@ 2752,17 2686,18 @@ int mp4_get_metadata(MP4FileHandle file, const char *item, char *dest, int dlen)
    }
    else if (!stricmp(item, "tool"))
    {
        if (MP4GetMetadataTool(file, &pVal))
        if (mp4ff_meta_get_tool(file, &pVal))
        {
            strncpy(dest, pVal, dlen-1);
            dest[dlen-1] = '\0';
            return 1;
        }
    }
#if 0
    else
    {
        u_int32_t valueSize = 0;
        u_int8_t *pValue = NULL;
        uint32_t valueSize = 0;
        uint8_t *pValue = NULL;

        if (MP4GetMetadataFreeForm(file, (char *)item, &pValue, &valueSize))
        {


@@ 2772,6 2707,7 @@ int mp4_get_metadata(MP4FileHandle file, const char *item, char *dest, int dlen)
            return 1;
        }
    }
#endif

    return 0;
}


@@ 2793,8 2729,20 @@ __declspec(dllexport) int winampGetExtendedFileInfo(const char *fn, const char *
    else
    {
        char temp[2048], temp2[2048];
        MP4FileHandle file = MP4Read(fn, 0);
        if (file == MP4_INVALID_FILE_HANDLE) return 0;
        FILE *mp4File;
        mp4ff_callback_t mp4cb = {0};
        mp4ff_t *file;

        mp4File = fopen(fn, "rb");
        mp4cb.read = read_callback;
        mp4cb.seek = seek_callback;
        mp4cb.write = write_callback;
        mp4cb.truncate = truncate_callback;
        mp4cb.user_data = mp4File;


        file = mp4ff_open_read(&mp4cb);
        if (file == NULL) return 0;

        if (mp4_get_metadata(file, data, temp, sizeof(temp)))
        {


@@ 2804,13 2752,14 @@ __declspec(dllexport) int winampGetExtendedFileInfo(const char *fn, const char *
            dest[len] = '\0';
        }

        MP4Close(file);
        mp4ff_close(file);
        fclose(mp4File);
    }

    return 1;
}

static struct medialib_tags mltags = {0, 0};
static mp4ff_metadata_t mltags = {0, 0};
static BOOL medialib_init = FALSE;
static char medialib_lastfn[2048] = "";



@@ 2820,15 2769,27 @@ __declspec(dllexport) int winampSetExtendedFileInfo(const char *fn, const char *
    char *temp;

    if (!medialib_init || (medialib_init && stricmp(fn, medialib_lastfn))) {
        MP4FileHandle file;
        FILE *mp4File;
        mp4ff_callback_t mp4cb = {0};
        mp4ff_t *file;
        strcpy(medialib_lastfn, fn);

        if (medialib_init) tag_delete(&mltags);

        file = MP4Read(fn, 0);
        if (file == MP4_INVALID_FILE_HANDLE) return 0;
        mp4File = fopen(medialib_lastfn, "rb");
        mp4cb.read = read_callback;
        mp4cb.seek = seek_callback;
        mp4cb.user_data = mp4File;


        file = mp4ff_open_read(&mp4cb);
        if (file == NULL) return 0;

        ReadMP4Tag(file, &mltags);
        MP4Close(file);

        mp4ff_close(file);
        fclose(mp4File);

        medialib_init = TRUE;
    }



@@ 2851,18 2812,19 @@ __declspec(dllexport) int winampWriteExtendedFileInfo()
{
    if (medialib_init)
    {
        MP4FileHandle file = MP4Modify(medialib_lastfn, 0, 0);
        if (file == MP4_INVALID_FILE_HANDLE) return 0;

        MP4MetadataDelete(file);
        MP4Close(file);
        FILE *mp4File;
        mp4ff_callback_t mp4cb = {0};

        file = MP4Modify(medialib_lastfn, 0, 0);
        if (file == MP4_INVALID_FILE_HANDLE) return 0;
        mp4File = fopen(medialib_lastfn, "rb+");
        mp4cb.read = read_callback;
        mp4cb.seek = seek_callback;
        mp4cb.write = write_callback;
        mp4cb.truncate = truncate_callback;
        mp4cb.user_data = mp4File;

        WriteMP4Tag(file, &mltags);
        mp4ff_meta_update(&mp4cb, &mltags);

        MP4Close(file);
        fclose(mp4File);

        return 1;
    }

M plugins/in_mp4/in_mp4.dsp => plugins/in_mp4/in_mp4.dsp +10 -6
@@ 43,7 43,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GX /O1 /I "..\..\include" /I "..\..\common\mp4v2" /I "..\..\common\mp4av" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GX /O1 /I "..\..\include" /I "..\..\common\mp4v2" /I "..\..\common\mp4av" /I "..\..\common\mp4ff" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x413 /d "NDEBUG"


@@ 69,7 69,7 @@ LINK32=xilink6.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\..\include" /I "..\..\common\mp4v2" /I "..\..\common\mp4av" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\..\include" /I "..\..\common\mp4v2" /I "..\..\common\mp4av" /I "..\..\common\mp4ff" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x413 /d "_DEBUG"


@@ 92,10 92,6 @@ LINK32=xilink6.exe
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File

SOURCE=.\aac2mp4.cpp
# End Source File
# Begin Source File

SOURCE=.\aacinfo.c
# End Source File
# Begin Source File


@@ 128,6 124,14 @@ SOURCE=.\in2.h
# End Source File
# Begin Source File

SOURCE=..\..\common\mp4ff\mp4ff.h
# End Source File
# Begin Source File

SOURCE=..\..\common\mp4ff\mp4ff_int_types.h
# End Source File
# Begin Source File

SOURCE=..\..\include\neaacdec.h
# End Source File
# Begin Source File

M plugins/in_mp4/in_mp4.dsw => plugins/in_mp4/in_mp4.dsw +2 -17
@@ 15,10 15,7 @@ Package=<4>
    Project_Dep_Name libfaad
    End Project Dependency
    Begin Project Dependency
    Project_Dep_Name libmp4v2_st
    End Project Dependency
    Begin Project Dependency
    Project_Dep_Name libmp4av_st
    Project_Dep_Name mp4ff
    End Project Dependency
}}}



@@ 36,19 33,7 @@ Package=<4>

###############################################################################

Project: "libmp4av_st"=..\..\common\mp4av\libmp4av_st.dsp - Package Owner=<4>

Package=<5>
{{{
}}}

Package=<4>
{{{
}}}

###############################################################################

Project: "libmp4v2_st"=..\..\common\mp4v2\libmp4v2_st60.dsp - Package Owner=<4>
Project: "mp4ff"=..\..\common\mp4ff\mp4ff.dsp - Package Owner=<4>

Package=<5>
{{{

M plugins/in_mp4/in_mp4.rc => plugins/in_mp4/in_mp4.rc +3 -13
@@ 63,23 63,16 @@ BEGIN
    EDITTEXT        IDC_METAWRITER,53,127,151,14,ES_AUTOHSCROLL
    EDITTEXT        IDC_METAALBUM,53,145,233,14,ES_AUTOHSCROLL
    EDITTEXT        IDC_METACOMMENTS,53,163,234,35,ES_AUTOHSCROLL
    EDITTEXT        IDC_METAGENRE,53,202,91,14,ES_AUTOHSCROLL
    EDITTEXT        IDC_METAGENRE,53,202,151,14,ES_AUTOHSCROLL
    EDITTEXT        IDC_METAYEAR,234,91,52,14,ES_AUTOHSCROLL
    EDITTEXT        IDC_METATRACK1,234,109,17,14,ES_AUTOHSCROLL
    EDITTEXT        IDC_METATRACK2,269,109,17,14,ES_AUTOHSCROLL
    EDITTEXT        IDC_METADISK1,234,127,17,14,ES_AUTOHSCROLL
    EDITTEXT        IDC_METADISK2,269,127,17,14,ES_AUTOHSCROLL
    EDITTEXT        IDC_METATEMPO,175,202,22,14,ES_AUTOHSCROLL
    EDITTEXT        IDC_METATRACK1,234,109,52,14,ES_AUTOHSCROLL
    EDITTEXT        IDC_METADISK1,234,127,52,14,ES_AUTOHSCROLL
    CONTROL         "Part of a compilation",IDC_METACOMPILATION,"Button",
                    BS_AUTOCHECKBOX | WS_TABSTOP,207,202,80,14
    DEFPUSHBUTTON   "OK",IDOK,246,234,50,14
    PUSHBUTTON      "Cancel",IDCANCEL,186,234,50,14
    PUSHBUTTON      "Convert Now!",IDC_CONVERT,111,166,81,14
    CTEXT           "You can convert this file to MP4 if you like. This does not involve re-encoding, only the container format is changed. Advantages of MP4 files are that they are playable by a lot more players and they will have a lot of support in the future.",
                    IDC_CONVERT1,45,103,214,36
    LTEXT           "",IDC_INFOTEXT,14,17,275,47,0,WS_EX_CLIENTEDGE
    GROUPBOX        "User data",IDC_USERDATA,7,76,289,151
    GROUPBOX        "Convert to MP4",IDC_CONVERT2,7,81,289,145
    LTEXT           "Name",IDC_STATIC1,13,91,20,14,SS_CENTERIMAGE
    LTEXT           "Artist",IDC_STATIC2,13,109,16,14,SS_CENTERIMAGE
    LTEXT           "Composer",IDC_STATIC3,13,127,32,14,SS_CENTERIMAGE


@@ 89,9 82,6 @@ BEGIN
    LTEXT           "Disc",IDC_STATIC9,211,127,15,14,SS_CENTERIMAGE
    LTEXT           "Track",IDC_STATIC8,211,109,20,14,SS_CENTERIMAGE
    LTEXT           "Genre",IDC_STATIC6,13,202,20,14,SS_CENTERIMAGE
    LTEXT           "BPM",IDC_STATIC12,153,202,16,14,SS_CENTERIMAGE
    LTEXT           "of",IDC_STATIC10,257,109,8,14,SS_CENTERIMAGE
    LTEXT           "of",IDC_STATIC11,257,127,8,14,SS_CENTERIMAGE
END

IDD_CONFIG DIALOG DISCARDABLE  0, 0, 233, 166

M plugins/in_mp4/utils.c => plugins/in_mp4/utils.c +19 -22
@@ 22,12 22,13 @@
** Commercial non-GPL licensing of this software is possible.
** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
**
** $Id: utils.c,v 1.7 2004/03/04 19:06:01 menno Exp $
** $Id: utils.c,v 1.8 2004/09/03 19:38:32 menno Exp $
**/

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <mp4.h>
//#include <mp4.h>
#include <mp4ff.h>
#include <neaacdec.h>
#include "utils.h"



@@ 47,34 48,28 @@ int StringComp(char const *str1, char const *str2, unsigned long len)
    return c1 - c2;
}

int GetAACTrack(MP4FileHandle infile)
int GetAACTrack(mp4ff_t *infile)
{
    /* find AAC track */
    int i, rc;
	int numTracks = MP4GetNumberOfTracks(infile, NULL, 0);
    int numTracks = mp4ff_total_tracks(infile);

	for (i = 0; i < numTracks; i++)
    for (i = 0; i < numTracks; i++)
    {
        MP4TrackId trackId = MP4FindTrackId(infile, i, NULL, 0);
        const char* trackType = MP4GetTrackType(infile, trackId);
        unsigned char *buff = NULL;
        int buff_size = 0;
        mp4AudioSpecificConfig mp4ASC;

        if (!strcmp(trackType, MP4_AUDIO_TRACK_TYPE))
        {
            unsigned char *buff = NULL;
            int buff_size = 0;
            mp4AudioSpecificConfig mp4ASC;
        mp4ff_get_decoder_config(infile, i, &buff, &buff_size);

            MP4GetTrackESConfiguration(infile, trackId, &buff, &buff_size);

            if (buff)
            {
                rc = AudioSpecificConfig(buff, buff_size, &mp4ASC);
                free(buff);
        if (buff)
        {
            rc = NeAACDecAudioSpecificConfig(buff, buff_size, &mp4ASC);
            free(buff);

                if (rc < 0)
                    return -1;
                return trackId;
            }
            if (rc < 0)
                continue;
            return i;
        }
    }



@@ 82,6 77,7 @@ int GetAACTrack(MP4FileHandle infile)
    return -1;
}

#if 0
int GetAudioTrack(MP4FileHandle infile)
{
    /* find AAC track */


@@ 123,6 119,7 @@ int GetVideoTrack(MP4FileHandle infile)
    /* can't decode this */
    return -1;
}
#endif

LPTSTR PathFindFileName(LPCTSTR pPath)
{

M plugins/in_mp4/utils.h => plugins/in_mp4/utils.h +6 -5
@@ 22,18 22,19 @@
** Commercial non-GPL licensing of this software is possible.
** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
**
** $Id: utils.h,v 1.3 2003/07/29 08:20:14 menno Exp $
** $Id: utils.h,v 1.4 2004/09/03 19:38:32 menno Exp $
**/

#ifndef UTILS_INCLUDED
#define UTILS_INCLUDED

#include <mp4.h>
//#include <mp4.h>
#include <mp4ff.h>

LPTSTR PathFindFileName(LPCTSTR pPath);
int GetVideoTrack(MP4FileHandle infile);
int GetAudioTrack(MP4FileHandle infile);
int GetAACTrack(MP4FileHandle infile);
//int GetVideoTrack(MP4FileHandle infile);
//int GetAudioTrack(MP4FileHandle infile);
int GetAACTrack(mp4ff_t *infile);
int StringComp(char const *str1, char const *str2, unsigned long len);
char *convert3in4to3in3(void *sample_buffer, int samples);